aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Hongwei Wang <hongweiw@google.com>2015-07-17 17:38:34 -0700
committerGravatar Hongwei Wang <hongweiw@google.com>2015-07-17 17:38:34 -0700
commitb307ae280b974a927cd1319ffd974c1dd90ec95d (patch)
treee38b428e51ec491cc7aac5a78925540092079131
parenteec3b9103baa784bbcd6be10d101ab53b1f169de (diff)
parentefccb3f5ce7cae89739d3a0474fcc0d6e2a5b12c (diff)
Merge branch 'master' into zookeeper
-rw-r--r--.gitignore6
-rw-r--r--.travis.yml3
-rw-r--r--BUILD30
-rw-r--r--Makefile1317
-rw-r--r--README.md4
-rw-r--r--build.json123
-rw-r--r--doc/connection-backoff.md57
-rw-r--r--doc/interop-test-descriptions.md96
-rw-r--r--gRPC.podspec7
-rw-r--r--include/grpc++/auth_context.h65
-rw-r--r--include/grpc++/auth_property_iterator.h77
-rw-r--r--include/grpc++/client_context.h10
-rw-r--r--include/grpc++/credentials.h6
-rw-r--r--include/grpc++/fixed_size_thread_pool.h (renamed from src/cpp/server/thread_pool.h)8
-rw-r--r--include/grpc++/impl/call.h141
-rw-r--r--include/grpc++/server.h4
-rw-r--r--include/grpc++/server_builder.h33
-rw-r--r--include/grpc++/server_context.h14
-rw-r--r--include/grpc++/stream.h26
-rw-r--r--include/grpc++/thread_pool_interface.h2
-rw-r--r--include/grpc/census.h4
-rw-r--r--include/grpc/grpc.h3
-rw-r--r--include/grpc/grpc_security.h22
-rw-r--r--include/grpc/support/port_platform.h2
-rw-r--r--include/grpc/support/time.h22
-rw-r--r--include/grpc/support/useful.h20
-rw-r--r--src/compiler/csharp_generator.cc50
-rw-r--r--src/compiler/objective_c_generator.cc78
-rw-r--r--src/core/census/grpc_context.c28
-rw-r--r--src/core/census/grpc_context.h19
-rw-r--r--src/core/census/initialize.c2
-rw-r--r--src/core/channel/census_filter.c10
-rw-r--r--src/core/channel/client_channel.c2
-rw-r--r--src/core/channel/http_client_filter.c18
-rw-r--r--src/core/channel/http_server_filter.c30
-rw-r--r--src/core/client_config/lb_policies/pick_first.h2
-rw-r--r--src/core/client_config/resolvers/zookeeper_resolver.c4
-rw-r--r--src/core/client_config/subchannel.c4
-rw-r--r--src/core/httpcli/httpcli.c1
-rw-r--r--src/core/httpcli/httpcli.h4
-rw-r--r--src/core/iomgr/alarm.h2
-rw-r--r--src/core/iomgr/iocp_windows.c1
-rw-r--r--src/core/iomgr/iomgr.c39
-rw-r--r--src/core/iomgr/pollset_multipoller_with_epoll.c3
-rw-r--r--src/core/iomgr/pollset_posix.c9
-rw-r--r--src/core/iomgr/pollset_set.h2
-rw-r--r--src/core/iomgr/pollset_windows.c6
-rw-r--r--src/core/iomgr/socket_windows.c35
-rw-r--r--src/core/iomgr/tcp_client_posix.c10
-rw-r--r--src/core/iomgr/tcp_client_windows.c3
-rw-r--r--src/core/iomgr/tcp_posix.c8
-rw-r--r--src/core/iomgr/tcp_server_windows.c80
-rw-r--r--src/core/iomgr/tcp_windows.c24
-rw-r--r--src/core/json/json.h2
-rw-r--r--src/core/profiling/timers_preciseclock.h2
-rw-r--r--src/core/security/client_auth_filter.c38
-rw-r--r--src/core/security/credentials.c169
-rw-r--r--src/core/security/credentials.h112
-rw-r--r--src/core/security/google_default_credentials.c89
-rw-r--r--src/core/security/json_token.c54
-rw-r--r--src/core/security/json_token.h15
-rw-r--r--src/core/security/jwt_verifier.c832
-rw-r--r--src/core/security/jwt_verifier.h136
-rw-r--r--src/core/security/secure_endpoint.c8
-rw-r--r--src/core/security/secure_transport_setup.c29
-rw-r--r--src/core/security/secure_transport_setup.h2
-rw-r--r--src/core/security/security_context.c14
-rw-r--r--src/core/security/security_context.h8
-rw-r--r--src/core/security/server_secure_chttp2.c47
-rw-r--r--src/core/statistics/census_rpc_stats.c4
-rw-r--r--src/core/statistics/census_tracing.c16
-rw-r--r--src/core/statistics/window_stats.h6
-rw-r--r--src/core/support/cancellable.c4
-rw-r--r--src/core/support/log_linux.c13
-rw-r--r--src/core/support/log_posix.c2
-rw-r--r--src/core/support/log_win32.c2
-rw-r--r--src/core/support/slice.c7
-rw-r--r--src/core/support/stack_lockfree.c130
-rw-r--r--src/core/support/stack_lockfree.h50
-rw-r--r--src/core/support/string.c57
-rw-r--r--src/core/support/string.h15
-rw-r--r--src/core/support/sync_win32.c2
-rw-r--r--src/core/support/time_posix.c44
-rw-r--r--src/core/support/time_win32.c35
-rw-r--r--src/core/surface/byte_buffer_queue.c8
-rw-r--r--src/core/surface/byte_buffer_queue.h2
-rw-r--r--src/core/surface/call.c103
-rw-r--r--src/core/surface/call.h2
-rw-r--r--src/core/surface/call_log_batch.c4
-rw-r--r--src/core/surface/channel.c35
-rw-r--r--src/core/surface/completion_queue.c230
-rw-r--r--src/core/surface/completion_queue.h18
-rw-r--r--src/core/surface/init.c2
-rw-r--r--src/core/surface/secure_channel_create.c1
-rw-r--r--src/core/surface/server.c397
-rw-r--r--src/core/surface/version.c41
-rw-r--r--src/core/transport/chttp2/frame_data.c9
-rw-r--r--src/core/transport/chttp2/frame_window_update.c4
-rw-r--r--src/core/transport/chttp2/hpack_parser.c19
-rw-r--r--src/core/transport/chttp2/hpack_table.c6
-rw-r--r--src/core/transport/chttp2/incoming_metadata.c2
-rw-r--r--src/core/transport/chttp2/internal.h28
-rw-r--r--src/core/transport/chttp2/parsing.c16
-rw-r--r--src/core/transport/chttp2/stream_encoder.c29
-rw-r--r--src/core/transport/chttp2/stream_lists.c16
-rw-r--r--src/core/transport/chttp2/writing.c60
-rw-r--r--src/core/transport/chttp2_transport.c54
-rw-r--r--src/core/transport/metadata.c127
-rw-r--r--src/core/transport/metadata.h26
-rw-r--r--src/core/transport/stream_op.c6
-rw-r--r--src/core/transport/stream_op.h2
-rw-r--r--src/core/transport/transport.c2
-rw-r--r--src/core/transport/transport.h8
-rw-r--r--src/core/transport/transport_op_string.c13
-rw-r--r--src/cpp/client/channel.cc4
-rw-r--r--src/cpp/client/client_context.cc8
-rw-r--r--src/cpp/client/secure_credentials.cc7
-rw-r--r--src/cpp/common/auth_property_iterator.cc87
-rw-r--r--src/cpp/common/create_auth_context.h42
-rw-r--r--src/cpp/common/insecure_create_auth_context.cc45
-rw-r--r--src/cpp/common/secure_auth_context.cc96
-rw-r--r--src/cpp/common/secure_auth_context.h66
-rw-r--r--src/cpp/common/secure_create_auth_context.cc50
-rw-r--r--src/cpp/server/async_server_context.cc99
-rw-r--r--src/cpp/server/create_default_thread_pool.cc4
-rw-r--r--src/cpp/server/fixed_size_thread_pool.cc (renamed from src/cpp/server/thread_pool.cc)15
-rw-r--r--src/cpp/server/server.cc13
-rw-r--r--src/cpp/server/server_builder.cc20
-rw-r--r--src/cpp/server/server_context.cc16
-rw-r--r--src/csharp/Grpc.Auth/Grpc.Auth.csproj4
-rw-r--r--src/csharp/Grpc.Auth/Grpc.Auth.nuspec6
-rw-r--r--src/csharp/Grpc.Auth/OAuth2InterceptorFactory.cs8
-rw-r--r--src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs1
-rw-r--r--src/csharp/Grpc.Core.Tests/ClientServerTest.cs6
-rw-r--r--src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj5
-rw-r--r--src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs17
-rw-r--r--src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs10
-rw-r--r--src/csharp/Grpc.Core.Tests/PInvokeTest.cs12
-rw-r--r--src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs1
-rw-r--r--src/csharp/Grpc.Core.Tests/ServerTest.cs3
-rw-r--r--src/csharp/Grpc.Core/Calls.cs18
-rw-r--r--src/csharp/Grpc.Core/Channel.cs30
-rw-r--r--src/csharp/Grpc.Core/ClientBase.cs (renamed from src/csharp/Grpc.Core/Stub/AbstractStub.cs)41
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.csproj12
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.nuspec8
-rw-r--r--src/csharp/Grpc.Core/GrpcEnvironment.cs110
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCall.cs9
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCallServer.cs9
-rw-r--r--src/csharp/Grpc.Core/Internal/CallSafeHandle.cs30
-rw-r--r--src/csharp/Grpc.Core/Internal/CompletionRegistry.cs12
-rw-r--r--src/csharp/Grpc.Core/Internal/DebugStats.cs35
-rw-r--r--src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs8
-rw-r--r--src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs8
-rw-r--r--src/csharp/Grpc.Core/Internal/ServerCallHandler.cs26
-rw-r--r--src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs14
-rw-r--r--src/csharp/Grpc.Core/Metadata.cs177
-rw-r--r--src/csharp/Grpc.Core/Properties/AssemblyInfo.cs1
-rw-r--r--src/csharp/Grpc.Core/Server.cs17
-rw-r--r--src/csharp/Grpc.Core/Version.cs5
-rw-r--r--src/csharp/Grpc.Core/packages.config2
-rw-r--r--src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj7
-rw-r--r--src/csharp/Grpc.Examples.MathClient/MathClient.cs16
-rw-r--r--src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs1
-rw-r--r--src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj3
-rw-r--r--src/csharp/Grpc.Examples.MathServer/MathServer.cs2
-rw-r--r--src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs1
-rw-r--r--src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj3
-rw-r--r--src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs13
-rw-r--r--src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs1
-rw-r--r--src/csharp/Grpc.Examples/Grpc.Examples.csproj3
-rw-r--r--src/csharp/Grpc.Examples/MathExamples.cs26
-rw-r--r--src/csharp/Grpc.Examples/MathGrpc.cs58
-rw-r--r--src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs1
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/.gitignore2
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj82
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs97
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs107
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/Properties/AssemblyInfo.cs11
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/packages.config5
-rw-r--r--src/csharp/Grpc.HealthCheck/.gitignore2
-rw-r--r--src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj79
-rw-r--r--src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec28
-rw-r--r--src/csharp/Grpc.HealthCheck/Health.cs687
-rw-r--r--src/csharp/Grpc.HealthCheck/HealthGrpc.cs70
-rw-r--r--src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs132
-rw-r--r--src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs11
-rw-r--r--src/csharp/Grpc.HealthCheck/packages.config5
-rw-r--r--src/csharp/Grpc.HealthCheck/proto/health.proto (renamed from src/csharp/Grpc.Core/Stub/StubConfiguration.cs)50
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj3
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs1
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj3
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs1
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj10
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropClient.cs12
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs5
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropServer.cs2
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs1
-rw-r--r--src/csharp/Grpc.IntegrationTesting/TestGrpc.cs82
-rw-r--r--src/csharp/Grpc.IntegrationTesting/packages.config2
-rw-r--r--src/csharp/Grpc.Tools.nuspec4
-rw-r--r--src/csharp/Grpc.nuspec6
-rw-r--r--src/csharp/Grpc.sln65
-rw-r--r--src/csharp/build_packages.bat15
-rw-r--r--src/csharp/ext/grpc_csharp_ext.c2
-rwxr-xr-xsrc/csharp/generate_proto_csharp.sh9
-rw-r--r--src/node/binding.gyp57
-rw-r--r--src/node/health_check/health.js70
-rw-r--r--src/node/health_check/health.proto50
-rw-r--r--src/node/package.json4
-rw-r--r--src/node/src/server.js9
-rw-r--r--src/node/test/health_test.js103
-rw-r--r--src/node/test/surface_test.js42
-rw-r--r--src/objective-c/GRPCClient/GRPCCall.h4
-rw-r--r--src/objective-c/GRPCClient/GRPCCall.m4
-rw-r--r--src/objective-c/GRPCClient/private/GRPCChannel.m2
-rw-r--r--src/objective-c/GRPCClient/private/GRPCDelegateWrapper.h5
-rw-r--r--src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m4
-rw-r--r--src/objective-c/ProtoRPC/ProtoRPC.h2
-rw-r--r--src/objective-c/ProtoRPC/ProtoRPC.m16
-rw-r--r--src/objective-c/ProtoRPC/ProtoService.h4
-rw-r--r--src/objective-c/ProtoRPC/ProtoService.m2
-rw-r--r--src/objective-c/RxLibrary/GRXBufferedPipe.h2
-rw-r--r--src/objective-c/RxLibrary/GRXForwardingWriter.h43
-rw-r--r--src/objective-c/RxLibrary/GRXForwardingWriter.m112
-rw-r--r--src/objective-c/RxLibrary/GRXImmediateWriter.h14
-rw-r--r--src/objective-c/RxLibrary/GRXImmediateWriter.m12
-rw-r--r--src/objective-c/RxLibrary/GRXWriter+Immediate.m12
-rw-r--r--src/objective-c/RxLibrary/GRXWriter.h11
-rw-r--r--src/objective-c/RxLibrary/GRXWriter.m76
-rw-r--r--src/objective-c/RxLibrary/transformations/GRXMappingWriter.h6
-rw-r--r--src/objective-c/RxLibrary/transformations/GRXMappingWriter.m6
-rw-r--r--src/objective-c/tests/GRPCClientTests.m12
-rw-r--r--src/objective-c/tests/InteropTests.m23
-rw-r--r--src/objective-c/tests/LocalClearTextTests.m6
-rw-r--r--src/objective-c/tests/Podfile1
-rwxr-xr-xsrc/php/bin/determine_extension_dir.sh12
-rwxr-xr-xsrc/php/bin/interop_client.sh2
-rwxr-xr-xsrc/php/bin/run_gen_code_test.sh6
-rwxr-xr-xsrc/php/bin/run_tests.sh2
-rw-r--r--src/php/ext/grpc/README.md4
-rw-r--r--src/php/ext/grpc/package.xml31
-rw-r--r--src/php/ext/grpc/timeval.c2
-rw-r--r--src/python/interop/setup.py2
-rw-r--r--src/python/src/.gitignore1
-rw-r--r--src/python/src/grpc/_adapter/.gitignore5
-rw-r--r--src/python/src/grpc/_cython/.gitignore7
-rw-r--r--src/python/src/grpc/_cython/README.rst52
-rw-r--r--src/python/src/grpc/_cython/__init__.py28
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/__init__.py28
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/call.pxd37
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/call.pyx82
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/channel.pxd36
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/channel.pyx84
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/completion_queue.pxd39
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/completion_queue.pyx117
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/credentials.pxd45
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/credentials.pyx217
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/grpc.pxd344
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/records.pxd129
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/records.pyx575
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/server.pxd45
-rw-r--r--src/python/src/grpc/_cython/_cygrpc/server.pyx158
-rw-r--r--src/python/src/grpc/_cython/adapter_low.py114
-rw-r--r--src/python/src/grpc/_cython/adapter_low_test.py187
-rw-r--r--src/python/src/grpc/_cython/cygrpc.pyx111
-rw-r--r--src/python/src/grpc/_cython/cygrpc_test.py276
-rw-r--r--src/python/src/grpc/_cython/test_utilities.py46
-rw-r--r--src/python/src/grpc/_links/__init__.py30
-rw-r--r--src/python/src/grpc/_links/_lonely_invocation_link_test.py88
-rw-r--r--src/python/src/grpc/_links/_proto_scenarios.py261
-rw-r--r--src/python/src/grpc/_links/_transmission_test.py226
-rw-r--r--src/python/src/grpc/_links/invocation.py363
-rw-r--r--src/python/src/grpc/_links/service.py402
-rw-r--r--src/python/src/grpc/framework/common/test_constants.py37
-rw-r--r--src/python/src/grpc/framework/common/test_control.py87
-rw-r--r--src/python/src/grpc/framework/common/test_coverage.py116
-rw-r--r--src/python/src/grpc/framework/foundation/relay.py175
-rw-r--r--src/python/src/grpc/framework/interfaces/__init__.py30
-rw-r--r--src/python/src/grpc/framework/interfaces/links/__init__.py30
-rw-r--r--src/python/src/grpc/framework/interfaces/links/links.py124
-rw-r--r--src/python/src/grpc/framework/interfaces/links/test_cases.py332
-rw-r--r--src/python/src/grpc/framework/interfaces/links/test_utilities.py66
-rw-r--r--src/python/src/grpc/framework/interfaces/links/utilities.py44
-rw-r--r--src/python/src/setup.py28
-rw-r--r--src/ruby/ext/grpc/extconf.rb75
-rw-r--r--src/ruby/ext/grpc/rb_completion_queue.c2
-rw-r--r--src/ruby/ext/grpc/rb_server.c6
-rwxr-xr-xsrc/ruby/grpc.gemspec2
-rw-r--r--src/ruby/lib/grpc/generic/rpc_server.rb10
-rw-r--r--src/ruby/lib/grpc/version.rb2
-rw-r--r--templates/Makefile.template164
-rw-r--r--templates/src/core/surface/version.c.template41
-rw-r--r--templates/vsprojects/Grpc.mak.template6
-rw-r--r--test/build/openssl-npn.c45
-rw-r--r--test/core/bad_client/bad_client.c4
-rw-r--r--test/core/client_config/uri_parser_test.c1
-rw-r--r--test/core/end2end/cq_verifier.c3
-rw-r--r--test/core/end2end/tests/request_response_with_payload_and_call_creds.c3
-rw-r--r--test/core/fling/client.c2
-rw-r--r--test/core/fling/server.c3
-rw-r--r--test/core/httpcli/httpcli_test.c3
-rw-r--r--test/core/iomgr/alarm_list_test.c16
-rw-r--r--test/core/iomgr/alarm_test.c4
-rw-r--r--test/core/iomgr/endpoint_tests.c6
-rw-r--r--test/core/iomgr/tcp_client_posix_test.c7
-rw-r--r--test/core/iomgr/tcp_server_posix_test.c4
-rw-r--r--test/core/network_benchmarks/low_level_ping_pong.c2
-rw-r--r--test/core/security/auth_context_test.c2
-rw-r--r--test/core/security/credentials_test.c93
-rw-r--r--test/core/security/jwt_verifier_test.c565
-rw-r--r--test/core/security/print_google_default_creds_token.c11
-rw-r--r--test/core/security/verify_jwt.c119
-rw-r--r--test/core/statistics/census_log_tests.c4
-rw-r--r--test/core/statistics/multiple_writers_circular_buffer_test.c2
-rw-r--r--test/core/statistics/multiple_writers_test.c2
-rw-r--r--test/core/statistics/performance_test.c2
-rw-r--r--test/core/statistics/quick_test.c2
-rw-r--r--test/core/statistics/small_log_test.c2
-rw-r--r--test/core/statistics/window_stats_test.c6
-rw-r--r--test/core/support/cancellable_test.c42
-rw-r--r--test/core/support/slice_test.c1
-rw-r--r--test/core/support/stack_lockfree_test.c154
-rw-r--r--test/core/support/string_test.c51
-rw-r--r--test/core/support/sync_test.c18
-rw-r--r--test/core/support/useful_test.c14
-rw-r--r--test/core/surface/completion_queue_test.c31
-rw-r--r--test/core/transport/chttp2/bin_encoder_test.c15
-rw-r--r--test/core/transport/chttp2/hpack_parser_test.c2
-rw-r--r--test/core/transport/chttp2/hpack_table_test.c2
-rw-r--r--test/core/transport/chttp2/stream_encoder_test.c10
-rw-r--r--test/core/transport/metadata_test.c38
-rw-r--r--test/core/tsi/transport_security_test.c8
-rw-r--r--test/core/util/grpc_profiler.c16
-rw-r--r--test/core/util/test_config.c38
-rw-r--r--test/core/util/test_config.h8
-rw-r--r--test/cpp/common/auth_property_iterator_test.cc101
-rw-r--r--test/cpp/common/secure_auth_context_test.cc123
-rw-r--r--test/cpp/end2end/client_crash_test.cc3
-rw-r--r--test/cpp/end2end/end2end_test.cc71
-rw-r--r--test/cpp/end2end/mock_test.cc8
-rw-r--r--test/cpp/end2end/server_crash_test.cc15
-rw-r--r--test/cpp/end2end/thread_stress_test.cc8
-rw-r--r--test/cpp/interop/client.cc5
-rw-r--r--test/cpp/interop/interop_client.cc21
-rw-r--r--test/cpp/interop/interop_client.h1
-rw-r--r--test/cpp/interop/server.cc12
-rw-r--r--test/cpp/interop/server_helper.cc13
-rw-r--r--test/cpp/interop/server_helper.h13
-rw-r--r--test/cpp/qps/driver.cc2
-rw-r--r--test/cpp/qps/qps_openloop_test.cc (renamed from test/cpp/qps/qps_test_openloop.cc)0
-rw-r--r--test/cpp/qps/server_async.cc2
-rw-r--r--test/cpp/qps/server_sync.cc4
-rw-r--r--test/cpp/qps/timer.cc2
-rw-r--r--test/cpp/qps/worker.cc3
-rw-r--r--test/cpp/server/fixed_size_thread_pool_test.cc (renamed from test/cpp/server/thread_pool_test.cc)10
-rw-r--r--test/cpp/util/cli_call_test.cc4
-rw-r--r--test/cpp/util/messages.proto2
-rwxr-xr-xtools/buildgen/generate_projects.py80
-rwxr-xr-xtools/buildgen/generate_projects.sh28
-rwxr-xr-xtools/distrib/python/submit.py6
-rw-r--r--tools/dockerfile/grpc_java/Dockerfile6
-rw-r--r--tools/dockerfile/grpc_java_android/Dockerfile27
-rw-r--r--tools/dockerfile/grpc_java_android/README.md10
-rw-r--r--tools/dockerfile/grpc_java_base/Dockerfile17
-rw-r--r--tools/doxygen/Doxyfile.c++3
-rw-r--r--tools/doxygen/Doxyfile.c++.internal11
-rw-r--r--tools/doxygen/Doxyfile.core.internal5
-rwxr-xr-xtools/jenkins/docker_run_jenkins.sh2
-rw-r--r--tools/jenkins/grpc_linuxbrew/Dockerfile62
-rwxr-xr-xtools/jenkins/run_distribution.sh55
-rwxr-xr-xtools/jenkins/run_jenkins.sh30
-rwxr-xr-xtools/run_tests/build_python.sh35
-rwxr-xr-xtools/run_tests/build_ruby.sh2
-rwxr-xr-xtools/run_tests/jobset.py8
-rwxr-xr-xtools/run_tests/python_tests.json102
-rw-r--r--tools/run_tests/run_csharp.bat5
-rwxr-xr-xtools/run_tests/run_python.sh4
-rwxr-xr-xtools/run_tests/run_tests.py56
-rw-r--r--tools/run_tests/sources_and_headers.json144
-rw-r--r--tools/run_tests/tests.json50
-rw-r--r--vsprojects/Grpc.mak29
-rw-r--r--vsprojects/README.md2
-rw-r--r--vsprojects/gpr/gpr.vcxproj3
-rw-r--r--vsprojects/gpr/gpr.vcxproj.filters6
-rw-r--r--vsprojects/grpc++/grpc++.vcxproj16
-rw-r--r--vsprojects/grpc++/grpc++.vcxproj.filters31
-rw-r--r--vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj11
-rw-r--r--vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters22
-rw-r--r--vsprojects/grpc/grpc.vcxproj5
-rw-r--r--vsprojects/grpc/grpc.vcxproj.filters9
-rw-r--r--vsprojects/grpc_unsecure/grpc_unsecure.vcxproj2
-rw-r--r--vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters3
-rw-r--r--vsprojects/nuget_package/grpc.native.csharp_ext.nuspec4
393 files changed, 14810 insertions, 2883 deletions
diff --git a/.gitignore b/.gitignore
index 9c9ae5abd4..89bd1003f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,8 +4,8 @@ gens
libs
objs
-# Python virtual environment (pre-3.4 only)
-python2.7_virtual_environment
+# Python virtual environments
+python*_virtual_environment
# gcov coverage data
coverage
@@ -31,3 +31,5 @@ coverage
# vim temp files
.*.swp
+# Makefile's cache
+cache.mk
diff --git a/.travis.yml b/.travis.yml
index 97cf99d71e..b6c8062985 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,8 @@ before_install:
- echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
- echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | sudo tee -a /etc/apt/sources.list.d/mono-xamarin.list
- sudo apt-get update -qq
- - sudo apt-get install -qq libgtest-dev libgflags-dev python-virtualenv clang-3.5
+ - sudo apt-get install -qq libgtest-dev libgflags-dev python-virtualenv python-dev python3-dev clang-3.5
+ - sudo pip install --upgrade virtualenv
- sudo pip install cpp-coveralls mako simplejson
- sudo apt-get install -qq mono-devel nunit
- wget www.nuget.org/NuGet.exe -O nuget.exe
diff --git a/BUILD b/BUILD
index 7c7a7052e9..0a29ba2131 100644
--- a/BUILD
+++ b/BUILD
@@ -47,6 +47,7 @@ cc_library(
"src/core/support/env.h",
"src/core/support/file.h",
"src/core/support/murmur_hash.h",
+ "src/core/support/stack_lockfree.h",
"src/core/support/string.h",
"src/core/support/string_win32.h",
"src/core/support/thd_internal.h",
@@ -73,6 +74,7 @@ cc_library(
"src/core/support/murmur_hash.c",
"src/core/support/slice.c",
"src/core/support/slice_buffer.c",
+ "src/core/support/stack_lockfree.c",
"src/core/support/string.c",
"src/core/support/string_posix.c",
"src/core/support/string_win32.c",
@@ -138,6 +140,7 @@ cc_library(
"src/core/security/base64.h",
"src/core/security/credentials.h",
"src/core/security/json_token.h",
+ "src/core/security/jwt_verifier.h",
"src/core/security/secure_endpoint.h",
"src/core/security/secure_transport_setup.h",
"src/core/security/security_connector.h",
@@ -254,6 +257,7 @@ cc_library(
"src/core/security/credentials_win32.c",
"src/core/security/google_default_credentials.c",
"src/core/security/json_token.c",
+ "src/core/security/jwt_verifier.c",
"src/core/security/secure_endpoint.c",
"src/core/security/secure_transport_setup.c",
"src/core/security/security_connector.c",
@@ -346,6 +350,7 @@ cc_library(
"src/core/surface/server_chttp2.c",
"src/core/surface/server_create.c",
"src/core/surface/surface_trace.c",
+ "src/core/surface/version.c",
"src/core/transport/chttp2/alpn.c",
"src/core/transport/chttp2/bin_encoder.c",
"src/core/transport/chttp2/frame_data.c",
@@ -576,6 +581,7 @@ cc_library(
"src/core/surface/server_chttp2.c",
"src/core/surface/server_create.c",
"src/core/surface/surface_trace.c",
+ "src/core/surface/version.c",
"src/core/transport/chttp2/alpn.c",
"src/core/transport/chttp2/bin_encoder.c",
"src/core/transport/chttp2/frame_data.c",
@@ -647,11 +653,15 @@ cc_library(
name = "grpc++",
srcs = [
"src/cpp/client/secure_credentials.h",
+ "src/cpp/common/secure_auth_context.h",
"src/cpp/server/secure_server_credentials.h",
"src/cpp/client/channel.h",
- "src/cpp/server/thread_pool.h",
+ "src/cpp/common/create_auth_context.h",
"src/cpp/client/secure_channel_arguments.cc",
"src/cpp/client/secure_credentials.cc",
+ "src/cpp/common/auth_property_iterator.cc",
+ "src/cpp/common/secure_auth_context.cc",
+ "src/cpp/common/secure_create_auth_context.cc",
"src/cpp/server/secure_server_credentials.cc",
"src/cpp/client/channel.cc",
"src/cpp/client/channel_arguments.cc",
@@ -667,12 +677,12 @@ cc_library(
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/async_generic_service.cc",
"src/cpp/server/create_default_thread_pool.cc",
+ "src/cpp/server/fixed_size_thread_pool.cc",
"src/cpp/server/insecure_server_credentials.cc",
"src/cpp/server/server.cc",
"src/cpp/server/server_builder.cc",
"src/cpp/server/server_context.cc",
"src/cpp/server/server_credentials.cc",
- "src/cpp/server/thread_pool.cc",
"src/cpp/util/byte_buffer.cc",
"src/cpp/util/slice.cc",
"src/cpp/util/status.cc",
@@ -681,6 +691,8 @@ cc_library(
hdrs = [
"include/grpc++/async_generic_service.h",
"include/grpc++/async_unary_call.h",
+ "include/grpc++/auth_context.h",
+ "include/grpc++/auth_property_iterator.h",
"include/grpc++/byte_buffer.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
@@ -690,6 +702,7 @@ cc_library(
"include/grpc++/config_protobuf.h",
"include/grpc++/create_channel.h",
"include/grpc++/credentials.h",
+ "include/grpc++/fixed_size_thread_pool.h",
"include/grpc++/generic_stub.h",
"include/grpc++/impl/call.h",
"include/grpc++/impl/client_unary_call.h",
@@ -733,7 +746,8 @@ cc_library(
name = "grpc++_unsecure",
srcs = [
"src/cpp/client/channel.h",
- "src/cpp/server/thread_pool.h",
+ "src/cpp/common/create_auth_context.h",
+ "src/cpp/common/insecure_create_auth_context.cc",
"src/cpp/client/channel.cc",
"src/cpp/client/channel_arguments.cc",
"src/cpp/client/client_context.cc",
@@ -748,12 +762,12 @@ cc_library(
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/async_generic_service.cc",
"src/cpp/server/create_default_thread_pool.cc",
+ "src/cpp/server/fixed_size_thread_pool.cc",
"src/cpp/server/insecure_server_credentials.cc",
"src/cpp/server/server.cc",
"src/cpp/server/server_builder.cc",
"src/cpp/server/server_context.cc",
"src/cpp/server/server_credentials.cc",
- "src/cpp/server/thread_pool.cc",
"src/cpp/util/byte_buffer.cc",
"src/cpp/util/slice.cc",
"src/cpp/util/status.cc",
@@ -762,6 +776,8 @@ cc_library(
hdrs = [
"include/grpc++/async_generic_service.h",
"include/grpc++/async_unary_call.h",
+ "include/grpc++/auth_context.h",
+ "include/grpc++/auth_property_iterator.h",
"include/grpc++/byte_buffer.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
@@ -771,6 +787,7 @@ cc_library(
"include/grpc++/config_protobuf.h",
"include/grpc++/create_channel.h",
"include/grpc++/credentials.h",
+ "include/grpc++/fixed_size_thread_pool.h",
"include/grpc++/generic_stub.h",
"include/grpc++/impl/call.h",
"include/grpc++/impl/client_unary_call.h",
@@ -891,6 +908,7 @@ objc_library(
"src/core/support/murmur_hash.c",
"src/core/support/slice.c",
"src/core/support/slice_buffer.c",
+ "src/core/support/stack_lockfree.c",
"src/core/support/string.c",
"src/core/support/string_posix.c",
"src/core/support/string_win32.c",
@@ -938,6 +956,7 @@ objc_library(
"src/core/support/env.h",
"src/core/support/file.h",
"src/core/support/murmur_hash.h",
+ "src/core/support/stack_lockfree.h",
"src/core/support/string.h",
"src/core/support/string_win32.h",
"src/core/support/thd_internal.h",
@@ -966,6 +985,7 @@ objc_library(
"src/core/security/credentials_win32.c",
"src/core/security/google_default_credentials.c",
"src/core/security/json_token.c",
+ "src/core/security/jwt_verifier.c",
"src/core/security/secure_endpoint.c",
"src/core/security/secure_transport_setup.c",
"src/core/security/security_connector.c",
@@ -1058,6 +1078,7 @@ objc_library(
"src/core/surface/server_chttp2.c",
"src/core/surface/server_create.c",
"src/core/surface/surface_trace.c",
+ "src/core/surface/version.c",
"src/core/transport/chttp2/alpn.c",
"src/core/transport/chttp2/bin_encoder.c",
"src/core/transport/chttp2/frame_data.c",
@@ -1103,6 +1124,7 @@ objc_library(
"src/core/security/base64.h",
"src/core/security/credentials.h",
"src/core/security/json_token.h",
+ "src/core/security/jwt_verifier.h",
"src/core/security/secure_endpoint.h",
"src/core/security/secure_transport_setup.h",
"src/core/security/security_connector.h",
diff --git a/Makefile b/Makefile
index 307bf62601..310a048161 100644
--- a/Makefile
+++ b/Makefile
@@ -215,6 +215,7 @@ endif
endif
INSTALL = install
RM = rm -f
+PKG_CONFIG = pkg-config
ifndef VALID_CONFIG_$(CONFIG)
$(error Invalid CONFIG value '$(CONFIG)')
@@ -331,9 +332,17 @@ HOST_LDLIBS = $(LDLIBS)
# These are automatically computed variables.
# There shouldn't be any need to change anything from now on.
-HAS_PKG_CONFIG = $(shell command -v pkg-config >/dev/null 2>&1 && echo true || echo false)
+-include cache.mk
-PC_TEMPLATE = prefix=$(prefix)\nexec_prefix=\$${prefix}\nincludedir=\$${prefix}/include\nlibdir=\$${exec_prefix}/lib\n\nName: $(PC_NAME)\nDescription: $(PC_DESCRIPTION)\nVersion: $(VERSION)\nCflags: -I\$${includedir} $(PC_CFLAGS)\nRequires.private: $(PC_REQUIRES_PRIVATE)\nLibs: -L\$${libdir}\nLibs.private: $(PC_LIBS_PRIVATE)
+CACHE_MK =
+
+HAS_PKG_CONFIG ?= $(shell command -v $(PKG_CONFIG) >/dev/null 2>&1 && echo true || echo false)
+
+ifeq ($(HAS_PKG_CONFIG), true)
+CACHE_MK += HAS_PKG_CONFIG = true,
+endif
+
+PC_TEMPLATE = prefix=$(prefix),exec_prefix=\$${prefix},includedir=\$${prefix}/include,libdir=\$${exec_prefix}/lib,,Name: $(PC_NAME),Description: $(PC_DESCRIPTION),Version: $(VERSION),Cflags: -I\$${includedir} $(PC_CFLAGS),Requires.private: $(PC_REQUIRES_PRIVATE),Libs: -L\$${libdir} $(PC_LIB),Libs.private: $(PC_LIBS_PRIVATE)
# gpr .pc file
PC_NAME = gRPC Portable Runtime
@@ -341,7 +350,8 @@ PC_DESCRIPTION = gRPC Portable Runtime
PC_CFLAGS = -pthread
PC_REQUIRES_PRIVATE =
PC_LIBS_PRIVATE = -lpthread
-ifeq ($(SYSTEM),Darwin)
+PC_LIB = -lgpr
+ifneq ($(SYSTEM),Darwin)
PC_LIBS_PRIVATE += -lrt
endif
GPR_PC_FILE := $(PC_TEMPLATE)
@@ -371,10 +381,10 @@ OPENSSL_REQUIRES_DL = true
endif
ifeq ($(HAS_PKG_CONFIG),true)
-OPENSSL_ALPN_CHECK_CMD = pkg-config --atleast-version=1.0.2 openssl
-ZLIB_CHECK_CMD = pkg-config --exists zlib
-PERFTOOLS_CHECK_CMD = pkg-config --exists profiler
-PROTOBUF_CHECK_CMD = pkg-config --atleast-version=3.0.0-alpha-3 protobuf
+OPENSSL_ALPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.2 openssl
+OPENSSL_NPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.1 openssl
+ZLIB_CHECK_CMD = $(PKG_CONFIG) --exists zlib
+PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.0.0-alpha-3 protobuf
else # HAS_PKG_CONFIG
ifeq ($(SYSTEM),MINGW32)
@@ -384,16 +394,19 @@ OPENSSL_LIBS = ssl crypto
endif
OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/openssl-alpn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
+OPENSSL_NPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/openssl-npn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS)
-PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/perftools.c -lprofiler $(LDFLAGS)
PROTOBUF_CHECK_CMD = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS)
ifeq ($(OPENSSL_REQUIRES_DL),true)
OPENSSL_ALPN_CHECK_CMD += -ldl
+OPENSSL_NPN_CHECK_CMD += -ldl
endif
endif # HAS_PKG_CONFIG
+PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/perftools.c -lprofiler $(LDFLAGS)
+
PROTOC_CHECK_CMD = which protoc > /dev/null
PROTOC_CHECK_VERSION_CMD = protoc --version | grep -q libprotoc.3
DTRACE_CHECK_CMD = which dtrace > /dev/null
@@ -401,28 +414,49 @@ SYSTEMTAP_HEADERS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/buil
ZOOKEEPER_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/zookeeper.c $(LDFLAGS) -lzookeeper_mt
ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
-HAS_SYSTEM_PERFTOOLS = $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false)
+HAS_SYSTEM_PERFTOOLS ?= $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_SYSTEM_PERFTOOLS),true)
DEFINES += GRPC_HAVE_PERFTOOLS
LIBS += profiler
+CACHE_MK += HAS_SYSTEM_PERFTOOLS = true,
endif
endif
HAS_SYSTEM_PROTOBUF_VERIFY = $(shell $(PROTOBUF_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
-HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
-HAS_SYSTEM_ZLIB = $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false)
-HAS_SYSTEM_PROTOBUF = $(HAS_SYSTEM_PROTOBUF_VERIFY)
+HAS_SYSTEM_OPENSSL_ALPN ?= $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
+ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true)
+HAS_SYSTEM_OPENSSL_NPN = true
+CACHE_MK += HAS_SYSTEM_OPENSSL_ALPN = true,
+else
+HAS_SYSTEM_OPENSSL_NPN ?= $(shell $(OPENSSL_NPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
+endif
+ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
+CACHE_MK += HAS_SYSTEM_OPENSSL_NPN = true,
+endif
+HAS_SYSTEM_ZLIB ?= $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false)
+ifeq ($(HAS_SYSTEM_ZLIB),true)
+CACHE_MK += HAS_SYSTEM_ZLIB = true,
+endif
+HAS_SYSTEM_PROTOBUF ?= $(HAS_SYSTEM_PROTOBUF_VERIFY)
+ifeq ($(HAS_SYSTEM_PROTOBUF),true)
+CACHE_MK += HAS_SYSTEM_PROTOBUF = true,
+endif
else
# override system libraries if the config requires a custom compiled library
HAS_SYSTEM_OPENSSL_ALPN = false
+HAS_SYSTEM_OPENSSL_NPN = false
HAS_SYSTEM_ZLIB = false
HAS_SYSTEM_PROTOBUF = false
endif
-HAS_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false)
+HAS_PROTOC ?= $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_PROTOC),true)
-HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_VERSION_CMD) 2> /dev/null && echo true || echo false)
+CACHE_MK += HAS_PROTOC = true,
+HAS_VALID_PROTOC ?= $(shell $(PROTOC_CHECK_VERSION_CMD) 2> /dev/null && echo true || echo false)
+ifeq ($(HAS_VALID_PROTOC),true)
+CACHE_MK += HAS_VALID_PROTOC = true,
+endif
else
HAS_VALID_PROTOC = false
endif
@@ -430,6 +464,7 @@ endif
# Check for Systemtap (https://sourceware.org/systemtap/), first by making sure <sys/sdt.h> is present
# in the system and secondly by checking for the "dtrace" binary (on Linux, this is part of the Systemtap
# distribution. It's part of the base system on BSD/Solaris machines).
+ifndef HAS_SYSTEMTAP
HAS_SYSTEMTAP_HEADERS = $(shell $(SYSTEMTAP_HEADERS_CHECK_CMD) 2> /dev/null && echo true || echo false)
HAS_DTRACE = $(shell $(DTRACE_CHECK_CMD) 2> /dev/null && echo true || echo false)
HAS_SYSTEMTAP = false
@@ -438,9 +473,17 @@ ifeq ($(HAS_DTRACE),true)
HAS_SYSTEMTAP = true
endif
endif
+endif
+
+ifeq ($(HAS_SYSTEMTAP),true)
+CACHE_MK += HAS_SYSTEMTAP = true,
+endif
HAS_ZOOKEEPER = $(shell $(ZOOKEEPER_CHECK_CMD) 2> /dev/null && echo true || echo false)
+# Note that for testing purposes, one can do:
+# make HAS_EMBEDDED_OPENSSL_ALPN=false
+# to emulate the fact we do not have OpenSSL in the third_party folder.
ifeq ($(wildcard third_party/openssl/ssl/ssl.h),)
HAS_EMBEDDED_OPENSSL_ALPN = false
else
@@ -475,8 +518,8 @@ DEP_MISSING += zlib
endif
else
ifeq ($(HAS_PKG_CONFIG),true)
-CPPFLAGS += $(shell pkg-config --cflags zlib)
-LDFLAGS += $(shell pkg-config --libs-only-L zlib)
+CPPFLAGS += $(shell $(PKG_CONFIG) --cflags zlib)
+LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L zlib)
PC_REQUIRES_GRPC += zlib
else
PC_LIBS_GRPC += -lz
@@ -492,11 +535,11 @@ ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true)
ifeq ($(HAS_PKG_CONFIG),true)
OPENSSL_PKG_CONFIG = true
PC_REQUIRES_SECURE = openssl
-CPPFLAGS := $(shell pkg-config --cflags openssl) $(CPPFLAGS)
-LDFLAGS_OPENSSL_PKG_CONFIG = $(shell pkg-config --libs-only-L openssl)
+CPPFLAGS := $(shell $(PKG_CONFIG) --cflags openssl) $(CPPFLAGS)
+LDFLAGS_OPENSSL_PKG_CONFIG = $(shell $(PKG_CONFIG) --libs-only-L openssl)
ifeq ($(SYSTEM),Linux)
ifneq ($(LDFLAGS_OPENSSL_PKG_CONFIG),)
-LDFLAGS_OPENSSL_PKG_CONFIG += $(shell pkg-config --libs-only-L openssl | sed s/L/Wl,-rpath,/)
+LDFLAGS_OPENSSL_PKG_CONFIG += $(shell $(PKG_CONFIG) --libs-only-L openssl | sed s/L/Wl,-rpath,/)
endif
endif
LDFLAGS := $(LDFLAGS_OPENSSL_PKG_CONFIG) $(LDFLAGS)
@@ -509,6 +552,7 @@ endif
endif
else
ifeq ($(HAS_EMBEDDED_OPENSSL_ALPN),true)
+USE_SYSTEM_OPENSSL = false
OPENSSL_DEP = $(LIBDIR)/$(CONFIG)/openssl/libssl.a
OPENSSL_MERGE_LIBS += $(LIBDIR)/$(CONFIG)/openssl/libssl.a $(LIBDIR)/$(CONFIG)/openssl/libcrypto.a
# need to prefix these to ensure overriding system libraries
@@ -518,12 +562,21 @@ ifeq ($(OPENSSL_REQUIRES_DL),true)
LIBS_SECURE = dl
endif
else
+ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
+USE_SYSTEM_OPENSSL = true
+CPPFLAGS += -DTSI_OPENSSL_ALPN_SUPPORT=0
+LIBS_SECURE = $(OPENSSL_LIBS)
+ifeq ($(OPENSSL_REQUIRES_DL),true)
+LIBS_SECURE += dl
+endif
+else
NO_SECURE = true
endif
endif
+endif
ifeq ($(OPENSSL_PKG_CONFIG),true)
-LDLIBS_SECURE += $(shell pkg-config --libs-only-l openssl)
+LDLIBS_SECURE += $(shell $(PKG_CONFIG) --libs-only-l openssl)
else
LDLIBS_SECURE += $(addprefix -l, $(LIBS_SECURE))
endif
@@ -534,6 +587,7 @@ PC_DESCRIPTION = high performance general RPC framework
PC_CFLAGS =
PC_REQUIRES_PRIVATE = $(PC_REQUIRES_GRPC) $(PC_REQUIRES_SECURE)
PC_LIBS_PRIVATE = $(PC_LIBS_GRPC) $(PC_LIBS_SECURE)
+PC_LIB = -lgrpc
GRPC_PC_FILE := $(PC_TEMPLATE)
# gprc_unsecure .pc file
@@ -542,6 +596,7 @@ PC_DESCRIPTION = high performance general RPC framework without SSL
PC_CFLAGS =
PC_REQUIRES_PRIVATE = $(PC_REQUIRES_GRPC)
PC_LIBS_PRIVATE = $(PC_LIBS_GRPC)
+PC_LIB = -lgrpc
GRPC_UNSECURE_PC_FILE := $(PC_TEMPLATE)
# gprc_zookeeper .pc file
@@ -561,11 +616,11 @@ ifeq ($(HAS_SYSTEM_PROTOBUF),true)
ifeq ($(HAS_PKG_CONFIG),true)
PROTOBUF_PKG_CONFIG = true
PC_REQUIRES_GRPCXX = protobuf
-CPPFLAGS := $(shell pkg-config --cflags protobuf) $(CPPFLAGS)
-LDFLAGS_PROTOBUF_PKG_CONFIG = $(shell pkg-config --libs-only-L protobuf)
+CPPFLAGS := $(shell $(PKG_CONFIG) --cflags protobuf) $(CPPFLAGS)
+LDFLAGS_PROTOBUF_PKG_CONFIG = $(shell $(PKG_CONFIG) --libs-only-L protobuf)
ifeq ($(SYSTEM),Linux)
ifneq ($(LDFLAGS_PROTOBUF_PKG_CONFIG),)
-LDFLAGS_PROTOBUF_PKG_CONFIG += $(shell pkg-config --libs-only-L protobuf | sed s/L/Wl,-rpath,/)
+LDFLAGS_PROTOBUF_PKG_CONFIG += $(shell $(PKG_CONFIG) --libs-only-L protobuf | sed s/L/Wl,-rpath,/)
endif
endif
else
@@ -588,7 +643,7 @@ LIBS_PROTOC = protoc protobuf
HOST_LDLIBS_PROTOC += $(addprefix -l, $(LIBS_PROTOC))
ifeq ($(PROTOBUF_PKG_CONFIG),true)
-LDLIBS_PROTOBUF += $(shell pkg-config --libs-only-l protobuf)
+LDLIBS_PROTOBUF += $(shell $(PKG_CONFIG) --libs-only-l protobuf)
else
LDLIBS_PROTOBUF += $(addprefix -l, $(LIBS_PROTOBUF))
endif
@@ -599,6 +654,7 @@ PC_DESCRIPTION = C++ wrapper for gRPC
PC_CFLAGS =
PC_REQUIRES_PRIVATE = grpc $(PC_REQUIRES_GRPCXX)
PC_LIBS_PRIVATE = $(PC_LIBS_GRPCXX)
+PC_LIB = -lgrpc++
GRPCXX_PC_FILE := $(PC_TEMPLATE)
# grpc++_unsecure .pc file
@@ -607,6 +663,7 @@ PC_DESCRIPTION = C++ wrapper for gRPC without SSL
PC_CFLAGS =
PC_REQUIRES_PRIVATE = grpc_unsecure $(PC_REQUIRES_GRPCXX)
PC_LIBS_PRIVATE = $(PC_LIBS_GRPCXX)
+PC_LIB = -lgrpc++
GRPCXX_UNSECURE_PC_FILE := $(PC_TEMPLATE)
ifeq ($(MAKECMDGOALS),clean)
@@ -667,7 +724,7 @@ openssl_dep_message:
@echo
@echo "DEPENDENCY ERROR"
@echo
- @echo "The target you are trying to run requires OpenSSL with ALPN support."
+ @echo "The target you are trying to run requires OpenSSL."
@echo "Your system doesn't have it, and neither does the third_party directory."
@echo
@echo "Please consult INSTALL to get more information."
@@ -744,6 +801,7 @@ gpr_host_port_test: $(BINDIR)/$(CONFIG)/gpr_host_port_test
gpr_log_test: $(BINDIR)/$(CONFIG)/gpr_log_test
gpr_slice_buffer_test: $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test
gpr_slice_test: $(BINDIR)/$(CONFIG)/gpr_slice_test
+gpr_stack_lockfree_test: $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test
gpr_string_test: $(BINDIR)/$(CONFIG)/gpr_string_test
gpr_sync_test: $(BINDIR)/$(CONFIG)/gpr_sync_test
gpr_thd_test: $(BINDIR)/$(CONFIG)/gpr_thd_test
@@ -759,9 +817,11 @@ grpc_create_jwt: $(BINDIR)/$(CONFIG)/grpc_create_jwt
grpc_credentials_test: $(BINDIR)/$(CONFIG)/grpc_credentials_test
grpc_fetch_oauth2: $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2
grpc_json_token_test: $(BINDIR)/$(CONFIG)/grpc_json_token_test
+grpc_jwt_verifier_test: $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test
grpc_print_google_default_creds_token: $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token
grpc_security_connector_test: $(BINDIR)/$(CONFIG)/grpc_security_connector_test
grpc_stream_op_test: $(BINDIR)/$(CONFIG)/grpc_stream_op_test
+grpc_verify_jwt: $(BINDIR)/$(CONFIG)/grpc_verify_jwt
hpack_parser_test: $(BINDIR)/$(CONFIG)/hpack_parser_test
hpack_table_test: $(BINDIR)/$(CONFIG)/hpack_table_test
httpcli_format_request_test: $(BINDIR)/$(CONFIG)/httpcli_format_request_test
@@ -794,6 +854,7 @@ uri_parser_test: $(BINDIR)/$(CONFIG)/uri_parser_test
async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test
async_streaming_ping_pong_test: $(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test
async_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test
+auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test
channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test
client_crash_test: $(BINDIR)/$(CONFIG)/client_crash_test
@@ -803,6 +864,7 @@ cxx_byte_buffer_test: $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test
cxx_slice_test: $(BINDIR)/$(CONFIG)/cxx_slice_test
cxx_time_test: $(BINDIR)/$(CONFIG)/cxx_time_test
end2end_test: $(BINDIR)/$(CONFIG)/end2end_test
+fixed_size_thread_pool_test: $(BINDIR)/$(CONFIG)/fixed_size_thread_pool_test
generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test
grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli
grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin
@@ -819,15 +881,15 @@ pubsub_publisher_test: $(BINDIR)/$(CONFIG)/pubsub_publisher_test
pubsub_subscriber_test: $(BINDIR)/$(CONFIG)/pubsub_subscriber_test
qps_driver: $(BINDIR)/$(CONFIG)/qps_driver
qps_interarrival_test: $(BINDIR)/$(CONFIG)/qps_interarrival_test
+qps_openloop_test: $(BINDIR)/$(CONFIG)/qps_openloop_test
qps_test: $(BINDIR)/$(CONFIG)/qps_test
-qps_test_openloop: $(BINDIR)/$(CONFIG)/qps_test_openloop
qps_worker: $(BINDIR)/$(CONFIG)/qps_worker
+secure_auth_context_test: $(BINDIR)/$(CONFIG)/secure_auth_context_test
server_crash_test: $(BINDIR)/$(CONFIG)/server_crash_test
server_crash_test_client: $(BINDIR)/$(CONFIG)/server_crash_test_client
status_test: $(BINDIR)/$(CONFIG)/status_test
sync_streaming_ping_pong_test: $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test
sync_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test
-thread_pool_test: $(BINDIR)/$(CONFIG)/thread_pool_test
thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test
chttp2_fake_security_bad_hostname_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test
chttp2_fake_security_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test
@@ -1308,6 +1370,7 @@ initial_settings_frame_bad_client_test: $(BINDIR)/$(CONFIG)/initial_settings_fra
run_dep_checks:
$(OPENSSL_ALPN_CHECK_CMD) || true
+ $(OPENSSL_NPN_CHECK_CMD) || true
$(ZLIB_CHECK_CMD) || true
$(PERFTOOLS_CHECK_CMD) || true
$(PROTOBUF_CHECK_CMD) || true
@@ -1329,7 +1392,7 @@ ifeq ($(SYSTEM),Darwin)
else
ifeq ($(SYSTEM),MINGW32)
@echo "We currently don't have a good way to compile OpenSSL in-place under msys."
- @echo "Please provide an ALPN-capable OpenSSL in your mingw32 system."
+ @echo "Please provide a OpenSSL in your mingw32 system."
@echo
@echo "Note that you can find a compatible version of the libraries here:"
@echo
@@ -1371,16 +1434,16 @@ $(LIBDIR)/$(CONFIG)/protobuf/libprotobuf.a: third_party/protobuf/configure
static: static_c static_cxx
-static_c: pc_c pc_c_unsecure pc_gpr pc_c_zookeeper $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a static_zookeeper_libs
+static_c: pc_c pc_c_unsecure cache.mk pc_gpr pc_c_zookeeper $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a static_zookeeper_libs
-static_cxx: pc_cxx pc_cxx_unsecure pc_gpr $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a
+static_cxx: pc_cxx pc_cxx_unsecure pc_gpr cache.mk $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a
shared: shared_c shared_cxx
-shared_c: pc_c pc_c_unsecure pc_gpr pc_c_zookeeper $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT) shared_zookeeper_libs
+shared_c: pc_c pc_c_unsecure pc_gpr cache.mk pc_c_zookeeper $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT) shared_zookeeper_libs
-shared_cxx: pc_cxx pc_cxx_unsecure $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.$(SHARED_EXT)
+shared_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.$(SHARED_EXT)
shared_csharp: shared_c $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT)
ifeq ($(HAS_ZOOKEEPER),true)
@@ -1421,9 +1484,9 @@ privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG
buildtests: buildtests_c buildtests_cxx
-buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alarm_heap_test $(BINDIR)/$(CONFIG)/alarm_list_test $(BINDIR)/$(CONFIG)/alarm_test $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/fd_conservation_posix_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cancellable_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_tls_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_auth_context_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_security_connector_test $(BINDIR)/$(CONFIG)/grpc_stream_op_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/multiple_server_queues_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/poll_kick_posix_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/time_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/timers_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/transport_security_test $(BINDIR)/$(CONFIG)/uri_parser_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test
+buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alarm_heap_test $(BINDIR)/$(CONFIG)/alarm_list_test $(BINDIR)/$(CONFIG)/alarm_test $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/fd_conservation_posix_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cancellable_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_tls_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_auth_context_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test $(BINDIR)/$(CONFIG)/grpc_security_connector_test $(BINDIR)/$(CONFIG)/grpc_stream_op_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/multiple_server_queues_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/poll_kick_posix_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/time_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/timers_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/transport_security_test $(BINDIR)/$(CONFIG)/uri_parser_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_flags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_server_finishes_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_flags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_server_finishes_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test
-buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/cli_call_test $(BINDIR)/$(CONFIG)/client_crash_test $(BINDIR)/$(CONFIG)/client_crash_test_server $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test $(BINDIR)/$(CONFIG)/cxx_slice_test $(BINDIR)/$(CONFIG)/cxx_time_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/generic_end2end_test $(BINDIR)/$(CONFIG)/grpc_cli $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/mock_test $(BINDIR)/$(CONFIG)/qps_interarrival_test $(BINDIR)/$(CONFIG)/qps_test $(BINDIR)/$(CONFIG)/qps_test_openloop $(BINDIR)/$(CONFIG)/server_crash_test $(BINDIR)/$(CONFIG)/server_crash_test_client $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test $(BINDIR)/$(CONFIG)/thread_pool_test $(BINDIR)/$(CONFIG)/thread_stress_test
+buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test $(BINDIR)/$(CONFIG)/auth_property_iterator_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/cli_call_test $(BINDIR)/$(CONFIG)/client_crash_test $(BINDIR)/$(CONFIG)/client_crash_test_server $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test $(BINDIR)/$(CONFIG)/cxx_slice_test $(BINDIR)/$(CONFIG)/cxx_time_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/fixed_size_thread_pool_test $(BINDIR)/$(CONFIG)/generic_end2end_test $(BINDIR)/$(CONFIG)/grpc_cli $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/mock_test $(BINDIR)/$(CONFIG)/qps_interarrival_test $(BINDIR)/$(CONFIG)/qps_openloop_test $(BINDIR)/$(CONFIG)/qps_test $(BINDIR)/$(CONFIG)/secure_auth_context_test $(BINDIR)/$(CONFIG)/server_crash_test $(BINDIR)/$(CONFIG)/server_crash_test_client $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test $(BINDIR)/$(CONFIG)/thread_stress_test
test: test_c test_cxx
@@ -1474,6 +1537,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test || ( echo test gpr_slice_buffer_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_slice_test"
$(Q) $(BINDIR)/$(CONFIG)/gpr_slice_test || ( echo test gpr_slice_test failed ; exit 1 )
+ $(E) "[RUN] Testing gpr_stack_lockfree_test"
+ $(Q) $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test || ( echo test gpr_stack_lockfree_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_string_test"
$(Q) $(BINDIR)/$(CONFIG)/gpr_string_test || ( echo test gpr_string_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_sync_test"
@@ -1500,6 +1565,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/grpc_credentials_test || ( echo test grpc_credentials_test failed ; exit 1 )
$(E) "[RUN] Testing grpc_json_token_test"
$(Q) $(BINDIR)/$(CONFIG)/grpc_json_token_test || ( echo test grpc_json_token_test failed ; exit 1 )
+ $(E) "[RUN] Testing grpc_jwt_verifier_test"
+ $(Q) $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test || ( echo test grpc_jwt_verifier_test failed ; exit 1 )
$(E) "[RUN] Testing grpc_security_connector_test"
$(Q) $(BINDIR)/$(CONFIG)/grpc_security_connector_test || ( echo test grpc_security_connector_test failed ; exit 1 )
$(E) "[RUN] Testing grpc_stream_op_test"
@@ -2522,6 +2589,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test || ( echo test async_streaming_ping_pong_test failed ; exit 1 )
$(E) "[RUN] Testing async_unary_ping_pong_test"
$(Q) $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test || ( echo test async_unary_ping_pong_test failed ; exit 1 )
+ $(E) "[RUN] Testing auth_property_iterator_test"
+ $(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 )
$(E) "[RUN] Testing channel_arguments_test"
$(Q) $(BINDIR)/$(CONFIG)/channel_arguments_test || ( echo test channel_arguments_test failed ; exit 1 )
$(E) "[RUN] Testing cli_call_test"
@@ -2538,16 +2607,20 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/cxx_time_test || ( echo test cxx_time_test failed ; exit 1 )
$(E) "[RUN] Testing end2end_test"
$(Q) $(BINDIR)/$(CONFIG)/end2end_test || ( echo test end2end_test failed ; exit 1 )
+ $(E) "[RUN] Testing fixed_size_thread_pool_test"
+ $(Q) $(BINDIR)/$(CONFIG)/fixed_size_thread_pool_test || ( echo test fixed_size_thread_pool_test failed ; exit 1 )
$(E) "[RUN] Testing generic_end2end_test"
$(Q) $(BINDIR)/$(CONFIG)/generic_end2end_test || ( echo test generic_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing interop_test"
$(Q) $(BINDIR)/$(CONFIG)/interop_test || ( echo test interop_test failed ; exit 1 )
$(E) "[RUN] Testing mock_test"
$(Q) $(BINDIR)/$(CONFIG)/mock_test || ( echo test mock_test failed ; exit 1 )
+ $(E) "[RUN] Testing qps_openloop_test"
+ $(Q) $(BINDIR)/$(CONFIG)/qps_openloop_test || ( echo test qps_openloop_test failed ; exit 1 )
$(E) "[RUN] Testing qps_test"
$(Q) $(BINDIR)/$(CONFIG)/qps_test || ( echo test qps_test failed ; exit 1 )
- $(E) "[RUN] Testing qps_test_openloop"
- $(Q) $(BINDIR)/$(CONFIG)/qps_test_openloop || ( echo test qps_test_openloop failed ; exit 1 )
+ $(E) "[RUN] Testing secure_auth_context_test"
+ $(Q) $(BINDIR)/$(CONFIG)/secure_auth_context_test || ( echo test secure_auth_context_test failed ; exit 1 )
$(E) "[RUN] Testing server_crash_test"
$(Q) $(BINDIR)/$(CONFIG)/server_crash_test || ( echo test server_crash_test failed ; exit 1 )
$(E) "[RUN] Testing status_test"
@@ -2556,8 +2629,6 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test || ( echo test sync_streaming_ping_pong_test failed ; exit 1 )
$(E) "[RUN] Testing sync_unary_ping_pong_test"
$(Q) $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test || ( echo test sync_unary_ping_pong_test failed ; exit 1 )
- $(E) "[RUN] Testing thread_pool_test"
- $(Q) $(BINDIR)/$(CONFIG)/thread_pool_test || ( echo test thread_pool_test failed ; exit 1 )
$(E) "[RUN] Testing thread_stress_test"
$(Q) $(BINDIR)/$(CONFIG)/thread_stress_test || ( echo test thread_stress_test failed ; exit 1 )
@@ -2573,7 +2644,7 @@ test_python: static_c
tools: tools_c tools_cxx
-tools_c: privatelibs_c $(BINDIR)/$(CONFIG)/gen_hpack_tables $(BINDIR)/$(CONFIG)/grpc_create_jwt $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token
+tools_c: privatelibs_c $(BINDIR)/$(CONFIG)/gen_hpack_tables $(BINDIR)/$(CONFIG)/grpc_create_jwt $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token $(BINDIR)/$(CONFIG)/grpc_verify_jwt
tools_cxx: privatelibs_cxx
@@ -2643,20 +2714,24 @@ ifeq ($(CONFIG),opt)
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT)
endif
+cache.mk::
+ $(E) "[MAKE] Generating $@"
+ $(Q) echo "$(CACHE_MK)" | tr , '\n' >$@
+
$(LIBDIR)/$(CONFIG)/pkgconfig/gpr.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
- $(Q) echo -e "$(GPR_PC_FILE)" >$@
+ $(Q) echo "$(GPR_PC_FILE)" | tr , '\n' >$@
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
- $(Q) echo -e "$(GRPC_PC_FILE)" >$@
+ $(Q) echo "$(GRPC_PC_FILE)" | tr , '\n' >$@
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
- $(Q) echo -e "$(GRPC_UNSECURE_PC_FILE)" >$@
+ $(Q) echo "$(GRPC_UNSECURE_PC_FILE)" | tr , '\n' >$@
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc_zookeeper.pc:
$(E) "[MAKE] Generating $@"
@@ -2666,12 +2741,12 @@ $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_zookeeper.pc:
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
- $(Q) echo -e "$(GRPCXX_PC_FILE)" >$@
+ $(Q) echo "$(GRPCXX_PC_FILE)" | tr , '\n' >$@
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
- $(Q) echo -e "$(GRPCXX_UNSECURE_PC_FILE)" >$@
+ $(Q) echo "$(GRPCXX_UNSECURE_PC_FILE)" | tr , '\n' >$@
ifeq ($(NO_PROTOC),true)
$(GENDIR)/examples/pubsub/empty.pb.cc: protoc_dep_error
@@ -3109,7 +3184,7 @@ endif
clean:
$(E) "[CLEAN] Cleaning build directories."
- $(Q) $(RM) -rf $(OBJDIR) $(LIBDIR) $(BINDIR) $(GENDIR)
+ $(Q) $(RM) -rf $(OBJDIR) $(LIBDIR) $(BINDIR) $(GENDIR) cache.mk
# The various libraries
@@ -3139,6 +3214,7 @@ LIBGPR_SRC = \
src/core/support/murmur_hash.c \
src/core/support/slice.c \
src/core/support/slice_buffer.c \
+ src/core/support/stack_lockfree.c \
src/core/support/string.c \
src/core/support/string_posix.c \
src/core/support/string_win32.c \
@@ -3256,6 +3332,7 @@ LIBGRPC_SRC = \
src/core/security/credentials_win32.c \
src/core/security/google_default_credentials.c \
src/core/security/json_token.c \
+ src/core/security/jwt_verifier.c \
src/core/security/secure_endpoint.c \
src/core/security/secure_transport_setup.c \
src/core/security/security_connector.c \
@@ -3348,6 +3425,7 @@ LIBGRPC_SRC = \
src/core/surface/server_chttp2.c \
src/core/surface/server_create.c \
src/core/surface/surface_trace.c \
+ src/core/surface/version.c \
src/core/transport/chttp2/alpn.c \
src/core/transport/chttp2/bin_encoder.c \
src/core/transport/chttp2/frame_data.c \
@@ -3390,7 +3468,7 @@ LIBGRPC_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LI
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libgrpc.a: openssl_dep_error
@@ -3466,7 +3544,7 @@ LIBGRPC_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(bas
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libgrpc_test_util.a: openssl_dep_error
@@ -3608,6 +3686,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/surface/server_chttp2.c \
src/core/surface/server_create.c \
src/core/surface/surface_trace.c \
+ src/core/surface/version.c \
src/core/transport/chttp2/alpn.c \
src/core/transport/chttp2/bin_encoder.c \
src/core/transport/chttp2/frame_data.c \
@@ -3726,6 +3805,9 @@ endif
LIBGRPC++_SRC = \
src/cpp/client/secure_channel_arguments.cc \
src/cpp/client/secure_credentials.cc \
+ src/cpp/common/auth_property_iterator.cc \
+ src/cpp/common/secure_auth_context.cc \
+ src/cpp/common/secure_create_auth_context.cc \
src/cpp/server/secure_server_credentials.cc \
src/cpp/client/channel.cc \
src/cpp/client/channel_arguments.cc \
@@ -3741,12 +3823,12 @@ LIBGRPC++_SRC = \
src/cpp/proto/proto_utils.cc \
src/cpp/server/async_generic_service.cc \
src/cpp/server/create_default_thread_pool.cc \
+ src/cpp/server/fixed_size_thread_pool.cc \
src/cpp/server/insecure_server_credentials.cc \
src/cpp/server/server.cc \
src/cpp/server/server_builder.cc \
src/cpp/server/server_context.cc \
src/cpp/server/server_credentials.cc \
- src/cpp/server/thread_pool.cc \
src/cpp/util/byte_buffer.cc \
src/cpp/util/slice.cc \
src/cpp/util/status.cc \
@@ -3755,6 +3837,8 @@ LIBGRPC++_SRC = \
PUBLIC_HEADERS_CXX += \
include/grpc++/async_generic_service.h \
include/grpc++/async_unary_call.h \
+ include/grpc++/auth_context.h \
+ include/grpc++/auth_property_iterator.h \
include/grpc++/byte_buffer.h \
include/grpc++/channel_arguments.h \
include/grpc++/channel_interface.h \
@@ -3764,6 +3848,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/config_protobuf.h \
include/grpc++/create_channel.h \
include/grpc++/credentials.h \
+ include/grpc++/fixed_size_thread_pool.h \
include/grpc++/generic_stub.h \
include/grpc++/impl/call.h \
include/grpc++/impl/client_unary_call.h \
@@ -3795,7 +3880,7 @@ LIBGRPC++_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libgrpc++.a: openssl_dep_error
@@ -3869,7 +3954,7 @@ LIBGRPC++_TEST_CONFIG_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a: openssl_dep_error
@@ -3922,7 +4007,7 @@ LIBGRPC++_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(b
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a: openssl_dep_error
@@ -3966,6 +4051,7 @@ $(OBJDIR)/$(CONFIG)/test/cpp/util/subprocess.o: $(GENDIR)/test/cpp/util/messages
LIBGRPC++_UNSECURE_SRC = \
+ src/cpp/common/insecure_create_auth_context.cc \
src/cpp/client/channel.cc \
src/cpp/client/channel_arguments.cc \
src/cpp/client/client_context.cc \
@@ -3980,12 +4066,12 @@ LIBGRPC++_UNSECURE_SRC = \
src/cpp/proto/proto_utils.cc \
src/cpp/server/async_generic_service.cc \
src/cpp/server/create_default_thread_pool.cc \
+ src/cpp/server/fixed_size_thread_pool.cc \
src/cpp/server/insecure_server_credentials.cc \
src/cpp/server/server.cc \
src/cpp/server/server_builder.cc \
src/cpp/server/server_context.cc \
src/cpp/server/server_credentials.cc \
- src/cpp/server/thread_pool.cc \
src/cpp/util/byte_buffer.cc \
src/cpp/util/slice.cc \
src/cpp/util/status.cc \
@@ -3994,6 +4080,8 @@ LIBGRPC++_UNSECURE_SRC = \
PUBLIC_HEADERS_CXX += \
include/grpc++/async_generic_service.h \
include/grpc++/async_unary_call.h \
+ include/grpc++/auth_context.h \
+ include/grpc++/auth_property_iterator.h \
include/grpc++/byte_buffer.h \
include/grpc++/channel_arguments.h \
include/grpc++/channel_interface.h \
@@ -4003,6 +4091,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/config_protobuf.h \
include/grpc++/create_channel.h \
include/grpc++/credentials.h \
+ include/grpc++/fixed_size_thread_pool.h \
include/grpc++/generic_stub.h \
include/grpc++/impl/call.h \
include/grpc++/impl/client_unary_call.h \
@@ -4128,7 +4217,7 @@ LIBINTEROP_CLIENT_HELPER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libinterop_client_helper.a: openssl_dep_error
@@ -4179,7 +4268,7 @@ LIBINTEROP_CLIENT_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o,
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libinterop_client_main.a: openssl_dep_error
@@ -4228,7 +4317,7 @@ LIBINTEROP_SERVER_HELPER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libinterop_server_helper.a: openssl_dep_error
@@ -4278,7 +4367,7 @@ LIBINTEROP_SERVER_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o,
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libinterop_server_main.a: openssl_dep_error
@@ -4330,7 +4419,7 @@ LIBPUBSUB_CLIENT_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libpubsub_client_lib.a: openssl_dep_error
@@ -4390,7 +4479,7 @@ LIBQPS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIB
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libqps.a: openssl_dep_error
@@ -4447,7 +4536,7 @@ LIBGRPC_CSHARP_EXT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(ba
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a: openssl_dep_error
@@ -4506,7 +4595,7 @@ LIBEND2END_FIXTURE_CHTTP2_FAKE_SECURITY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/,
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a: openssl_dep_error
@@ -4612,7 +4701,7 @@ LIBEND2END_FIXTURE_CHTTP2_SIMPLE_SSL_FULLSTACK_OBJS = $(addprefix $(OBJDIR)/$(CO
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a: openssl_dep_error
@@ -4649,7 +4738,7 @@ LIBEND2END_FIXTURE_CHTTP2_SIMPLE_SSL_FULLSTACK_WITH_POLL_OBJS = $(addprefix $(OB
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack_with_poll.a: openssl_dep_error
@@ -4686,7 +4775,7 @@ LIBEND2END_FIXTURE_CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_OBJS = $(addprefix $(
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a: openssl_dep_error
@@ -5275,7 +5364,7 @@ LIBEND2END_TEST_REQUEST_RESPONSE_WITH_PAYLOAD_AND_CALL_CREDS_OBJS = $(addprefix
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_payload_and_call_creds.a: openssl_dep_error
@@ -5498,7 +5587,7 @@ LIBEND2END_CERTS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(base
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libend2end_certs.a: openssl_dep_error
@@ -5535,7 +5624,7 @@ LIBBAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(ba
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libbad_client_test.a: openssl_dep_error
@@ -5574,7 +5663,7 @@ ALARM_HEAP_TEST_SRC = \
ALARM_HEAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALARM_HEAP_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/alarm_heap_test: openssl_dep_error
@@ -5603,7 +5692,7 @@ ALARM_LIST_TEST_SRC = \
ALARM_LIST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALARM_LIST_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/alarm_list_test: openssl_dep_error
@@ -5632,7 +5721,7 @@ ALARM_TEST_SRC = \
ALARM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALARM_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/alarm_test: openssl_dep_error
@@ -5661,7 +5750,7 @@ ALPN_TEST_SRC = \
ALPN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALPN_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/alpn_test: openssl_dep_error
@@ -5690,7 +5779,7 @@ BIN_ENCODER_TEST_SRC = \
BIN_ENCODER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BIN_ENCODER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/bin_encoder_test: openssl_dep_error
@@ -5719,7 +5808,7 @@ CHTTP2_STATUS_CONVERSION_TEST_SRC = \
CHTTP2_STATUS_CONVERSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_STATUS_CONVERSION_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_status_conversion_test: openssl_dep_error
@@ -5748,7 +5837,7 @@ CHTTP2_STREAM_ENCODER_TEST_SRC = \
CHTTP2_STREAM_ENCODER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_STREAM_ENCODER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test: openssl_dep_error
@@ -5777,7 +5866,7 @@ CHTTP2_STREAM_MAP_TEST_SRC = \
CHTTP2_STREAM_MAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_STREAM_MAP_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_stream_map_test: openssl_dep_error
@@ -5806,7 +5895,7 @@ DUALSTACK_SOCKET_TEST_SRC = \
DUALSTACK_SOCKET_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DUALSTACK_SOCKET_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/dualstack_socket_test: openssl_dep_error
@@ -5835,7 +5924,7 @@ FD_CONSERVATION_POSIX_TEST_SRC = \
FD_CONSERVATION_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FD_CONSERVATION_POSIX_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/fd_conservation_posix_test: openssl_dep_error
@@ -5864,7 +5953,7 @@ FD_POSIX_TEST_SRC = \
FD_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FD_POSIX_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/fd_posix_test: openssl_dep_error
@@ -5893,7 +5982,7 @@ FLING_CLIENT_SRC = \
FLING_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_CLIENT_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/fling_client: openssl_dep_error
@@ -5922,7 +6011,7 @@ FLING_SERVER_SRC = \
FLING_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_SERVER_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/fling_server: openssl_dep_error
@@ -5951,7 +6040,7 @@ FLING_STREAM_TEST_SRC = \
FLING_STREAM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_STREAM_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/fling_stream_test: openssl_dep_error
@@ -5980,7 +6069,7 @@ FLING_TEST_SRC = \
FLING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/fling_test: openssl_dep_error
@@ -6009,7 +6098,7 @@ GEN_HPACK_TABLES_SRC = \
GEN_HPACK_TABLES_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GEN_HPACK_TABLES_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gen_hpack_tables: openssl_dep_error
@@ -6038,7 +6127,7 @@ GPR_CANCELLABLE_TEST_SRC = \
GPR_CANCELLABLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_CANCELLABLE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_cancellable_test: openssl_dep_error
@@ -6067,7 +6156,7 @@ GPR_CMDLINE_TEST_SRC = \
GPR_CMDLINE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_CMDLINE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_cmdline_test: openssl_dep_error
@@ -6096,7 +6185,7 @@ GPR_ENV_TEST_SRC = \
GPR_ENV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_ENV_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_env_test: openssl_dep_error
@@ -6125,7 +6214,7 @@ GPR_FILE_TEST_SRC = \
GPR_FILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_FILE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_file_test: openssl_dep_error
@@ -6154,7 +6243,7 @@ GPR_HISTOGRAM_TEST_SRC = \
GPR_HISTOGRAM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_HISTOGRAM_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_histogram_test: openssl_dep_error
@@ -6183,7 +6272,7 @@ GPR_HOST_PORT_TEST_SRC = \
GPR_HOST_PORT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_HOST_PORT_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_host_port_test: openssl_dep_error
@@ -6212,7 +6301,7 @@ GPR_LOG_TEST_SRC = \
GPR_LOG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_LOG_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_log_test: openssl_dep_error
@@ -6241,7 +6330,7 @@ GPR_SLICE_BUFFER_TEST_SRC = \
GPR_SLICE_BUFFER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_SLICE_BUFFER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_slice_buffer_test: openssl_dep_error
@@ -6270,7 +6359,7 @@ GPR_SLICE_TEST_SRC = \
GPR_SLICE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_SLICE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_slice_test: openssl_dep_error
@@ -6293,13 +6382,42 @@ endif
endif
+GPR_STACK_LOCKFREE_TEST_SRC = \
+ test/core/support/stack_lockfree_test.c \
+
+GPR_STACK_LOCKFREE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_STACK_LOCKFREE_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test: $(GPR_STACK_LOCKFREE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LD) $(LDFLAGS) $(GPR_STACK_LOCKFREE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/support/stack_lockfree_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+deps_gpr_stack_lockfree_test: $(GPR_STACK_LOCKFREE_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GPR_STACK_LOCKFREE_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
GPR_STRING_TEST_SRC = \
test/core/support/string_test.c \
GPR_STRING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_STRING_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_string_test: openssl_dep_error
@@ -6328,7 +6446,7 @@ GPR_SYNC_TEST_SRC = \
GPR_SYNC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_SYNC_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_sync_test: openssl_dep_error
@@ -6357,7 +6475,7 @@ GPR_THD_TEST_SRC = \
GPR_THD_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_THD_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_thd_test: openssl_dep_error
@@ -6386,7 +6504,7 @@ GPR_TIME_TEST_SRC = \
GPR_TIME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_TIME_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_time_test: openssl_dep_error
@@ -6415,7 +6533,7 @@ GPR_TLS_TEST_SRC = \
GPR_TLS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_TLS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_tls_test: openssl_dep_error
@@ -6444,7 +6562,7 @@ GPR_USEFUL_TEST_SRC = \
GPR_USEFUL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_USEFUL_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_useful_test: openssl_dep_error
@@ -6473,7 +6591,7 @@ GRPC_AUTH_CONTEXT_TEST_SRC = \
GRPC_AUTH_CONTEXT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_AUTH_CONTEXT_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_auth_context_test: openssl_dep_error
@@ -6502,7 +6620,7 @@ GRPC_BASE64_TEST_SRC = \
GRPC_BASE64_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_BASE64_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_base64_test: openssl_dep_error
@@ -6531,7 +6649,7 @@ GRPC_BYTE_BUFFER_READER_TEST_SRC = \
GRPC_BYTE_BUFFER_READER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_BYTE_BUFFER_READER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test: openssl_dep_error
@@ -6560,7 +6678,7 @@ GRPC_CHANNEL_STACK_TEST_SRC = \
GRPC_CHANNEL_STACK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CHANNEL_STACK_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_channel_stack_test: openssl_dep_error
@@ -6589,7 +6707,7 @@ GRPC_COMPLETION_QUEUE_TEST_SRC = \
GRPC_COMPLETION_QUEUE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_COMPLETION_QUEUE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_completion_queue_test: openssl_dep_error
@@ -6618,7 +6736,7 @@ GRPC_CREATE_JWT_SRC = \
GRPC_CREATE_JWT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CREATE_JWT_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_create_jwt: openssl_dep_error
@@ -6647,7 +6765,7 @@ GRPC_CREDENTIALS_TEST_SRC = \
GRPC_CREDENTIALS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CREDENTIALS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_credentials_test: openssl_dep_error
@@ -6676,7 +6794,7 @@ GRPC_FETCH_OAUTH2_SRC = \
GRPC_FETCH_OAUTH2_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_FETCH_OAUTH2_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_fetch_oauth2: openssl_dep_error
@@ -6705,7 +6823,7 @@ GRPC_JSON_TOKEN_TEST_SRC = \
GRPC_JSON_TOKEN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_JSON_TOKEN_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_json_token_test: openssl_dep_error
@@ -6728,13 +6846,42 @@ endif
endif
+GRPC_JWT_VERIFIER_TEST_SRC = \
+ test/core/security/jwt_verifier_test.c \
+
+GRPC_JWT_VERIFIER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_JWT_VERIFIER_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test: $(GRPC_JWT_VERIFIER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LD) $(LDFLAGS) $(GRPC_JWT_VERIFIER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/security/jwt_verifier_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+deps_grpc_jwt_verifier_test: $(GRPC_JWT_VERIFIER_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GRPC_JWT_VERIFIER_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_SRC = \
test/core/security/print_google_default_creds_token.c \
GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token: openssl_dep_error
@@ -6763,7 +6910,7 @@ GRPC_SECURITY_CONNECTOR_TEST_SRC = \
GRPC_SECURITY_CONNECTOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_SECURITY_CONNECTOR_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_security_connector_test: openssl_dep_error
@@ -6792,7 +6939,7 @@ GRPC_STREAM_OP_TEST_SRC = \
GRPC_STREAM_OP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_STREAM_OP_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_stream_op_test: openssl_dep_error
@@ -6815,13 +6962,42 @@ endif
endif
+GRPC_VERIFY_JWT_SRC = \
+ test/core/security/verify_jwt.c \
+
+GRPC_VERIFY_JWT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_VERIFY_JWT_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/grpc_verify_jwt: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/grpc_verify_jwt: $(GRPC_VERIFY_JWT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LD) $(LDFLAGS) $(GRPC_VERIFY_JWT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_verify_jwt
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/security/verify_jwt.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+deps_grpc_verify_jwt: $(GRPC_VERIFY_JWT_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GRPC_VERIFY_JWT_OBJS:.o=.dep)
+endif
+endif
+
+
HPACK_PARSER_TEST_SRC = \
test/core/transport/chttp2/hpack_parser_test.c \
HPACK_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_PARSER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/hpack_parser_test: openssl_dep_error
@@ -6850,7 +7026,7 @@ HPACK_TABLE_TEST_SRC = \
HPACK_TABLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_TABLE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/hpack_table_test: openssl_dep_error
@@ -6879,7 +7055,7 @@ HTTPCLI_FORMAT_REQUEST_TEST_SRC = \
HTTPCLI_FORMAT_REQUEST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPCLI_FORMAT_REQUEST_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/httpcli_format_request_test: openssl_dep_error
@@ -6908,7 +7084,7 @@ HTTPCLI_PARSER_TEST_SRC = \
HTTPCLI_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPCLI_PARSER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/httpcli_parser_test: openssl_dep_error
@@ -6937,7 +7113,7 @@ HTTPCLI_TEST_SRC = \
HTTPCLI_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPCLI_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/httpcli_test: openssl_dep_error
@@ -6966,7 +7142,7 @@ JSON_REWRITE_SRC = \
JSON_REWRITE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_REWRITE_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/json_rewrite: openssl_dep_error
@@ -6995,7 +7171,7 @@ JSON_REWRITE_TEST_SRC = \
JSON_REWRITE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_REWRITE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/json_rewrite_test: openssl_dep_error
@@ -7024,7 +7200,7 @@ JSON_TEST_SRC = \
JSON_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/json_test: openssl_dep_error
@@ -7053,7 +7229,7 @@ LAME_CLIENT_TEST_SRC = \
LAME_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LAME_CLIENT_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/lame_client_test: openssl_dep_error
@@ -7082,7 +7258,7 @@ LOW_LEVEL_PING_PONG_BENCHMARK_SRC = \
LOW_LEVEL_PING_PONG_BENCHMARK_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LOW_LEVEL_PING_PONG_BENCHMARK_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark: openssl_dep_error
@@ -7111,7 +7287,7 @@ MESSAGE_COMPRESS_TEST_SRC = \
MESSAGE_COMPRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MESSAGE_COMPRESS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/message_compress_test: openssl_dep_error
@@ -7140,7 +7316,7 @@ MULTI_INIT_TEST_SRC = \
MULTI_INIT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MULTI_INIT_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/multi_init_test: openssl_dep_error
@@ -7169,7 +7345,7 @@ MULTIPLE_SERVER_QUEUES_TEST_SRC = \
MULTIPLE_SERVER_QUEUES_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MULTIPLE_SERVER_QUEUES_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/multiple_server_queues_test: openssl_dep_error
@@ -7198,7 +7374,7 @@ MURMUR_HASH_TEST_SRC = \
MURMUR_HASH_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MURMUR_HASH_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/murmur_hash_test: openssl_dep_error
@@ -7227,7 +7403,7 @@ NO_SERVER_TEST_SRC = \
NO_SERVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NO_SERVER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/no_server_test: openssl_dep_error
@@ -7256,7 +7432,7 @@ POLL_KICK_POSIX_TEST_SRC = \
POLL_KICK_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(POLL_KICK_POSIX_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/poll_kick_posix_test: openssl_dep_error
@@ -7285,7 +7461,7 @@ RESOLVE_ADDRESS_TEST_SRC = \
RESOLVE_ADDRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/resolve_address_test: openssl_dep_error
@@ -7314,7 +7490,7 @@ SECURE_ENDPOINT_TEST_SRC = \
SECURE_ENDPOINT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SECURE_ENDPOINT_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/secure_endpoint_test: openssl_dep_error
@@ -7343,7 +7519,7 @@ SOCKADDR_UTILS_TEST_SRC = \
SOCKADDR_UTILS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SOCKADDR_UTILS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/sockaddr_utils_test: openssl_dep_error
@@ -7372,7 +7548,7 @@ TCP_CLIENT_POSIX_TEST_SRC = \
TCP_CLIENT_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_CLIENT_POSIX_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/tcp_client_posix_test: openssl_dep_error
@@ -7401,7 +7577,7 @@ TCP_POSIX_TEST_SRC = \
TCP_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_POSIX_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/tcp_posix_test: openssl_dep_error
@@ -7430,7 +7606,7 @@ TCP_SERVER_POSIX_TEST_SRC = \
TCP_SERVER_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_SERVER_POSIX_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/tcp_server_posix_test: openssl_dep_error
@@ -7459,7 +7635,7 @@ TIME_AVERAGED_STATS_TEST_SRC = \
TIME_AVERAGED_STATS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIME_AVERAGED_STATS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/time_averaged_stats_test: openssl_dep_error
@@ -7488,7 +7664,7 @@ TIME_TEST_SRC = \
TIME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIME_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/time_test: openssl_dep_error
@@ -7517,7 +7693,7 @@ TIMEOUT_ENCODING_TEST_SRC = \
TIMEOUT_ENCODING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIMEOUT_ENCODING_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/timeout_encoding_test: openssl_dep_error
@@ -7546,7 +7722,7 @@ TIMERS_TEST_SRC = \
TIMERS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIMERS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/timers_test: openssl_dep_error
@@ -7575,7 +7751,7 @@ TRANSPORT_METADATA_TEST_SRC = \
TRANSPORT_METADATA_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_METADATA_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/transport_metadata_test: openssl_dep_error
@@ -7604,7 +7780,7 @@ TRANSPORT_SECURITY_TEST_SRC = \
TRANSPORT_SECURITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_SECURITY_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/transport_security_test: openssl_dep_error
@@ -7633,7 +7809,7 @@ URI_PARSER_TEST_SRC = \
URI_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(URI_PARSER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/uri_parser_test: openssl_dep_error
@@ -7662,7 +7838,7 @@ ASYNC_END2END_TEST_SRC = \
ASYNC_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ASYNC_END2END_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/async_end2end_test: openssl_dep_error
@@ -7702,7 +7878,7 @@ ASYNC_STREAMING_PING_PONG_TEST_SRC = \
ASYNC_STREAMING_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ASYNC_STREAMING_PING_PONG_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test: openssl_dep_error
@@ -7742,7 +7918,7 @@ ASYNC_UNARY_PING_PONG_TEST_SRC = \
ASYNC_UNARY_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ASYNC_UNARY_PING_PONG_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/async_unary_ping_pong_test: openssl_dep_error
@@ -7776,13 +7952,53 @@ endif
endif
+AUTH_PROPERTY_ITERATOR_TEST_SRC = \
+ test/cpp/common/auth_property_iterator_test.cc \
+
+AUTH_PROPERTY_ITERATOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(AUTH_PROPERTY_ITERATOR_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/auth_property_iterator_test: openssl_dep_error
+
+else
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/auth_property_iterator_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/auth_property_iterator_test: $(PROTOBUF_DEP) $(AUTH_PROPERTY_ITERATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LDXX) $(LDFLAGS) $(AUTH_PROPERTY_ITERATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/auth_property_iterator_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/common/auth_property_iterator_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+deps_auth_property_iterator_test: $(AUTH_PROPERTY_ITERATOR_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(AUTH_PROPERTY_ITERATOR_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
CHANNEL_ARGUMENTS_TEST_SRC = \
test/cpp/client/channel_arguments_test.cc \
CHANNEL_ARGUMENTS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHANNEL_ARGUMENTS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/channel_arguments_test: openssl_dep_error
@@ -7822,7 +8038,7 @@ CLI_CALL_TEST_SRC = \
CLI_CALL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLI_CALL_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/cli_call_test: openssl_dep_error
@@ -7862,7 +8078,7 @@ CLIENT_CRASH_TEST_SRC = \
CLIENT_CRASH_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_CRASH_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/client_crash_test: openssl_dep_error
@@ -7902,7 +8118,7 @@ CLIENT_CRASH_TEST_SERVER_SRC = \
CLIENT_CRASH_TEST_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_CRASH_TEST_SERVER_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/client_crash_test_server: openssl_dep_error
@@ -7942,7 +8158,7 @@ CREDENTIALS_TEST_SRC = \
CREDENTIALS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CREDENTIALS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/credentials_test: openssl_dep_error
@@ -7982,7 +8198,7 @@ CXX_BYTE_BUFFER_TEST_SRC = \
CXX_BYTE_BUFFER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CXX_BYTE_BUFFER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/cxx_byte_buffer_test: openssl_dep_error
@@ -8022,7 +8238,7 @@ CXX_SLICE_TEST_SRC = \
CXX_SLICE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CXX_SLICE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/cxx_slice_test: openssl_dep_error
@@ -8062,7 +8278,7 @@ CXX_TIME_TEST_SRC = \
CXX_TIME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CXX_TIME_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/cxx_time_test: openssl_dep_error
@@ -8102,7 +8318,7 @@ END2END_TEST_SRC = \
END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(END2END_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/end2end_test: openssl_dep_error
@@ -8136,13 +8352,53 @@ endif
endif
+FIXED_SIZE_THREAD_POOL_TEST_SRC = \
+ test/cpp/server/fixed_size_thread_pool_test.cc \
+
+FIXED_SIZE_THREAD_POOL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FIXED_SIZE_THREAD_POOL_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/fixed_size_thread_pool_test: openssl_dep_error
+
+else
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/fixed_size_thread_pool_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/fixed_size_thread_pool_test: $(PROTOBUF_DEP) $(FIXED_SIZE_THREAD_POOL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LDXX) $(LDFLAGS) $(FIXED_SIZE_THREAD_POOL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/fixed_size_thread_pool_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/server/fixed_size_thread_pool_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+deps_fixed_size_thread_pool_test: $(FIXED_SIZE_THREAD_POOL_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(FIXED_SIZE_THREAD_POOL_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
GENERIC_END2END_TEST_SRC = \
test/cpp/end2end/generic_end2end_test.cc \
GENERIC_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GENERIC_END2END_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/generic_end2end_test: openssl_dep_error
@@ -8182,7 +8438,7 @@ GRPC_CLI_SRC = \
GRPC_CLI_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CLI_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_cli: openssl_dep_error
@@ -8358,7 +8614,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/interop_client: openssl_dep_error
@@ -8387,7 +8643,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/interop_server: openssl_dep_error
@@ -8420,7 +8676,7 @@ INTEROP_TEST_SRC = \
INTEROP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INTEROP_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/interop_test: openssl_dep_error
@@ -8460,7 +8716,7 @@ MOCK_TEST_SRC = \
MOCK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MOCK_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/mock_test: openssl_dep_error
@@ -8500,7 +8756,7 @@ PUBSUB_CLIENT_SRC = \
PUBSUB_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PUBSUB_CLIENT_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/pubsub_client: openssl_dep_error
@@ -8540,7 +8796,7 @@ PUBSUB_PUBLISHER_TEST_SRC = \
PUBSUB_PUBLISHER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PUBSUB_PUBLISHER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/pubsub_publisher_test: openssl_dep_error
@@ -8580,7 +8836,7 @@ PUBSUB_SUBSCRIBER_TEST_SRC = \
PUBSUB_SUBSCRIBER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PUBSUB_SUBSCRIBER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/pubsub_subscriber_test: openssl_dep_error
@@ -8620,7 +8876,7 @@ QPS_DRIVER_SRC = \
QPS_DRIVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_DRIVER_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/qps_driver: openssl_dep_error
@@ -8660,7 +8916,7 @@ QPS_INTERARRIVAL_TEST_SRC = \
QPS_INTERARRIVAL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_INTERARRIVAL_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/qps_interarrival_test: openssl_dep_error
@@ -8694,15 +8950,15 @@ endif
endif
-QPS_TEST_SRC = \
- test/cpp/qps/qps_test.cc \
+QPS_OPENLOOP_TEST_SRC = \
+ test/cpp/qps/qps_openloop_test.cc \
-QPS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_TEST_SRC))))
+QPS_OPENLOOP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_OPENLOOP_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
-$(BINDIR)/$(CONFIG)/qps_test: openssl_dep_error
+$(BINDIR)/$(CONFIG)/qps_openloop_test: openssl_dep_error
else
@@ -8711,38 +8967,38 @@ ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
-$(BINDIR)/$(CONFIG)/qps_test: protobuf_dep_error
+$(BINDIR)/$(CONFIG)/qps_openloop_test: protobuf_dep_error
else
-$(BINDIR)/$(CONFIG)/qps_test: $(PROTOBUF_DEP) $(QPS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+$(BINDIR)/$(CONFIG)/qps_openloop_test: $(PROTOBUF_DEP) $(QPS_OPENLOOP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
- $(Q) $(LDXX) $(LDFLAGS) $(QPS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_test
+ $(Q) $(LDXX) $(LDFLAGS) $(QPS_OPENLOOP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_openloop_test
endif
endif
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_test.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
-deps_qps_test: $(QPS_TEST_OBJS:.o=.dep)
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_openloop_test.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+deps_qps_openloop_test: $(QPS_OPENLOOP_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
--include $(QPS_TEST_OBJS:.o=.dep)
+-include $(QPS_OPENLOOP_TEST_OBJS:.o=.dep)
endif
endif
-QPS_TEST_OPENLOOP_SRC = \
- test/cpp/qps/qps_test_openloop.cc \
+QPS_TEST_SRC = \
+ test/cpp/qps/qps_test.cc \
-QPS_TEST_OPENLOOP_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_TEST_OPENLOOP_SRC))))
+QPS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
-$(BINDIR)/$(CONFIG)/qps_test_openloop: openssl_dep_error
+$(BINDIR)/$(CONFIG)/qps_test: openssl_dep_error
else
@@ -8751,25 +9007,25 @@ ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
-$(BINDIR)/$(CONFIG)/qps_test_openloop: protobuf_dep_error
+$(BINDIR)/$(CONFIG)/qps_test: protobuf_dep_error
else
-$(BINDIR)/$(CONFIG)/qps_test_openloop: $(PROTOBUF_DEP) $(QPS_TEST_OPENLOOP_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+$(BINDIR)/$(CONFIG)/qps_test: $(PROTOBUF_DEP) $(QPS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
- $(Q) $(LDXX) $(LDFLAGS) $(QPS_TEST_OPENLOOP_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_test_openloop
+ $(Q) $(LDXX) $(LDFLAGS) $(QPS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_test
endif
endif
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_test_openloop.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
-deps_qps_test_openloop: $(QPS_TEST_OPENLOOP_OBJS:.o=.dep)
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_test.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+deps_qps_test: $(QPS_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
--include $(QPS_TEST_OPENLOOP_OBJS:.o=.dep)
+-include $(QPS_TEST_OBJS:.o=.dep)
endif
endif
@@ -8780,7 +9036,7 @@ QPS_WORKER_SRC = \
QPS_WORKER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_WORKER_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/qps_worker: openssl_dep_error
@@ -8814,13 +9070,53 @@ endif
endif
+SECURE_AUTH_CONTEXT_TEST_SRC = \
+ test/cpp/common/secure_auth_context_test.cc \
+
+SECURE_AUTH_CONTEXT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SECURE_AUTH_CONTEXT_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/secure_auth_context_test: openssl_dep_error
+
+else
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/secure_auth_context_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/secure_auth_context_test: $(PROTOBUF_DEP) $(SECURE_AUTH_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LDXX) $(LDFLAGS) $(SECURE_AUTH_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/secure_auth_context_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/common/secure_auth_context_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+deps_secure_auth_context_test: $(SECURE_AUTH_CONTEXT_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(SECURE_AUTH_CONTEXT_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
SERVER_CRASH_TEST_SRC = \
test/cpp/end2end/server_crash_test.cc \
SERVER_CRASH_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CRASH_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/server_crash_test: openssl_dep_error
@@ -8860,7 +9156,7 @@ SERVER_CRASH_TEST_CLIENT_SRC = \
SERVER_CRASH_TEST_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CRASH_TEST_CLIENT_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/server_crash_test_client: openssl_dep_error
@@ -8900,7 +9196,7 @@ STATUS_TEST_SRC = \
STATUS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STATUS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/status_test: openssl_dep_error
@@ -8940,7 +9236,7 @@ SYNC_STREAMING_PING_PONG_TEST_SRC = \
SYNC_STREAMING_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SYNC_STREAMING_PING_PONG_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test: openssl_dep_error
@@ -8980,7 +9276,7 @@ SYNC_UNARY_PING_PONG_TEST_SRC = \
SYNC_UNARY_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SYNC_UNARY_PING_PONG_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test: openssl_dep_error
@@ -9014,53 +9310,13 @@ endif
endif
-THREAD_POOL_TEST_SRC = \
- test/cpp/server/thread_pool_test.cc \
-
-THREAD_POOL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(THREAD_POOL_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL with ALPN.
-
-$(BINDIR)/$(CONFIG)/thread_pool_test: openssl_dep_error
-
-else
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
-
-$(BINDIR)/$(CONFIG)/thread_pool_test: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/thread_pool_test: $(PROTOBUF_DEP) $(THREAD_POOL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
- $(E) "[LD] Linking $@"
- $(Q) mkdir -p `dirname $@`
- $(Q) $(LDXX) $(LDFLAGS) $(THREAD_POOL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/thread_pool_test
-
-endif
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/cpp/server/thread_pool_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-deps_thread_pool_test: $(THREAD_POOL_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(THREAD_POOL_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
THREAD_STRESS_TEST_SRC = \
test/cpp/end2end/thread_stress_test.cc \
THREAD_STRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(THREAD_STRESS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/thread_stress_test: openssl_dep_error
@@ -9096,7 +9352,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test: openssl_dep_error
@@ -9114,7 +9370,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test: openssl_dep_error
@@ -9132,7 +9388,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test: openssl_dep_error
@@ -9150,7 +9406,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test: openssl_dep_error
@@ -9168,7 +9424,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test: openssl_dep_error
@@ -9186,7 +9442,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test: openssl_dep_error
@@ -9204,7 +9460,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test: openssl_dep_error
@@ -9222,7 +9478,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test: openssl_dep_error
@@ -9240,7 +9496,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test: openssl_dep_error
@@ -9258,7 +9514,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test: openssl_dep_error
@@ -9276,7 +9532,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test: openssl_dep_error
@@ -9294,7 +9550,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test: openssl_dep_error
@@ -9312,7 +9568,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test: openssl_dep_error
@@ -9330,7 +9586,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test: openssl_dep_error
@@ -9348,7 +9604,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_max_message_length_test: openssl_dep_error
@@ -9366,7 +9622,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test: openssl_dep_error
@@ -9384,7 +9640,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test: openssl_dep_error
@@ -9402,7 +9658,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_registered_call_test: openssl_dep_error
@@ -9420,7 +9676,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test: openssl_dep_error
@@ -9438,7 +9694,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test: openssl_dep_error
@@ -9456,7 +9712,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test: openssl_dep_error
@@ -9474,7 +9730,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_and_call_creds_test: openssl_dep_error
@@ -9492,7 +9748,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test: openssl_dep_error
@@ -9510,7 +9766,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_flags_test: openssl_dep_error
@@ -9528,7 +9784,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test: openssl_dep_error
@@ -9546,7 +9802,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test: openssl_dep_error
@@ -9564,7 +9820,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_server_finishes_request_test: openssl_dep_error
@@ -9582,7 +9838,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test: openssl_dep_error
@@ -9600,7 +9856,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test: openssl_dep_error
@@ -9618,7 +9874,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_with_high_initial_sequence_number_test: openssl_dep_error
@@ -9636,7 +9892,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test: openssl_dep_error
@@ -9654,7 +9910,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test: openssl_dep_error
@@ -9672,7 +9928,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test: openssl_dep_error
@@ -9690,7 +9946,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test: openssl_dep_error
@@ -9708,7 +9964,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test: openssl_dep_error
@@ -9726,7 +9982,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test: openssl_dep_error
@@ -9744,7 +10000,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test: openssl_dep_error
@@ -9762,7 +10018,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test: openssl_dep_error
@@ -9780,7 +10036,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test: openssl_dep_error
@@ -9798,7 +10054,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test: openssl_dep_error
@@ -9816,7 +10072,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test: openssl_dep_error
@@ -9834,7 +10090,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test: openssl_dep_error
@@ -9852,7 +10108,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test: openssl_dep_error
@@ -9870,7 +10126,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test: openssl_dep_error
@@ -9888,7 +10144,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_max_message_length_test: openssl_dep_error
@@ -9906,7 +10162,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test: openssl_dep_error
@@ -9924,7 +10180,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test: openssl_dep_error
@@ -9942,7 +10198,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_registered_call_test: openssl_dep_error
@@ -9960,7 +10216,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test: openssl_dep_error
@@ -9978,7 +10234,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test: openssl_dep_error
@@ -9996,7 +10252,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test: openssl_dep_error
@@ -10014,7 +10270,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_and_call_creds_test: openssl_dep_error
@@ -10032,7 +10288,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test: openssl_dep_error
@@ -10050,7 +10306,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_flags_test: openssl_dep_error
@@ -10068,7 +10324,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test: openssl_dep_error
@@ -10086,7 +10342,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test: openssl_dep_error
@@ -10104,7 +10360,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_server_finishes_request_test: openssl_dep_error
@@ -10122,7 +10378,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test: openssl_dep_error
@@ -10140,7 +10396,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test: openssl_dep_error
@@ -10158,7 +10414,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_with_high_initial_sequence_number_test: openssl_dep_error
@@ -10176,7 +10432,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_bad_hostname_test: openssl_dep_error
@@ -10194,7 +10450,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_test: openssl_dep_error
@@ -10212,7 +10468,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_and_writes_closed_test: openssl_dep_error
@@ -10230,7 +10486,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_invoke_test: openssl_dep_error
@@ -10248,7 +10504,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_before_invoke_test: openssl_dep_error
@@ -10266,7 +10522,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_in_a_vacuum_test: openssl_dep_error
@@ -10284,7 +10540,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_census_simple_request_test: openssl_dep_error
@@ -10302,7 +10558,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_disappearing_server_test: openssl_dep_error
@@ -10320,7 +10576,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_inflight_calls_test: openssl_dep_error
@@ -10338,7 +10594,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_tags_test: openssl_dep_error
@@ -10356,7 +10612,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_empty_batch_test: openssl_dep_error
@@ -10374,7 +10630,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_graceful_server_shutdown_test: openssl_dep_error
@@ -10392,7 +10648,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_invoke_large_request_test: openssl_dep_error
@@ -10410,7 +10666,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_concurrent_streams_test: openssl_dep_error
@@ -10428,7 +10684,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_message_length_test: openssl_dep_error
@@ -10446,7 +10702,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_no_op_test: openssl_dep_error
@@ -10464,7 +10720,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_ping_pong_streaming_test: openssl_dep_error
@@ -10482,7 +10738,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_registered_call_test: openssl_dep_error
@@ -10500,7 +10756,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_binary_metadata_and_payload_test: openssl_dep_error
@@ -10518,7 +10774,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_metadata_and_payload_test: openssl_dep_error
@@ -10536,7 +10792,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_test: openssl_dep_error
@@ -10554,7 +10810,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_and_call_creds_test: openssl_dep_error
@@ -10572,7 +10828,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_trailing_metadata_and_payload_test: openssl_dep_error
@@ -10590,7 +10846,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_flags_test: openssl_dep_error
@@ -10608,7 +10864,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_large_metadata_test: openssl_dep_error
@@ -10626,7 +10882,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_payload_test: openssl_dep_error
@@ -10644,7 +10900,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_server_finishes_request_test: openssl_dep_error
@@ -10662,7 +10918,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_delayed_request_test: openssl_dep_error
@@ -10680,7 +10936,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_test: openssl_dep_error
@@ -10698,7 +10954,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_with_high_initial_sequence_number_test: openssl_dep_error
@@ -10716,7 +10972,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_bad_hostname_test: openssl_dep_error
@@ -10734,7 +10990,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_accept_test: openssl_dep_error
@@ -10752,7 +11008,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_accept_and_writes_closed_test: openssl_dep_error
@@ -10770,7 +11026,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_after_invoke_test: openssl_dep_error
@@ -10788,7 +11044,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_before_invoke_test: openssl_dep_error
@@ -10806,7 +11062,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_cancel_in_a_vacuum_test: openssl_dep_error
@@ -10824,7 +11080,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_census_simple_request_test: openssl_dep_error
@@ -10842,7 +11098,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_disappearing_server_test: openssl_dep_error
@@ -10860,7 +11116,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_early_server_shutdown_finishes_inflight_calls_test: openssl_dep_error
@@ -10878,7 +11134,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_early_server_shutdown_finishes_tags_test: openssl_dep_error
@@ -10896,7 +11152,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_empty_batch_test: openssl_dep_error
@@ -10914,7 +11170,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_graceful_server_shutdown_test: openssl_dep_error
@@ -10932,7 +11188,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_invoke_large_request_test: openssl_dep_error
@@ -10950,7 +11206,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_max_concurrent_streams_test: openssl_dep_error
@@ -10968,7 +11224,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_max_message_length_test: openssl_dep_error
@@ -10986,7 +11242,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_no_op_test: openssl_dep_error
@@ -11004,7 +11260,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_ping_pong_streaming_test: openssl_dep_error
@@ -11022,7 +11278,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_registered_call_test: openssl_dep_error
@@ -11040,7 +11296,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_binary_metadata_and_payload_test: openssl_dep_error
@@ -11058,7 +11314,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_metadata_and_payload_test: openssl_dep_error
@@ -11076,7 +11332,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_payload_test: openssl_dep_error
@@ -11094,7 +11350,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_payload_and_call_creds_test: openssl_dep_error
@@ -11112,7 +11368,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_response_with_trailing_metadata_and_payload_test: openssl_dep_error
@@ -11130,7 +11386,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_flags_test: openssl_dep_error
@@ -11148,7 +11404,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_large_metadata_test: openssl_dep_error
@@ -11166,7 +11422,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_request_with_payload_test: openssl_dep_error
@@ -11184,7 +11440,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_server_finishes_request_test: openssl_dep_error
@@ -11202,7 +11458,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_delayed_request_test: openssl_dep_error
@@ -11220,7 +11476,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_request_test: openssl_dep_error
@@ -11238,7 +11494,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_fullstack_with_poll_simple_request_with_high_initial_sequence_number_test: openssl_dep_error
@@ -11256,7 +11512,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test: openssl_dep_error
@@ -11274,7 +11530,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test: openssl_dep_error
@@ -11292,7 +11548,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test: openssl_dep_error
@@ -11310,7 +11566,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test: openssl_dep_error
@@ -11328,7 +11584,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test: openssl_dep_error
@@ -11346,7 +11602,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test: openssl_dep_error
@@ -11364,7 +11620,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test: openssl_dep_error
@@ -11382,7 +11638,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test: openssl_dep_error
@@ -11400,7 +11656,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test: openssl_dep_error
@@ -11418,7 +11674,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test: openssl_dep_error
@@ -11436,7 +11692,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test: openssl_dep_error
@@ -11454,7 +11710,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test: openssl_dep_error
@@ -11472,7 +11728,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test: openssl_dep_error
@@ -11490,7 +11746,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test: openssl_dep_error
@@ -11508,7 +11764,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_message_length_test: openssl_dep_error
@@ -11526,7 +11782,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test: openssl_dep_error
@@ -11544,7 +11800,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test: openssl_dep_error
@@ -11562,7 +11818,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_registered_call_test: openssl_dep_error
@@ -11580,7 +11836,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test: openssl_dep_error
@@ -11598,7 +11854,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test: openssl_dep_error
@@ -11616,7 +11872,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test: openssl_dep_error
@@ -11634,7 +11890,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_and_call_creds_test: openssl_dep_error
@@ -11652,7 +11908,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test: openssl_dep_error
@@ -11670,7 +11926,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_flags_test: openssl_dep_error
@@ -11688,7 +11944,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test: openssl_dep_error
@@ -11706,7 +11962,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test: openssl_dep_error
@@ -11724,7 +11980,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_server_finishes_request_test: openssl_dep_error
@@ -11742,7 +11998,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test: openssl_dep_error
@@ -11760,7 +12016,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test: openssl_dep_error
@@ -11778,7 +12034,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_with_high_initial_sequence_number_test: openssl_dep_error
@@ -11796,7 +12052,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_bad_hostname_test: openssl_dep_error
@@ -11814,7 +12070,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_after_accept_test: openssl_dep_error
@@ -11832,7 +12088,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_after_accept_and_writes_closed_test: openssl_dep_error
@@ -11850,7 +12106,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_after_invoke_test: openssl_dep_error
@@ -11868,7 +12124,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_before_invoke_test: openssl_dep_error
@@ -11886,7 +12142,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_cancel_in_a_vacuum_test: openssl_dep_error
@@ -11904,7 +12160,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_census_simple_request_test: openssl_dep_error
@@ -11922,7 +12178,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_disappearing_server_test: openssl_dep_error
@@ -11940,7 +12196,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_early_server_shutdown_finishes_inflight_calls_test: openssl_dep_error
@@ -11958,7 +12214,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_early_server_shutdown_finishes_tags_test: openssl_dep_error
@@ -11976,7 +12232,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_empty_batch_test: openssl_dep_error
@@ -11994,7 +12250,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_graceful_server_shutdown_test: openssl_dep_error
@@ -12012,7 +12268,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_invoke_large_request_test: openssl_dep_error
@@ -12030,7 +12286,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_max_concurrent_streams_test: openssl_dep_error
@@ -12048,7 +12304,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_max_message_length_test: openssl_dep_error
@@ -12066,7 +12322,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_no_op_test: openssl_dep_error
@@ -12084,7 +12340,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_ping_pong_streaming_test: openssl_dep_error
@@ -12102,7 +12358,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_registered_call_test: openssl_dep_error
@@ -12120,7 +12376,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_binary_metadata_and_payload_test: openssl_dep_error
@@ -12138,7 +12394,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_metadata_and_payload_test: openssl_dep_error
@@ -12156,7 +12412,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_payload_test: openssl_dep_error
@@ -12174,7 +12430,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_payload_and_call_creds_test: openssl_dep_error
@@ -12192,7 +12448,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_response_with_trailing_metadata_and_payload_test: openssl_dep_error
@@ -12210,7 +12466,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_with_flags_test: openssl_dep_error
@@ -12228,7 +12484,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_with_large_metadata_test: openssl_dep_error
@@ -12246,7 +12502,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_request_with_payload_test: openssl_dep_error
@@ -12264,7 +12520,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_server_finishes_request_test: openssl_dep_error
@@ -12282,7 +12538,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_simple_delayed_request_test: openssl_dep_error
@@ -12300,7 +12556,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_simple_request_test: openssl_dep_error
@@ -12318,7 +12574,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_with_poll_simple_request_with_high_initial_sequence_number_test: openssl_dep_error
@@ -12336,7 +12592,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test: openssl_dep_error
@@ -12354,7 +12610,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test: openssl_dep_error
@@ -12372,7 +12628,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test: openssl_dep_error
@@ -12390,7 +12646,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test: openssl_dep_error
@@ -12408,7 +12664,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test: openssl_dep_error
@@ -12426,7 +12682,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test: openssl_dep_error
@@ -12444,7 +12700,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test: openssl_dep_error
@@ -12462,7 +12718,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test: openssl_dep_error
@@ -12480,7 +12736,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test: openssl_dep_error
@@ -12498,7 +12754,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test: openssl_dep_error
@@ -12516,7 +12772,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test: openssl_dep_error
@@ -12534,7 +12790,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test: openssl_dep_error
@@ -12552,7 +12808,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test: openssl_dep_error
@@ -12570,7 +12826,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test: openssl_dep_error
@@ -12588,7 +12844,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_message_length_test: openssl_dep_error
@@ -12606,7 +12862,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test: openssl_dep_error
@@ -12624,7 +12880,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test: openssl_dep_error
@@ -12642,7 +12898,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_registered_call_test: openssl_dep_error
@@ -12660,7 +12916,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test: openssl_dep_error
@@ -12678,7 +12934,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test: openssl_dep_error
@@ -12696,7 +12952,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test: openssl_dep_error
@@ -12714,7 +12970,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_and_call_creds_test: openssl_dep_error
@@ -12732,7 +12988,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test: openssl_dep_error
@@ -12750,7 +13006,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_flags_test: openssl_dep_error
@@ -12768,7 +13024,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test: openssl_dep_error
@@ -12786,7 +13042,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test: openssl_dep_error
@@ -12804,7 +13060,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_server_finishes_request_test: openssl_dep_error
@@ -12822,7 +13078,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test: openssl_dep_error
@@ -12840,7 +13096,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test: openssl_dep_error
@@ -12858,7 +13114,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_with_high_initial_sequence_number_test: openssl_dep_error
@@ -12876,7 +13132,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test: openssl_dep_error
@@ -12894,7 +13150,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test: openssl_dep_error
@@ -12912,7 +13168,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test: openssl_dep_error
@@ -12930,7 +13186,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test: openssl_dep_error
@@ -12948,7 +13204,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test: openssl_dep_error
@@ -12966,7 +13222,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test: openssl_dep_error
@@ -12984,7 +13240,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test: openssl_dep_error
@@ -13002,7 +13258,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test: openssl_dep_error
@@ -13020,7 +13276,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test: openssl_dep_error
@@ -13038,7 +13294,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test: openssl_dep_error
@@ -13056,7 +13312,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test: openssl_dep_error
@@ -13074,7 +13330,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test: openssl_dep_error
@@ -13092,7 +13348,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test: openssl_dep_error
@@ -13110,7 +13366,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test: openssl_dep_error
@@ -13128,7 +13384,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_message_length_test: openssl_dep_error
@@ -13146,7 +13402,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test: openssl_dep_error
@@ -13164,7 +13420,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test: openssl_dep_error
@@ -13182,7 +13438,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_registered_call_test: openssl_dep_error
@@ -13200,7 +13456,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test: openssl_dep_error
@@ -13218,7 +13474,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test: openssl_dep_error
@@ -13236,7 +13492,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test: openssl_dep_error
@@ -13254,7 +13510,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_and_call_creds_test: openssl_dep_error
@@ -13272,7 +13528,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test: openssl_dep_error
@@ -13290,7 +13546,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_flags_test: openssl_dep_error
@@ -13308,7 +13564,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test: openssl_dep_error
@@ -13326,7 +13582,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test: openssl_dep_error
@@ -13344,7 +13600,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_server_finishes_request_test: openssl_dep_error
@@ -13362,7 +13618,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test: openssl_dep_error
@@ -13380,7 +13636,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test: openssl_dep_error
@@ -13398,7 +13654,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_with_high_initial_sequence_number_test: openssl_dep_error
@@ -13416,7 +13672,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test: openssl_dep_error
@@ -13434,7 +13690,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test: openssl_dep_error
@@ -13452,7 +13708,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test: openssl_dep_error
@@ -13470,7 +13726,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test: openssl_dep_error
@@ -13488,7 +13744,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test: openssl_dep_error
@@ -13506,7 +13762,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test: openssl_dep_error
@@ -13524,7 +13780,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test: openssl_dep_error
@@ -13542,7 +13798,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test: openssl_dep_error
@@ -13560,7 +13816,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test: openssl_dep_error
@@ -13578,7 +13834,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test: openssl_dep_error
@@ -13596,7 +13852,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test: openssl_dep_error
@@ -13614,7 +13870,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test: openssl_dep_error
@@ -13632,7 +13888,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test: openssl_dep_error
@@ -13650,7 +13906,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test: openssl_dep_error
@@ -13668,7 +13924,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_message_length_test: openssl_dep_error
@@ -13686,7 +13942,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test: openssl_dep_error
@@ -13704,7 +13960,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test: openssl_dep_error
@@ -13722,7 +13978,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_registered_call_test: openssl_dep_error
@@ -13740,7 +13996,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test: openssl_dep_error
@@ -13758,7 +14014,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test: openssl_dep_error
@@ -13776,7 +14032,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test: openssl_dep_error
@@ -13794,7 +14050,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_and_call_creds_test: openssl_dep_error
@@ -13812,7 +14068,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test: openssl_dep_error
@@ -13830,7 +14086,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_flags_test: openssl_dep_error
@@ -13848,7 +14104,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test: openssl_dep_error
@@ -13866,7 +14122,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test: openssl_dep_error
@@ -13884,7 +14140,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_server_finishes_request_test: openssl_dep_error
@@ -13902,7 +14158,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test: openssl_dep_error
@@ -13920,7 +14176,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test: openssl_dep_error
@@ -13938,7 +14194,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_test: openssl_dep_error
@@ -13956,7 +14212,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_bad_hostname_test: openssl_dep_error
@@ -13974,7 +14230,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_accept_test: openssl_dep_error
@@ -13992,7 +14248,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_accept_and_writes_closed_test: openssl_dep_error
@@ -14010,7 +14266,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_after_invoke_test: openssl_dep_error
@@ -14028,7 +14284,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_before_invoke_test: openssl_dep_error
@@ -14046,7 +14302,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_cancel_in_a_vacuum_test: openssl_dep_error
@@ -14064,7 +14320,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_census_simple_request_test: openssl_dep_error
@@ -14082,7 +14338,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_disappearing_server_test: openssl_dep_error
@@ -14100,7 +14356,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_inflight_calls_test: openssl_dep_error
@@ -14118,7 +14374,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_tags_test: openssl_dep_error
@@ -14136,7 +14392,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_empty_batch_test: openssl_dep_error
@@ -14154,7 +14410,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_graceful_server_shutdown_test: openssl_dep_error
@@ -14172,7 +14428,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_invoke_large_request_test: openssl_dep_error
@@ -14190,7 +14446,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_max_concurrent_streams_test: openssl_dep_error
@@ -14208,7 +14464,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_max_message_length_test: openssl_dep_error
@@ -14226,7 +14482,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_no_op_test: openssl_dep_error
@@ -14244,7 +14500,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_ping_pong_streaming_test: openssl_dep_error
@@ -14262,7 +14518,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_registered_call_test: openssl_dep_error
@@ -14280,7 +14536,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_binary_metadata_and_payload_test: openssl_dep_error
@@ -14298,7 +14554,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_metadata_and_payload_test: openssl_dep_error
@@ -14316,7 +14572,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_payload_test: openssl_dep_error
@@ -14334,7 +14590,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_payload_and_call_creds_test: openssl_dep_error
@@ -14352,7 +14608,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_response_with_trailing_metadata_and_payload_test: openssl_dep_error
@@ -14370,7 +14626,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_flags_test: openssl_dep_error
@@ -14388,7 +14644,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_large_metadata_test: openssl_dep_error
@@ -14406,7 +14662,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_request_with_payload_test: openssl_dep_error
@@ -14424,7 +14680,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_server_finishes_request_test: openssl_dep_error
@@ -14442,7 +14698,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_delayed_request_test: openssl_dep_error
@@ -14460,7 +14716,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_request_test: openssl_dep_error
@@ -14478,7 +14734,7 @@ endif
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_socket_pair_with_grpc_trace_simple_request_with_high_initial_sequence_number_test: openssl_dep_error
@@ -15940,6 +16196,7 @@ src/core/security/credentials_posix.c: $(OPENSSL_DEP)
src/core/security/credentials_win32.c: $(OPENSSL_DEP)
src/core/security/google_default_credentials.c: $(OPENSSL_DEP)
src/core/security/json_token.c: $(OPENSSL_DEP)
+src/core/security/jwt_verifier.c: $(OPENSSL_DEP)
src/core/security/secure_endpoint.c: $(OPENSSL_DEP)
src/core/security/secure_transport_setup.c: $(OPENSSL_DEP)
src/core/security/security_connector.c: $(OPENSSL_DEP)
diff --git a/README.md b/README.md
index f71ee6a6c1..36d9fa07ca 100644
--- a/README.md
+++ b/README.md
@@ -39,9 +39,9 @@ Libraries in different languages are in different state of development. We are s
* Ruby Library: [src/ruby] (src/ruby) : Early adopter ready - Alpha.
* NodeJS Library: [src/node] (src/node) : Early adopter ready - Alpha.
* Python Library: [src/python] (src/python) : Early adopter ready - Alpha.
- * C# Library: [src/csharp] (src/csharp) : Early adopter ready - Alpha.
+ * C# Library: [src/csharp] (src/csharp) : Early adopter ready - Alpha.
+ * Objective-C Library: [src/objective-c] (src/objective-c): Early adopter ready - Alpha.
* PHP Library: [src/php] (src/php) : Pre-Alpha.
- * Objective-C Library: [src/objective-c] (src/objective-c): Pre-Alpha.
#Overview
diff --git a/build.json b/build.json
index 3e8c0713d3..529b3e87c5 100644
--- a/build.json
+++ b/build.json
@@ -30,6 +30,8 @@
"public_headers": [
"include/grpc++/async_generic_service.h",
"include/grpc++/async_unary_call.h",
+ "include/grpc++/auth_context.h",
+ "include/grpc++/auth_property_iterator.h",
"include/grpc++/byte_buffer.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
@@ -39,6 +41,7 @@
"include/grpc++/config_protobuf.h",
"include/grpc++/create_channel.h",
"include/grpc++/credentials.h",
+ "include/grpc++/fixed_size_thread_pool.h",
"include/grpc++/generic_stub.h",
"include/grpc++/impl/call.h",
"include/grpc++/impl/client_unary_call.h",
@@ -68,7 +71,7 @@
],
"headers": [
"src/cpp/client/channel.h",
- "src/cpp/server/thread_pool.h"
+ "src/cpp/common/create_auth_context.h"
],
"src": [
"src/cpp/client/channel.cc",
@@ -85,12 +88,12 @@
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/async_generic_service.cc",
"src/cpp/server/create_default_thread_pool.cc",
+ "src/cpp/server/fixed_size_thread_pool.cc",
"src/cpp/server/insecure_server_credentials.cc",
"src/cpp/server/server.cc",
"src/cpp/server/server_builder.cc",
"src/cpp/server/server_context.cc",
"src/cpp/server/server_credentials.cc",
- "src/cpp/server/thread_pool.cc",
"src/cpp/util/byte_buffer.cc",
"src/cpp/util/slice.cc",
"src/cpp/util/status.cc",
@@ -285,6 +288,7 @@
"src/core/surface/server_chttp2.c",
"src/core/surface/server_create.c",
"src/core/surface/surface_trace.c",
+ "src/core/surface/version.c",
"src/core/transport/chttp2/alpn.c",
"src/core/transport/chttp2/bin_encoder.c",
"src/core/transport/chttp2/frame_data.c",
@@ -373,6 +377,7 @@
"src/core/support/env.h",
"src/core/support/file.h",
"src/core/support/murmur_hash.h",
+ "src/core/support/stack_lockfree.h",
"src/core/support/string.h",
"src/core/support/string_win32.h",
"src/core/support/thd_internal.h"
@@ -401,6 +406,7 @@
"src/core/support/murmur_hash.c",
"src/core/support/slice.c",
"src/core/support/slice_buffer.c",
+ "src/core/support/stack_lockfree.c",
"src/core/support/string.c",
"src/core/support/string_posix.c",
"src/core/support/string_win32.c",
@@ -451,6 +457,7 @@
"src/core/security/base64.h",
"src/core/security/credentials.h",
"src/core/security/json_token.h",
+ "src/core/security/jwt_verifier.h",
"src/core/security/secure_endpoint.h",
"src/core/security/secure_transport_setup.h",
"src/core/security/security_connector.h",
@@ -473,6 +480,7 @@
"src/core/security/credentials_win32.c",
"src/core/security/google_default_credentials.c",
"src/core/security/json_token.c",
+ "src/core/security/jwt_verifier.c",
"src/core/security/secure_endpoint.c",
"src/core/security/secure_transport_setup.c",
"src/core/security/security_connector.c",
@@ -580,11 +588,15 @@
"language": "c++",
"headers": [
"src/cpp/client/secure_credentials.h",
+ "src/cpp/common/secure_auth_context.h",
"src/cpp/server/secure_server_credentials.h"
],
"src": [
"src/cpp/client/secure_channel_arguments.cc",
"src/cpp/client/secure_credentials.cc",
+ "src/cpp/common/auth_property_iterator.cc",
+ "src/cpp/common/secure_auth_context.cc",
+ "src/cpp/common/secure_create_auth_context.cc",
"src/cpp/server/secure_server_credentials.cc"
],
"deps": [
@@ -637,6 +649,9 @@
"name": "grpc++_unsecure",
"build": "all",
"language": "c++",
+ "src": [
+ "src/cpp/common/insecure_create_auth_context.cc"
+ ],
"deps": [
"gpr",
"grpc_unsecure"
@@ -1182,6 +1197,18 @@
]
},
{
+ "name": "gpr_stack_lockfree_test",
+ "build": "test",
+ "language": "c",
+ "src": [
+ "test/core/support/stack_lockfree_test.c"
+ ],
+ "deps": [
+ "gpr_test_util",
+ "gpr"
+ ]
+ },
+ {
"name": "gpr_string_test",
"build": "test",
"language": "c",
@@ -1380,6 +1407,20 @@
]
},
{
+ "name": "grpc_jwt_verifier_test",
+ "build": "test",
+ "language": "c",
+ "src": [
+ "test/core/security/jwt_verifier_test.c"
+ ],
+ "deps": [
+ "grpc_test_util",
+ "grpc",
+ "gpr_test_util",
+ "gpr"
+ ]
+ },
+ {
"name": "grpc_print_google_default_creds_token",
"build": "tool",
"language": "c",
@@ -1422,6 +1463,20 @@
]
},
{
+ "name": "grpc_verify_jwt",
+ "build": "tool",
+ "language": "c",
+ "src": [
+ "test/core/security/verify_jwt.c"
+ ],
+ "deps": [
+ "grpc_test_util",
+ "grpc",
+ "gpr_test_util",
+ "gpr"
+ ]
+ },
+ {
"name": "hpack_parser_test",
"build": "test",
"language": "c",
@@ -1890,6 +1945,19 @@
]
},
{
+ "name": "auth_property_iterator_test",
+ "build": "test",
+ "language": "c++",
+ "src": [
+ "test/cpp/common/auth_property_iterator_test.cc"
+ ],
+ "deps": [
+ "grpc++",
+ "grpc",
+ "gpr"
+ ]
+ },
+ {
"name": "channel_arguments_test",
"build": "test",
"language": "c++",
@@ -2026,6 +2094,21 @@
]
},
{
+ "name": "fixed_size_thread_pool_test",
+ "build": "test",
+ "language": "c++",
+ "src": [
+ "test/cpp/server/fixed_size_thread_pool_test.cc"
+ ],
+ "deps": [
+ "grpc_test_util",
+ "grpc++",
+ "grpc",
+ "gpr_test_util",
+ "gpr"
+ ]
+ },
+ {
"name": "generic_end2end_test",
"build": "test",
"language": "c++",
@@ -2279,11 +2362,11 @@
]
},
{
- "name": "qps_test",
+ "name": "qps_openloop_test",
"build": "test",
"language": "c++",
"src": [
- "test/cpp/qps/qps_test.cc"
+ "test/cpp/qps/qps_openloop_test.cc"
],
"deps": [
"qps",
@@ -2297,11 +2380,11 @@
]
},
{
- "name": "qps_test_openloop",
+ "name": "qps_test",
"build": "test",
"language": "c++",
"src": [
- "test/cpp/qps/qps_test_openloop.cc"
+ "test/cpp/qps/qps_test.cc"
],
"deps": [
"qps",
@@ -2337,6 +2420,19 @@
]
},
{
+ "name": "secure_auth_context_test",
+ "build": "test",
+ "language": "c++",
+ "src": [
+ "test/cpp/common/secure_auth_context_test.cc"
+ ],
+ "deps": [
+ "grpc++",
+ "grpc",
+ "gpr"
+ ]
+ },
+ {
"name": "server_crash_test",
"build": "test",
"language": "c++",
@@ -2419,21 +2515,6 @@
]
},
{
- "name": "thread_pool_test",
- "build": "test",
- "language": "c++",
- "src": [
- "test/cpp/server/thread_pool_test.cc"
- ],
- "deps": [
- "grpc_test_util",
- "grpc++",
- "grpc",
- "gpr_test_util",
- "gpr"
- ]
- },
- {
"name": "thread_stress_test",
"build": "test",
"language": "c++",
diff --git a/doc/connection-backoff.md b/doc/connection-backoff.md
index 47b71f927b..7094e737c5 100644
--- a/doc/connection-backoff.md
+++ b/doc/connection-backoff.md
@@ -8,58 +8,39 @@ requests) and instead do some form of exponential backoff.
We have several parameters:
1. INITIAL_BACKOFF (how long to wait after the first failure before retrying)
2. MULTIPLIER (factor with which to multiply backoff after a failed retry)
- 3. MAX_BACKOFF (Upper bound on backoff)
- 4. MIN_CONNECTION_TIMEOUT
+ 3. MAX_BACKOFF (upper bound on backoff)
+ 4. MIN_CONNECT_TIMEOUT (minimum time we're willing to give a connection to
+ complete)
## Proposed Backoff Algorithm
Exponentially back off the start time of connection attempts up to a limit of
-MAX_BACKOFF.
+MAX_BACKOFF, with jitter.
```
ConnectWithBackoff()
current_backoff = INITIAL_BACKOFF
current_deadline = now() + INITIAL_BACKOFF
- while (TryConnect(Max(current_deadline, MIN_CONNECT_TIMEOUT))
+ while (TryConnect(Max(current_deadline, now() + MIN_CONNECT_TIMEOUT))
!= SUCCESS)
SleepUntil(current_deadline)
current_backoff = Min(current_backoff * MULTIPLIER, MAX_BACKOFF)
- current_deadline = now() + current_backoff
-```
-
-## Historical Algorithm in Stubby
-
-Exponentially increase up to a limit of MAX_BACKOFF the intervals between
-connection attempts. This is what stubby 2 uses, and is equivalent if
-TryConnect() fails instantly.
+ current_deadline = now() + current_backoff +
+ UniformRandom(-JITTER * current_backoff, JITTER * current_backoff)
```
-LegacyConnectWithBackoff()
- current_backoff = INITIAL_BACKOFF
- while (TryConnect(MIN_CONNECT_TIMEOUT) != SUCCESS)
- SleepFor(current_backoff)
- current_backoff = Min(current_backoff * MULTIPLIER, MAX_BACKOFF)
-```
-
-The grpc C implementation currently uses this approach with an initial backoff
-of 1 second, multiplier of 2, and maximum backoff of 120 seconds. (This will
-change)
-Stubby, or at least rpc2, uses exactly this algorithm with an initial backoff
-of 1 second, multiplier of 1.2, and a maximum backoff of 120 seconds.
+With specific parameters of
+MIN_CONNECT_TIMEOUT = 20 seconds
+INITIAL_BACKOFF = 1 second
+MULTIPLIER = 1.6
+MAX_BACKOFF = 120 seconds
+JITTER = 0.2
-## Use Cases to Consider
+Implementations with pressing concerns (such as minimizing the number of wakeups
+on a mobile phone) may wish to use a different algorithm, and in particular
+different jitter logic.
-* Client tries to connect to a server which is down for multiple hours, eg for
- maintenance
-* Client tries to connect to a server which is overloaded
-* User is bringing up both a client and a server at the same time
- * In particular, we would like to avoid a large unnecessary delay if the
- client connects to a server which is about to come up
-* Client/server are misconfigured such that connection attempts always fail
- * We want to make sure these don’t put too much load on the server by
- default.
-* Server is overloaded and wants to transiently make clients back off
-* Application has out of band reason to believe a server is back
- * We should consider an out of band mechanism for the client to hint that
- we should short circuit the backoff.
+Alternate implementations must ensure that connection backoffs started at the
+same time disperse, and must not attempt connections substantially more often
+than the above algorithm.
diff --git a/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md
index c3da84377a..3ee5d0f032 100644
--- a/doc/interop-test-descriptions.md
+++ b/doc/interop-test-descriptions.md
@@ -392,6 +392,97 @@ Asserts:
* clients are free to assert that the response payload body contents are zero
and comparing the entire response message against a golden response
+### oauth2_auth_token
+
+Similar to the other auth tests, this test is only for cloud-to-prod path.
+
+This test verifies unary calls succeed in sending messages using an OAuth2 token
+that is obtained out of band. For the purpose of the test, the OAuth2 token is
+actually obtained from the service account credentials via the
+language-specific authorization library.
+
+The difference between this test and the other auth tests is that rather than
+configuring the test client with ServiceAccountCredentials directly, the test
+first uses the authorization library to obtain an authorization token.
+
+The test
+- uses the flag `--service_account_key_file` with the path to a json key file
+downloaded from https://console.developers.google.com. Alternately, if using a
+usable auth implementation, it may specify the file location in the environment
+variable GOOGLE_APPLICATION_CREDENTIALS
+- uses the flag `--oauth_scope` for the oauth scope. For testing against
+grpc-test.sandbox.google.com, "https://www.googleapis.com/auth/xapi.zoo" should
+be passed as the `--oauth_scope`.
+
+Server features:
+* [UnaryCall][]
+* [Compressable Payload][]
+* [Echo Authenticated Username][]
+* [Echo OAuth Scope][]
+
+Procedure:
+ 1. Client uses the auth library to obtain an authorization token
+ 2. Client configures the channel to use AccessTokenCredentials with the access token obtained in step 1.
+ 3. Client calls UnaryCall with the following message
+
+ ```
+ {
+ fill_username: true
+ fill_oauth_scope: true
+ }
+ ```
+
+Asserts:
+* call was successful
+* received SimpleResponse.username is in the json key file used by the auth
+library to obtain the authorization token
+* received SimpleResponse.oauth_scope is in `--oauth_scope`
+
+### per_rpc_creds
+
+Similar to the other auth tests, this test is only for cloud-to-prod path.
+
+This test verifies unary calls succeed in sending messages using an OAuth2 token
+that is obtained out of band. For the purpose of the test, the OAuth2 token is
+actually obtained from the service account credentials via the
+language-specific authorization library.
+
+The test
+- uses the flag `--service_account_key_file` with the path to a json key file
+downloaded from https://console.developers.google.com. Alternately, if using a
+usable auth implementation, it may specify the file location in the environment
+variable GOOGLE_APPLICATION_CREDENTIALS
+- uses the flag `--oauth_scope` for the oauth scope. For testing against
+grpc-test.sandbox.google.com, "https://www.googleapis.com/auth/xapi.zoo" should
+be passed as the `--oauth_scope`.
+
+Server features:
+* [UnaryCall][]
+* [Compressable Payload][]
+* [Echo Authenticated Username][]
+* [Echo OAuth Scope][]
+
+Procedure:
+ 1. Client uses the auth library to obtain an authorization token
+ 2. Client configures the channel with just SSL credentials.
+ 3. Client calls UnaryCall, setting per-call credentials to
+ AccessTokenCredentials with the access token obtained in step 1. The request is
+ the following message
+
+ ```
+ {
+ fill_username: true
+ fill_oauth_scope: true
+ }
+ ```
+
+Asserts:
+* call was successful
+* received SimpleResponse.username is in the json key file used by the auth
+library to obtain the authorization token
+* received SimpleResponse.oauth_scope is in `--oauth_scope`
+
+
### Metadata (TODO: fix name)
Status: Not yet implementable
@@ -560,11 +651,6 @@ Propagation of status code and message (yangg)
Multiple thousand simultaneous calls on same Channel (ctiller)
-OAuth2 tokens + Service Credentials from GCE metadata server (GCE->prod only)
-(abhishek)
-
-OAuth2 tokens + JWT signing key (GCE->prod only) (abhishek)
-
Metadata: client headers, server headers + trailers, binary+ascii
#### Normal priority:
diff --git a/gRPC.podspec b/gRPC.podspec
index bdcbc3f612..34fbccf4e7 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -64,6 +64,7 @@ Pod::Spec.new do |s|
ss.source_files = 'src/core/support/env.h',
'src/core/support/file.h',
'src/core/support/murmur_hash.h',
+ 'src/core/support/stack_lockfree.h',
'src/core/support/grpc_string.h',
'src/core/support/string_win32.h',
'src/core/support/thd_internal.h',
@@ -118,6 +119,7 @@ Pod::Spec.new do |s|
'src/core/support/murmur_hash.c',
'src/core/support/slice.c',
'src/core/support/slice_buffer.c',
+ 'src/core/support/stack_lockfree.c',
'src/core/support/string.c',
'src/core/support/string_posix.c',
'src/core/support/string_win32.c',
@@ -140,6 +142,7 @@ Pod::Spec.new do |s|
'src/core/security/base64.h',
'src/core/security/credentials.h',
'src/core/security/json_token.h',
+ 'src/core/security/jwt_verifier.h',
'src/core/security/secure_endpoint.h',
'src/core/security/secure_transport_setup.h',
'src/core/security/security_connector.h',
@@ -263,6 +266,7 @@ Pod::Spec.new do |s|
'src/core/security/credentials_win32.c',
'src/core/security/google_default_credentials.c',
'src/core/security/json_token.c',
+ 'src/core/security/jwt_verifier.c',
'src/core/security/secure_endpoint.c',
'src/core/security/secure_transport_setup.c',
'src/core/security/security_connector.c',
@@ -355,6 +359,7 @@ Pod::Spec.new do |s|
'src/core/surface/server_chttp2.c',
'src/core/surface/server_create.c',
'src/core/surface/surface_trace.c',
+ 'src/core/surface/version.c',
'src/core/transport/chttp2/alpn.c',
'src/core/transport/chttp2/bin_encoder.c',
'src/core/transport/chttp2/frame_data.c',
@@ -387,6 +392,7 @@ Pod::Spec.new do |s|
ss.private_header_files = 'src/core/support/env.h',
'src/core/support/file.h',
'src/core/support/murmur_hash.h',
+ 'src/core/support/stack_lockfree.h',
'src/core/support/string.h',
'src/core/support/string_win32.h',
'src/core/support/thd_internal.h',
@@ -398,6 +404,7 @@ Pod::Spec.new do |s|
'src/core/security/base64.h',
'src/core/security/credentials.h',
'src/core/security/json_token.h',
+ 'src/core/security/jwt_verifier.h',
'src/core/security/secure_endpoint.h',
'src/core/security/secure_transport_setup.h',
'src/core/security/security_connector.h',
diff --git a/include/grpc++/auth_context.h b/include/grpc++/auth_context.h
new file mode 100644
index 0000000000..c42105b927
--- /dev/null
+++ b/include/grpc++/auth_context.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * 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 GRPCXX_AUTH_CONTEXT_H
+#define GRPCXX_AUTH_CONTEXT_H
+
+#include <vector>
+
+#include <grpc++/auth_property_iterator.h>
+#include <grpc++/config.h>
+
+namespace grpc {
+
+class AuthContext {
+ public:
+ virtual ~AuthContext() {}
+
+ // A peer identity, in general is one or more properties (in which case they
+ // have the same name).
+ virtual std::vector<grpc::string> GetPeerIdentity() const = 0;
+ virtual grpc::string GetPeerIdentityPropertyName() const = 0;
+
+ // Returns all the property values with the given name.
+ virtual std::vector<grpc::string> FindPropertyValues(
+ const grpc::string& name) const = 0;
+
+ // Iteration over all the properties.
+ virtual AuthPropertyIterator begin() const = 0;
+ virtual AuthPropertyIterator end() const = 0;
+};
+
+} // namespace grpc
+
+#endif // GRPCXX_AUTH_CONTEXT_H
+
diff --git a/include/grpc++/auth_property_iterator.h b/include/grpc++/auth_property_iterator.h
new file mode 100644
index 0000000000..c7870c46be
--- /dev/null
+++ b/include/grpc++/auth_property_iterator.h
@@ -0,0 +1,77 @@
+/*
+ *
+ * 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 GRPCXX_AUTH_PROPERTY_ITERATOR_H
+#define GRPCXX_AUTH_PROPERTY_ITERATOR_H
+
+#include <iterator>
+#include <vector>
+
+#include <grpc++/config.h>
+
+struct grpc_auth_context;
+struct grpc_auth_property;
+struct grpc_auth_property_iterator;
+
+namespace grpc {
+class SecureAuthContext;
+
+typedef std::pair<grpc::string, grpc::string> AuthProperty;
+
+class AuthPropertyIterator
+ : public std::iterator<std::input_iterator_tag, const AuthProperty> {
+ public:
+ ~AuthPropertyIterator();
+ AuthPropertyIterator& operator++();
+ AuthPropertyIterator operator++(int);
+ bool operator==(const AuthPropertyIterator& rhs) const;
+ bool operator!=(const AuthPropertyIterator& rhs) const;
+ const AuthProperty operator*();
+
+ protected:
+ AuthPropertyIterator();
+ AuthPropertyIterator(const grpc_auth_property* property,
+ const grpc_auth_property_iterator* iter);
+ private:
+ friend class SecureAuthContext;
+ const grpc_auth_property* property_;
+ // The following items form a grpc_auth_property_iterator.
+ const grpc_auth_context* ctx_;
+ size_t index_;
+ const char* name_;
+};
+
+} // namespace grpc
+
+ #endif // GRPCXX_AUTH_PROPERTY_ITERATOR_H
+
diff --git a/include/grpc++/client_context.h b/include/grpc++/client_context.h
index 5e10875260..7adaaa6e6f 100644
--- a/include/grpc++/client_context.h
+++ b/include/grpc++/client_context.h
@@ -40,12 +40,14 @@
#include <grpc/support/log.h>
#include <grpc/support/time.h>
+#include <grpc++/auth_context.h>
#include <grpc++/config.h>
#include <grpc++/status.h>
#include <grpc++/time.h>
struct grpc_call;
struct grpc_completion_queue;
+struct census_context;
namespace grpc {
@@ -107,6 +109,12 @@ class ClientContext {
creds_ = creds;
}
+ std::shared_ptr<const AuthContext> auth_context() const;
+
+ // Get and set census context
+ void set_census_context(census_context* ccp) { census_context_ = ccp; }
+ census_context* get_census_context() const { return census_context_; }
+
void TryCancel();
private:
@@ -154,6 +162,8 @@ class ClientContext {
gpr_timespec deadline_;
grpc::string authority_;
std::shared_ptr<Credentials> creds_;
+ mutable std::shared_ptr<const AuthContext> auth_context_;
+ census_context* census_context_;
std::multimap<grpc::string, grpc::string> send_initial_metadata_;
std::multimap<grpc::string, grpc::string> recv_initial_metadata_;
std::multimap<grpc::string, grpc::string> trailing_metadata_;
diff --git a/include/grpc++/credentials.h b/include/grpc++/credentials.h
index 7a40cd199d..0eaaefcbca 100644
--- a/include/grpc++/credentials.h
+++ b/include/grpc++/credentials.h
@@ -120,6 +120,12 @@ std::shared_ptr<Credentials> JWTCredentials(const grpc::string& json_key,
std::shared_ptr<Credentials> RefreshTokenCredentials(
const grpc::string& json_refresh_token);
+// Builds access token credentials.
+// access_token is an oauth2 access token that was fetched using an out of band
+// mechanism.
+std::shared_ptr<Credentials> AccessTokenCredentials(
+ const grpc::string& access_token);
+
// Builds IAM credentials.
std::shared_ptr<Credentials> IAMCredentials(
const grpc::string& authorization_token,
diff --git a/src/cpp/server/thread_pool.h b/include/grpc++/fixed_size_thread_pool.h
index 3b70249bf9..9f0cbfbae9 100644
--- a/src/cpp/server/thread_pool.h
+++ b/include/grpc++/fixed_size_thread_pool.h
@@ -45,10 +45,10 @@
namespace grpc {
-class ThreadPool GRPC_FINAL : public ThreadPoolInterface {
+class FixedSizeThreadPool GRPC_FINAL : public ThreadPoolInterface {
public:
- explicit ThreadPool(int num_threads);
- ~ThreadPool();
+ explicit FixedSizeThreadPool(int num_threads);
+ ~FixedSizeThreadPool();
void ScheduleCallback(const std::function<void()>& callback) GRPC_OVERRIDE;
@@ -62,8 +62,6 @@ class ThreadPool GRPC_FINAL : public ThreadPoolInterface {
void ThreadFunc();
};
-ThreadPoolInterface* CreateDefaultThreadPool();
-
} // namespace grpc
#endif // GRPC_INTERNAL_CPP_SERVER_THREAD_POOL_H
diff --git a/include/grpc++/impl/call.h b/include/grpc++/impl/call.h
index 64fa5d6efb..1fa4490779 100644
--- a/include/grpc++/impl/call.h
+++ b/include/grpc++/impl/call.h
@@ -60,6 +60,93 @@ void FillMetadataMap(grpc_metadata_array* arr,
grpc_metadata* FillMetadataArray(
const std::multimap<grpc::string, grpc::string>& metadata);
+/// Per-message write options.
+class WriteOptions {
+ public:
+ WriteOptions() : flags_(0) {}
+ WriteOptions(const WriteOptions& other) : flags_(other.flags_) {}
+
+ /// Clear all flags.
+ inline void Clear() {
+ flags_ = 0;
+ }
+
+ /// Returns raw flags bitset.
+ inline gpr_uint32 flags() const {
+ return flags_;
+ }
+
+ /// Sets flag for the disabling of compression for the next message write.
+ ///
+ /// \sa GRPC_WRITE_NO_COMPRESS
+ inline WriteOptions& set_no_compression() {
+ SetBit(GRPC_WRITE_NO_COMPRESS);
+ return *this;
+ }
+
+ /// Clears flag for the disabling of compression for the next message write.
+ ///
+ /// \sa GRPC_WRITE_NO_COMPRESS
+ inline WriteOptions& clear_no_compression() {
+ ClearBit(GRPC_WRITE_NO_COMPRESS);
+ return *this;
+ }
+
+ /// Get value for the flag indicating whether compression for the next
+ /// message write is forcefully disabled.
+ ///
+ /// \sa GRPC_WRITE_NO_COMPRESS
+ inline bool get_no_compression() const {
+ return GetBit(GRPC_WRITE_NO_COMPRESS);
+ }
+
+ /// Sets flag indicating that the write may be buffered and need not go out on
+ /// the wire immediately.
+ ///
+ /// \sa GRPC_WRITE_BUFFER_HINT
+ inline WriteOptions& set_buffer_hint() {
+ SetBit(GRPC_WRITE_BUFFER_HINT);
+ return *this;
+ }
+
+ /// Clears flag indicating that the write may be buffered and need not go out
+ /// on the wire immediately.
+ ///
+ /// \sa GRPC_WRITE_BUFFER_HINT
+ inline WriteOptions& clear_buffer_hint() {
+ ClearBit(GRPC_WRITE_BUFFER_HINT);
+ return *this;
+ }
+
+ /// Get value for the flag indicating that the write may be buffered and need
+ /// not go out on the wire immediately.
+ ///
+ /// \sa GRPC_WRITE_BUFFER_HINT
+ inline bool get_buffer_hint() const {
+ return GetBit(GRPC_WRITE_BUFFER_HINT);
+ }
+
+ WriteOptions& operator=(const WriteOptions& rhs) {
+ flags_ = rhs.flags_;
+ return *this;
+ }
+
+ private:
+ void SetBit(const gpr_int32 mask) {
+ flags_ |= mask;
+ }
+
+ void ClearBit(const gpr_int32 mask) {
+ flags_ &= ~mask;
+ }
+
+ bool GetBit(const gpr_int32 mask) const {
+ return flags_ & mask;
+ }
+
+ gpr_uint32 flags_;
+};
+
/// Default argument for CallOpSet. I is unused by the class, but can be
/// used for generating multiple names for the same thing.
template <int I>
@@ -104,6 +191,12 @@ class CallOpSendMessage {
public:
CallOpSendMessage() : send_buf_(nullptr), own_buf_(false) {}
+ /// Send \a message using \a options for the write. The \a options are cleared
+ /// after use.
+ template <class M>
+ Status SendMessage(const M& message,
+ const WriteOptions& options) GRPC_MUST_USE_RESULT;
+
template <class M>
Status SendMessage(const M& message) GRPC_MUST_USE_RESULT;
@@ -112,8 +205,10 @@ class CallOpSendMessage {
if (send_buf_ == nullptr) return;
grpc_op* op = &ops[(*nops)++];
op->op = GRPC_OP_SEND_MESSAGE;
- op->flags = 0;
+ op->flags = write_options_.flags();
op->data.send_message = send_buf_;
+ // Flags are per-message: clear them after use.
+ write_options_.Clear();
}
void FinishOp(bool* status, int max_message_size) {
if (own_buf_) grpc_byte_buffer_destroy(send_buf_);
@@ -122,14 +217,22 @@ class CallOpSendMessage {
private:
grpc_byte_buffer* send_buf_;
+ WriteOptions write_options_;
bool own_buf_;
};
template <class M>
-Status CallOpSendMessage::SendMessage(const M& message) {
+Status CallOpSendMessage::SendMessage(const M& message,
+ const WriteOptions& options) {
+ write_options_ = options;
return SerializationTraits<M>::Serialize(message, &send_buf_, &own_buf_);
}
+template <class M>
+Status CallOpSendMessage::SendMessage(const M& message) {
+ return SendMessage(message, WriteOptions());
+}
+
template <class R>
class CallOpRecvMessage {
public:
@@ -172,17 +275,34 @@ class CallOpRecvMessage {
grpc_byte_buffer* recv_buf_;
};
+namespace CallOpGenericRecvMessageHelper {
+class DeserializeFunc {
+ public:
+ virtual Status Deserialize(grpc_byte_buffer* buf, int max_message_size) = 0;
+};
+
+template <class R>
+class DeserializeFuncType GRPC_FINAL : public DeserializeFunc {
+ public:
+ DeserializeFuncType(R* message) : message_(message) {}
+ Status Deserialize(grpc_byte_buffer* buf,
+ int max_message_size) GRPC_OVERRIDE {
+ return SerializationTraits<R>::Deserialize(buf, message_, max_message_size);
+ }
+
+ private:
+ R* message_; // Not a managed pointer because management is external to this
+};
+} // namespace CallOpGenericRecvMessageHelper
+
class CallOpGenericRecvMessage {
public:
CallOpGenericRecvMessage() : got_message(false) {}
template <class R>
void RecvMessage(R* message) {
- deserialize_ = [message](grpc_byte_buffer* buf,
- int max_message_size) -> Status {
- return SerializationTraits<R>::Deserialize(buf, message,
- max_message_size);
- };
+ deserialize_.reset(
+ new CallOpGenericRecvMessageHelper::DeserializeFuncType<R>(message));
}
bool got_message;
@@ -201,7 +321,7 @@ class CallOpGenericRecvMessage {
if (recv_buf_) {
if (*status) {
got_message = true;
- *status = deserialize_(recv_buf_, max_message_size).ok();
+ *status = deserialize_->Deserialize(recv_buf_, max_message_size).ok();
} else {
got_message = false;
grpc_byte_buffer_destroy(recv_buf_);
@@ -210,12 +330,11 @@ class CallOpGenericRecvMessage {
got_message = false;
*status = false;
}
- deserialize_ = DeserializeFunc();
+ deserialize_.reset();
}
private:
- typedef std::function<Status(grpc_byte_buffer*, int)> DeserializeFunc;
- DeserializeFunc deserialize_;
+ std::unique_ptr<CallOpGenericRecvMessageHelper::DeserializeFunc> deserialize_;
grpc_byte_buffer* recv_buf_;
};
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index 6a9e757e77..94ee0b6a4a 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -84,8 +84,8 @@ class Server GRPC_FINAL : public GrpcLibrary, private CallHook {
int max_message_size);
// Register a service. This call does not take ownership of the service.
// The service must exist for the lifetime of the Server instance.
- bool RegisterService(RpcService* service);
- bool RegisterAsyncService(AsynchronousService* service);
+ bool RegisterService(const grpc::string *host, RpcService* service);
+ bool RegisterAsyncService(const grpc::string *host, AsynchronousService* service);
void RegisterAsyncGenericService(AsyncGenericService* service);
// Add a listening port. Can be called multiple times.
int AddListeningPort(const grpc::string& addr, ServerCredentials* creds);
diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h
index ecee475e3e..44ee00eec9 100644
--- a/include/grpc++/server_builder.h
+++ b/include/grpc++/server_builder.h
@@ -58,17 +58,35 @@ class ServerBuilder {
// Register a service. This call does not take ownership of the service.
// The service must exist for the lifetime of the Server instance returned by
// BuildAndStart().
+ // Matches requests with any :authority
void RegisterService(SynchronousService* service);
- // Register an asynchronous service. New calls will be delevered to cq.
+ // Register an asynchronous service.
// This call does not take ownership of the service or completion queue.
// The service and completion queuemust exist for the lifetime of the Server
// instance returned by BuildAndStart().
+ // Matches requests with any :authority
void RegisterAsyncService(AsynchronousService* service);
// Register a generic service.
+ // Matches requests with any :authority
void RegisterAsyncGenericService(AsyncGenericService* service);
+ // Register a service. This call does not take ownership of the service.
+ // The service must exist for the lifetime of the Server instance returned by
+ // BuildAndStart().
+ // Only matches requests with :authority \a host
+ void RegisterService(const grpc::string& host,
+ SynchronousService* service);
+
+ // Register an asynchronous service.
+ // This call does not take ownership of the service or completion queue.
+ // The service and completion queuemust exist for the lifetime of the Server
+ // instance returned by BuildAndStart().
+ // Only matches requests with :authority \a host
+ void RegisterAsyncService(const grpc::string& host,
+ AsynchronousService* service);
+
// Set max message size in bytes.
void SetMaxMessageSize(int max_message_size) {
max_message_size_ = max_message_size;
@@ -98,9 +116,18 @@ class ServerBuilder {
int* selected_port;
};
+ typedef std::unique_ptr<grpc::string> HostString;
+ template <class T> struct NamedService {
+ explicit NamedService(T* s) : service(s) {}
+ NamedService(const grpc::string& h, T *s)
+ : host(new grpc::string(h)), service(s) {}
+ HostString host;
+ T* service;
+ };
+
int max_message_size_;
- std::vector<RpcService*> services_;
- std::vector<AsynchronousService*> async_services_;
+ std::vector<std::unique_ptr<NamedService<RpcService>>> services_;
+ std::vector<std::unique_ptr<NamedService<AsynchronousService>>> async_services_;
std::vector<Port> ports_;
std::vector<ServerCompletionQueue*> cqs_;
std::shared_ptr<ServerCredentials> creds_;
diff --git a/include/grpc++/server_context.h b/include/grpc++/server_context.h
index 326b6a125c..6f094eda3d 100644
--- a/include/grpc++/server_context.h
+++ b/include/grpc++/server_context.h
@@ -35,8 +35,10 @@
#define GRPCXX_SERVER_CONTEXT_H
#include <map>
+#include <memory>
#include <grpc/support/time.h>
+#include <grpc++/auth_context.h>
#include <grpc++/config.h>
#include <grpc++/time.h>
@@ -74,6 +76,10 @@ class CallOpBuffer;
class CompletionQueue;
class Server;
+namespace testing {
+class InteropContextInspector;
+} // namespace testing
+
// Interface of server side rpc context.
class ServerContext {
public:
@@ -91,13 +97,16 @@ class ServerContext {
void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
- bool IsCancelled();
+ bool IsCancelled() const;
const std::multimap<grpc::string, grpc::string>& client_metadata() {
return client_metadata_;
}
+ std::shared_ptr<const AuthContext> auth_context() const;
+
private:
+ friend class ::grpc::testing::InteropContextInspector;
friend class ::grpc::Server;
template <class W, class R>
friend class ::grpc::ServerAsyncReader;
@@ -133,12 +142,15 @@ class ServerContext {
ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
size_t metadata_count);
+ void set_call(grpc_call* call);
+
CompletionOp* completion_op_;
gpr_timespec deadline_;
grpc_call* call_;
CompletionQueue* cq_;
bool sent_initial_metadata_;
+ mutable std::shared_ptr<const AuthContext> auth_context_;
std::multimap<grpc::string, grpc::string> client_metadata_;
std::multimap<grpc::string, grpc::string> initial_metadata_;
std::multimap<grpc::string, grpc::string> trailing_metadata_;
diff --git a/include/grpc++/stream.h b/include/grpc++/stream.h
index dd5e52d6d3..3903f2ec06 100644
--- a/include/grpc++/stream.h
+++ b/include/grpc++/stream.h
@@ -79,7 +79,11 @@ class WriterInterface {
// Blocking write msg to the stream. Returns true on success.
// Returns false when the stream has been closed.
- virtual bool Write(const W& msg) = 0;
+ virtual bool Write(const W& msg, const WriteOptions& options) = 0;
+
+ inline bool Write(const W& msg) {
+ return Write(msg, WriteOptions());
+ }
};
template <class R>
@@ -168,9 +172,10 @@ class ClientWriter : public ClientWriterInterface<W> {
cq_.Pluck(&ops);
}
- bool Write(const W& msg) GRPC_OVERRIDE {
+ using WriterInterface<W>::Write;
+ bool Write(const W& msg, const WriteOptions& options) GRPC_OVERRIDE {
CallOpSet<CallOpSendMessage> ops;
- if (!ops.SendMessage(msg).ok()) {
+ if (!ops.SendMessage(msg, options).ok()) {
return false;
}
call_.PerformOps(&ops);
@@ -246,9 +251,10 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> {
return cq_.Pluck(&ops) && ops.got_message;
}
- bool Write(const W& msg) GRPC_OVERRIDE {
+ using WriterInterface<W>::Write;
+ bool Write(const W& msg, const WriteOptions& options) GRPC_OVERRIDE {
CallOpSet<CallOpSendMessage> ops;
- if (!ops.SendMessage(msg).ok()) return false;
+ if (!ops.SendMessage(msg, options).ok()) return false;
call_.PerformOps(&ops);
return cq_.Pluck(&ops);
}
@@ -317,9 +323,10 @@ class ServerWriter GRPC_FINAL : public WriterInterface<W> {
call_->cq()->Pluck(&ops);
}
- bool Write(const W& msg) GRPC_OVERRIDE {
+ using WriterInterface<W>::Write;
+ bool Write(const W& msg, const WriteOptions& options) GRPC_OVERRIDE {
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> ops;
- if (!ops.SendMessage(msg).ok()) {
+ if (!ops.SendMessage(msg, options).ok()) {
return false;
}
if (!ctx_->sent_initial_metadata_) {
@@ -359,9 +366,10 @@ class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>,
return call_->cq()->Pluck(&ops) && ops.got_message;
}
- bool Write(const W& msg) GRPC_OVERRIDE {
+ using WriterInterface<W>::Write;
+ bool Write(const W& msg, const WriteOptions& options) GRPC_OVERRIDE {
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> ops;
- if (!ops.SendMessage(msg).ok()) {
+ if (!ops.SendMessage(msg, options).ok()) {
return false;
}
if (!ctx_->sent_initial_metadata_) {
diff --git a/include/grpc++/thread_pool_interface.h b/include/grpc++/thread_pool_interface.h
index ead307f6a2..ac4458d530 100644
--- a/include/grpc++/thread_pool_interface.h
+++ b/include/grpc++/thread_pool_interface.h
@@ -47,6 +47,8 @@ class ThreadPoolInterface {
virtual void ScheduleCallback(const std::function<void()>& callback) = 0;
};
+ThreadPoolInterface* CreateDefaultThreadPool();
+
} // namespace grpc
#endif // GRPCXX_THREAD_POOL_INTERFACE_H
diff --git a/include/grpc/census.h b/include/grpc/census.h
index b2049b3289..3fc07affc8 100644
--- a/include/grpc/census.h
+++ b/include/grpc/census.h
@@ -61,6 +61,10 @@ enum census_functions {
int census_initialize(int functions);
void census_shutdown();
+/* If any census feature has been initialized, this funtion will return a
+ * non-zero value. */
+int census_available();
+
/* Internally, Census relies on a context, which should be propagated across
* RPC's. From the RPC subsystems viewpoint, this is an opaque data structure.
* A context must be used as the first argument to all other census
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index b5b25a68e2..ad0bf7d663 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -357,6 +357,9 @@ void grpc_init(void);
destroyed. */
void grpc_shutdown(void);
+/** Return a string representing the current version of grpc */
+const char *grpc_version_string(void);
+
/** Create a completion queue */
grpc_completion_queue *grpc_completion_queue_create(void);
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 7a6aa66670..37d66c04ae 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -51,6 +51,11 @@ typedef struct grpc_credentials grpc_credentials;
The creator of the credentials object is responsible for its release. */
void grpc_credentials_release(grpc_credentials *creds);
+/* Environment variable that points to the google default application
+ credentials json key or refresh token. Used in the
+ grpc_google_default_credentials_create function. */
+#define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS"
+
/* Creates default credentials to connect to a google gRPC service.
WARNING: Do NOT use this credentials to connect to a non-google service as
this could result in an oauth2 token leak. */
@@ -126,13 +131,18 @@ grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
grpc_credentials *grpc_refresh_token_credentials_create(
const char *json_refresh_token);
-/* Creates a fake transport security credentials object for testing. */
-grpc_credentials *grpc_fake_transport_security_credentials_create(void);
+/* Creates an Oauth2 Access Token credentials with an access token that was
+ aquired by an out of band mechanism. */
+grpc_credentials *grpc_access_token_credentials_create(
+ const char *access_token);
/* Creates an IAM credentials object. */
grpc_credentials *grpc_iam_credentials_create(const char *authorization_token,
const char *authority_selector);
+/* Creates a fake transport security credentials object for testing. */
+grpc_credentials *grpc_fake_transport_security_credentials_create(void);
+
/* --- Secure channel creation. --- */
/* The caller of the secure_channel_create functions may override the target
@@ -243,8 +253,12 @@ const char *grpc_auth_context_peer_identity_property_name(
/* Returns 1 if the peer is authenticated, 0 otherwise. */
int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
-/* Gets the auth context from the call. */
-const grpc_auth_context *grpc_call_auth_context(grpc_call *call);
+/* Gets the auth context from the call. Caller needs to call
+ grpc_auth_context_release on the returned context. */
+grpc_auth_context *grpc_call_auth_context(grpc_call *call);
+
+/* Releases the auth context returned from grpc_call_auth_context. */
+void grpc_auth_context_release(grpc_auth_context *context);
#ifdef __cplusplus
}
diff --git a/include/grpc/support/port_platform.h b/include/grpc/support/port_platform.h
index d3cfee113d..a5d1b62702 100644
--- a/include/grpc/support/port_platform.h
+++ b/include/grpc/support/port_platform.h
@@ -82,6 +82,7 @@
#define GPR_WIN32_ATOMIC 1
#define GPR_MSVC_TLS 1
#endif
+#define GPR_WINDOWS_CRASH_HANDLER 1
#elif defined(_WIN32) || defined(WIN32)
#define GPR_ARCH_32 1
#define GPR_WIN32 1
@@ -94,6 +95,7 @@
#define GPR_WIN32_ATOMIC 1
#define GPR_MSVC_TLS 1
#endif
+#define GPR_WINDOWS_CRASH_HANDLER 1
#elif defined(ANDROID) || defined(__ANDROID__)
#define GPR_ANDROID 1
#define GPR_ARCH_32 1
diff --git a/include/grpc/support/time.h b/include/grpc/support/time.h
index 1fd3181859..a5c947dfc8 100644
--- a/include/grpc/support/time.h
+++ b/include/grpc/support/time.h
@@ -46,8 +46,8 @@ extern "C" {
#endif
typedef struct gpr_timespec {
- time_t tv_sec;
- int tv_nsec;
+ time_t tv_sec;
+ int tv_nsec;
} gpr_timespec;
/* Time constants. */
@@ -62,8 +62,20 @@ extern const gpr_timespec gpr_inf_past; /* The far past. */
#define GPR_NS_PER_US 1000
#define GPR_US_PER_MS 1000
-/* Return the current time measured from the system's default epoch. */
-gpr_timespec gpr_now(void);
+/* The clocks we support. */
+typedef enum {
+ /* Monotonic clock. Epoch undefined. Always moves forwards. */
+ GPR_CLOCK_MONOTONIC = 0,
+ /* Realtime clock. May jump forwards or backwards. Settable by
+ the system administrator. Has its epoch at 0:00:00 UTC 1 Jan 1970. */
+ GPR_CLOCK_REALTIME
+} gpr_clock_type;
+
+/* initialize time subsystem */
+void gpr_time_init(void);
+
+/* Return the current time measured from the given clocks epoch. */
+gpr_timespec gpr_now(gpr_clock_type clock);
/* Return -ve, 0, or +ve according to whether a < b, a == b, or a > b
respectively. */
@@ -100,4 +112,4 @@ double gpr_timespec_to_micros(gpr_timespec t);
}
#endif
-#endif /* GRPC_SUPPORT_TIME_H */
+#endif /* GRPC_SUPPORT_TIME_H */
diff --git a/include/grpc/support/useful.h b/include/grpc/support/useful.h
index e1ce0455c6..3842611590 100644
--- a/include/grpc/support/useful.h
+++ b/include/grpc/support/useful.h
@@ -52,4 +52,24 @@
b = x; \
} while (0)
+/** Set the \a n-th bit of \a i (a mutable pointer). */
+#define GPR_BITSET(i, n) ((*(i)) |= (1u << (n)))
+
+/** Clear the \a n-th bit of \a i (a mutable pointer). */
+#define GPR_BITCLEAR(i, n) ((*(i)) &= ~(1u << (n)))
+
+/** Get the \a n-th bit of \a i */
+#define GPR_BITGET(i, n) (((i) & (1u << (n))) != 0)
+
+#define GPR_INTERNAL_HEXDIGIT_BITCOUNT(x) \
+ ((x) - (((x) >> 1) & 0x77777777) - (((x) >> 2) & 0x33333333) - \
+ (((x) >> 3) & 0x11111111))
+
+/** Returns number of bits set in bitset \a i */
+#define GPR_BITCOUNT(i) \
+ (((GPR_INTERNAL_HEXDIGIT_BITCOUNT(i) + \
+ (GPR_INTERNAL_HEXDIGIT_BITCOUNT(i) >> 4)) & \
+ 0x0f0f0f0f) % \
+ 255)
+
#endif /* GRPC_SUPPORT_USEFUL_H */
diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc
index ccb0b688b6..1910e9bd2d 100644
--- a/src/compiler/csharp_generator.cc
+++ b/src/compiler/csharp_generator.cc
@@ -257,7 +257,7 @@ void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) {
}
void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
- out->Print("// client-side stub interface\n");
+ out->Print("// client interface\n");
out->Print("public interface $name$\n", "name",
GetClientInterfaceName(service));
out->Print("{\n");
@@ -269,7 +269,7 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method
out->Print(
- "$response$ $methodname$($request$ request, CancellationToken token = default(CancellationToken));\n",
+ "$response$ $methodname$($request$ request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
@@ -280,7 +280,7 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
method_name += "Async"; // prevent name clash with synchronous method.
}
out->Print(
- "$returntype$ $methodname$($request_maybe$CancellationToken token = default(CancellationToken));\n",
+ "$returntype$ $methodname$($request_maybe$Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
@@ -312,7 +312,7 @@ void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) {
void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
out->Print("// client stub\n");
out->Print(
- "public class $name$ : AbstractStub<$name$, StubConfiguration>, $interface$\n",
+ "public class $name$ : ClientBase, $interface$\n",
"name", GetClientClassName(service), "interface",
GetClientInterfaceName(service));
out->Print("{\n");
@@ -320,12 +320,7 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
// constructors
out->Print(
- "public $name$(Channel channel) : this(channel, StubConfiguration.Default)\n",
- "name", GetClientClassName(service));
- out->Print("{\n");
- out->Print("}\n");
- out->Print(
- "public $name$(Channel channel, StubConfiguration config) : base(channel, config)\n",
+ "public $name$(Channel channel) : base(channel)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
@@ -337,16 +332,16 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method
out->Print(
- "public $response$ $methodname$($request$ request, CancellationToken token = default(CancellationToken))\n",
+ "public $response$ $methodname$($request$ request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("{\n");
out->Indent();
- out->Print("var call = CreateCall($servicenamefield$, $methodfield$);\n",
+ out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method));
- out->Print("return Calls.BlockingUnaryCall(call, request, token);\n");
+ out->Print("return Calls.BlockingUnaryCall(call, request, cancellationToken);\n");
out->Outdent();
out->Print("}\n");
}
@@ -356,28 +351,28 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
method_name += "Async"; // prevent name clash with synchronous method.
}
out->Print(
- "public $returntype$ $methodname$($request_maybe$CancellationToken token = default(CancellationToken))\n",
+ "public $returntype$ $methodname$($request_maybe$Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
- out->Print("var call = CreateCall($servicenamefield$, $methodfield$);\n",
+ out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method));
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
- out->Print("return Calls.AsyncUnaryCall(call, request, token);\n");
+ out->Print("return Calls.AsyncUnaryCall(call, request, cancellationToken);\n");
break;
case METHODTYPE_CLIENT_STREAMING:
- out->Print("return Calls.AsyncClientStreamingCall(call, token);\n");
+ out->Print("return Calls.AsyncClientStreamingCall(call, cancellationToken);\n");
break;
case METHODTYPE_SERVER_STREAMING:
out->Print(
- "return Calls.AsyncServerStreamingCall(call, request, token);\n");
+ "return Calls.AsyncServerStreamingCall(call, request, cancellationToken);\n");
break;
case METHODTYPE_BIDI_STREAMING:
- out->Print("return Calls.AsyncDuplexStreamingCall(call, token);\n");
+ out->Print("return Calls.AsyncDuplexStreamingCall(call, cancellationToken);\n");
break;
default:
GOOGLE_LOG(FATAL)<< "Can't get here.";
@@ -423,9 +418,9 @@ void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) {
}
void GenerateNewStubMethods(Printer* out, const ServiceDescriptor *service) {
- out->Print("// creates a new client stub\n");
- out->Print("public static $interface$ NewStub(Channel channel)\n",
- "interface", GetClientInterfaceName(service));
+ out->Print("// creates a new client\n");
+ out->Print("public static $classname$ NewClient(Channel channel)\n",
+ "classname", GetClientClassName(service));
out->Print("{\n");
out->Indent();
out->Print("return new $classname$(channel);\n", "classname",
@@ -433,17 +428,6 @@ void GenerateNewStubMethods(Printer* out, const ServiceDescriptor *service) {
out->Outdent();
out->Print("}\n");
out->Print("\n");
-
- out->Print("// creates a new client stub\n");
- out->Print(
- "public static $interface$ NewStub(Channel channel, StubConfiguration config)\n",
- "interface", GetClientInterfaceName(service));
- out->Print("{\n");
- out->Indent();
- out->Print("return new $classname$(channel, config);\n", "classname",
- GetClientClassName(service));
- out->Outdent();
- out->Print("}\n");
}
void GenerateService(Printer* out, const ServiceDescriptor *service) {
diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc
index 79a84b4a7a..711d0d5870 100644
--- a/src/compiler/objective_c_generator.cc
+++ b/src/compiler/objective_c_generator.cc
@@ -57,34 +57,34 @@ void PrintProtoRpcDeclarationAsPragma(Printer *printer,
vars["server_stream"] = method->server_streaming() ? "stream " : "";
printer->Print(vars,
- "#pragma mark $method_name$($client_stream$$request_type$)"
- " returns ($server_stream$$response_type$)\n\n");
+ "#pragma mark $method_name$($client_stream$$request_type$)"
+ " returns ($server_stream$$response_type$)\n\n");
}
-void PrintMethodSignature(Printer *printer,
- const MethodDescriptor *method,
- const map<string, string>& vars) {
+void PrintMethodSignature(Printer *printer, const MethodDescriptor *method,
+ const map<string, string> &vars) {
// TODO(jcanizales): Print method comments.
printer->Print(vars, "- ($return_type$)$method_name$With");
if (method->client_streaming()) {
- printer->Print("RequestsWriter:(id<GRXWriter>)requestWriter");
+ printer->Print("RequestsWriter:(GRXWriter *)requestWriter");
} else {
printer->Print(vars, "Request:($request_class$ *)request");
}
// TODO(jcanizales): Put this on a new line and align colons.
if (method->server_streaming()) {
- printer->Print(vars, " eventHandler:(void(^)(BOOL done, "
- "$response_class$ *response, NSError *error))eventHandler");
+ printer->Print(vars,
+ " eventHandler:(void(^)(BOOL done, "
+ "$response_class$ *response, NSError *error))eventHandler");
} else {
- printer->Print(vars, " handler:(void(^)($response_class$ *response, "
- "NSError *error))handler");
+ printer->Print(vars,
+ " handler:(void(^)($response_class$ *response, "
+ "NSError *error))handler");
}
}
-void PrintSimpleSignature(Printer *printer,
- const MethodDescriptor *method,
+void PrintSimpleSignature(Printer *printer, const MethodDescriptor *method,
map<string, string> vars) {
vars["method_name"] =
grpc_generator::LowercaseFirstLetter(vars["method_name"]);
@@ -92,8 +92,7 @@ void PrintSimpleSignature(Printer *printer,
PrintMethodSignature(printer, method, vars);
}
-void PrintAdvancedSignature(Printer *printer,
- const MethodDescriptor *method,
+void PrintAdvancedSignature(Printer *printer, const MethodDescriptor *method,
map<string, string> vars) {
vars["method_name"] = "RPCTo" + vars["method_name"];
vars["return_type"] = "ProtoRPC *";
@@ -101,15 +100,16 @@ void PrintAdvancedSignature(Printer *printer,
}
inline map<string, string> GetMethodVars(const MethodDescriptor *method) {
- return {{ "method_name", method->name() },
- { "request_type", method->input_type()->name() },
- { "response_type", method->output_type()->name() },
- { "request_class", ClassName(method->input_type()) },
- { "response_class", ClassName(method->output_type()) }};
+ map<string, string> res;
+ res["method_name"] = method->name();
+ res["request_type"] = method->input_type()->name();
+ res["response_type"] = method->output_type()->name();
+ res["request_class"] = ClassName(method->input_type());
+ res["response_class"] = ClassName(method->output_type());
+ return res;
}
-void PrintMethodDeclarations(Printer *printer,
- const MethodDescriptor *method) {
+void PrintMethodDeclarations(Printer *printer, const MethodDescriptor *method) {
map<string, string> vars = GetMethodVars(method);
PrintProtoRpcDeclarationAsPragma(printer, method, vars);
@@ -120,8 +120,7 @@ void PrintMethodDeclarations(Printer *printer,
printer->Print(";\n\n\n");
}
-void PrintSimpleImplementation(Printer *printer,
- const MethodDescriptor *method,
+void PrintSimpleImplementation(Printer *printer, const MethodDescriptor *method,
map<string, string> vars) {
printer->Print("{\n");
printer->Print(vars, " [[self RPCTo$method_name$With");
@@ -178,7 +177,7 @@ void PrintMethodImplementations(Printer *printer,
PrintAdvancedImplementation(printer, method, vars);
}
-} // namespace
+} // namespace
string GetHeader(const ServiceDescriptor *service) {
string output;
@@ -186,7 +185,7 @@ string GetHeader(const ServiceDescriptor *service) {
// Scope the output stream so it closes and finalizes output to the string.
grpc::protobuf::io::StringOutputStream output_stream(&output);
Printer printer(&output_stream, '$');
-
+
printer.Print("@protocol GRXWriteable;\n");
printer.Print("@protocol GRXWriter;\n\n");
@@ -199,12 +198,15 @@ string GetHeader(const ServiceDescriptor *service) {
}
printer.Print("@end\n\n");
- printer.Print("// Basic service implementation, over gRPC, that only does"
+ printer.Print(
+ "// Basic service implementation, over gRPC, that only does"
" marshalling and parsing.\n");
- printer.Print(vars, "@interface $service_class$ :"
- " ProtoService<$service_class$>\n");
- printer.Print("- (instancetype)initWithHost:(NSString *)host"
- " NS_DESIGNATED_INITIALIZER;\n");
+ printer.Print(vars,
+ "@interface $service_class$ :"
+ " ProtoService<$service_class$>\n");
+ printer.Print(
+ "- (instancetype)initWithHost:(NSString *)host"
+ " NS_DESIGNATED_INITIALIZER;\n");
printer.Print("@end\n");
}
return output;
@@ -222,18 +224,20 @@ string GetSource(const ServiceDescriptor *service) {
{"package", service->file()->package()}};
printer.Print(vars,
- "static NSString *const kPackageName = @\"$package$\";\n");
- printer.Print(vars,
- "static NSString *const kServiceName = @\"$service_name$\";\n\n");
+ "static NSString *const kPackageName = @\"$package$\";\n");
+ printer.Print(
+ vars, "static NSString *const kServiceName = @\"$service_name$\";\n\n");
printer.Print(vars, "@implementation $service_class$\n\n");
-
+
printer.Print("// Designated initializer\n");
printer.Print("- (instancetype)initWithHost:(NSString *)host {\n");
- printer.Print(" return (self = [super initWithHost:host"
+ printer.Print(
+ " return (self = [super initWithHost:host"
" packageName:kPackageName serviceName:kServiceName]);\n");
printer.Print("}\n\n");
- printer.Print("// Override superclass initializer to disallow different"
+ printer.Print(
+ "// Override superclass initializer to disallow different"
" package and service names.\n");
printer.Print("- (instancetype)initWithHost:(NSString *)host\n");
printer.Print(" packageName:(NSString *)packageName\n");
@@ -250,4 +254,4 @@ string GetSource(const ServiceDescriptor *service) {
return output;
}
-} // namespace grpc_objective_c_generator
+} // namespace grpc_objective_c_generator
diff --git a/src/core/census/grpc_context.c b/src/core/census/grpc_context.c
index cf2353199f..0ed63469b6 100644
--- a/src/core/census/grpc_context.c
+++ b/src/core/census/grpc_context.c
@@ -34,12 +34,28 @@
#include <grpc/census.h>
#include "src/core/census/grpc_context.h"
-void *grpc_census_context_create() {
- census_context *context;
- census_context_deserialize(NULL, &context);
- return (void *)context;
+static void grpc_census_context_destroy(void *context) {
+ census_context_destroy((census_context *)context);
}
-void grpc_census_context_destroy(void *context) {
- census_context_destroy((census_context *)context);
+void grpc_census_call_set_context(grpc_call *call, census_context *context) {
+ if (!census_available()) {
+ return;
+ }
+ if (context == NULL) {
+ if (grpc_call_is_client(call)) {
+ census_context *context_ptr;
+ census_context_deserialize(NULL, &context_ptr);
+ grpc_call_context_set(call, GRPC_CONTEXT_TRACING, context_ptr,
+ grpc_census_context_destroy);
+ } else {
+ /* TODO(aveitch): server side context code to be implemented. */
+ }
+ } else {
+ grpc_call_context_set(call, GRPC_CONTEXT_TRACING, context, NULL);
+ }
+}
+
+census_context *grpc_census_call_get_context(grpc_call *call) {
+ return (census_context *)grpc_call_context_get(call, GRPC_CONTEXT_TRACING);
}
diff --git a/src/core/census/grpc_context.h b/src/core/census/grpc_context.h
index f610f6ce21..4637e7218e 100644
--- a/src/core/census/grpc_context.h
+++ b/src/core/census/grpc_context.h
@@ -36,7 +36,22 @@
#ifndef CENSUS_GRPC_CONTEXT_H
#define CENSUS_GRPC_CONTEXT_H
-void *grpc_census_context_create();
-void grpc_census_context_destroy(void *context);
+#include <grpc/census.h>
+#include "src/core/surface/call.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Set census context for the call; Must be called before first call to
+ grpc_call_start_batch(). */
+void grpc_census_call_set_context(grpc_call *call, census_context *context);
+
+/* Retrieve the calls current census context. */
+census_context *grpc_census_call_get_context(grpc_call *call);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* CENSUS_GRPC_CONTEXT_H */
diff --git a/src/core/census/initialize.c b/src/core/census/initialize.c
index 057ac78ee7..8016520641 100644
--- a/src/core/census/initialize.c
+++ b/src/core/census/initialize.c
@@ -48,3 +48,5 @@ int census_initialize(int functions) {
}
void census_shutdown() { census_fns_enabled = CENSUS_NONE; }
+
+int census_available() { return (census_fns_enabled != CENSUS_NONE); }
diff --git a/src/core/channel/census_filter.c b/src/core/channel/census_filter.c
index 83b7682848..d996c3475e 100644
--- a/src/core/channel/census_filter.c
+++ b/src/core/channel/census_filter.c
@@ -151,7 +151,7 @@ static void client_init_call_elem(grpc_call_element* elem,
call_data* d = elem->call_data;
GPR_ASSERT(d != NULL);
init_rpc_stats(&d->stats);
- d->start_ts = gpr_now();
+ d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
d->op_id = census_tracing_start_op();
if (initial_op) client_mutate_op(elem, initial_op);
}
@@ -169,7 +169,7 @@ static void server_init_call_elem(grpc_call_element* elem,
call_data* d = elem->call_data;
GPR_ASSERT(d != NULL);
init_rpc_stats(&d->stats);
- d->start_ts = gpr_now();
+ d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
d->op_id = census_tracing_start_op();
if (initial_op) server_mutate_op(elem, initial_op);
}
@@ -177,8 +177,8 @@ static void server_init_call_elem(grpc_call_element* elem,
static void server_destroy_call_elem(grpc_call_element* elem) {
call_data* d = elem->call_data;
GPR_ASSERT(d != NULL);
- d->stats.elapsed_time_ms =
- gpr_timespec_to_micros(gpr_time_sub(gpr_now(), d->start_ts));
+ d->stats.elapsed_time_ms = gpr_timespec_to_micros(
+ gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), d->start_ts));
census_record_rpc_server_stats(d->op_id, &d->stats);
census_tracing_end_op(d->op_id);
}
@@ -197,7 +197,7 @@ static void destroy_channel_elem(grpc_channel_element* elem) {
channel_data* chand = elem->channel_data;
GPR_ASSERT(chand != NULL);
if (chand->path_str != NULL) {
- grpc_mdstr_unref(chand->path_str);
+ GRPC_MDSTR_UNREF(chand->path_str);
}
}
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c
index 871e970eb8..f890f99237 100644
--- a/src/core/channel/client_channel.c
+++ b/src/core/channel/client_channel.c
@@ -427,7 +427,7 @@ static void cc_on_config_changed(void *arg, int iomgr_success) {
GRPC_RESOLVER_REF(resolver, "channel-next");
gpr_mu_unlock(&chand->mu_config);
GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
- grpc_resolver_next(chand->resolver, &chand->incoming_configuration,
+ grpc_resolver_next(resolver, &chand->incoming_configuration,
&chand->on_config_changed);
GRPC_RESOLVER_UNREF(resolver, "channel-next");
} else {
diff --git a/src/core/channel/http_client_filter.c b/src/core/channel/http_client_filter.c
index 581eb13f58..63e4912397 100644
--- a/src/core/channel/http_client_filter.c
+++ b/src/core/channel/http_client_filter.c
@@ -108,13 +108,13 @@ static void hc_mutate_op(grpc_call_element *elem,
/* Send : prefixed headers, which have to be before any application
layer headers. */
grpc_metadata_batch_add_head(&op->data.metadata, &calld->method,
- grpc_mdelem_ref(channeld->method));
+ GRPC_MDELEM_REF(channeld->method));
grpc_metadata_batch_add_head(&op->data.metadata, &calld->scheme,
- grpc_mdelem_ref(channeld->scheme));
+ GRPC_MDELEM_REF(channeld->scheme));
grpc_metadata_batch_add_tail(&op->data.metadata, &calld->te_trailers,
- grpc_mdelem_ref(channeld->te_trailers));
+ GRPC_MDELEM_REF(channeld->te_trailers));
grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type,
- grpc_mdelem_ref(channeld->content_type));
+ GRPC_MDELEM_REF(channeld->content_type));
break;
}
}
@@ -196,11 +196,11 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */
channel_data *channeld = elem->channel_data;
- grpc_mdelem_unref(channeld->te_trailers);
- grpc_mdelem_unref(channeld->method);
- grpc_mdelem_unref(channeld->scheme);
- grpc_mdelem_unref(channeld->content_type);
- grpc_mdelem_unref(channeld->status);
+ GRPC_MDELEM_UNREF(channeld->te_trailers);
+ GRPC_MDELEM_UNREF(channeld->method);
+ GRPC_MDELEM_UNREF(channeld->scheme);
+ GRPC_MDELEM_UNREF(channeld->content_type);
+ GRPC_MDELEM_UNREF(channeld->status);
}
const grpc_channel_filter grpc_http_client_filter = {
diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c
index db0bf590c6..a6cbb5a7f4 100644
--- a/src/core/channel/http_server_filter.c
+++ b/src/core/channel/http_server_filter.c
@@ -129,9 +129,9 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
/* translate host to :authority since :authority may be
omitted */
grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
- channeld->mdctx, grpc_mdstr_ref(channeld->authority_key),
- grpc_mdstr_ref(md->value));
- grpc_mdelem_unref(md);
+ channeld->mdctx, GRPC_MDSTR_REF(channeld->authority_key),
+ GRPC_MDSTR_REF(md->value));
+ GRPC_MDELEM_UNREF(md);
return authority;
} else {
return md;
@@ -193,7 +193,7 @@ static void hs_mutate_op(grpc_call_element *elem,
if (op->type != GRPC_OP_METADATA) continue;
calld->sent_status = 1;
grpc_metadata_batch_add_head(&op->data.metadata, &calld->status,
- grpc_mdelem_ref(channeld->status_ok));
+ GRPC_MDELEM_REF(channeld->status_ok));
break;
}
}
@@ -264,17 +264,17 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */
channel_data *channeld = elem->channel_data;
- grpc_mdelem_unref(channeld->te_trailers);
- grpc_mdelem_unref(channeld->status_ok);
- grpc_mdelem_unref(channeld->status_not_found);
- grpc_mdelem_unref(channeld->method_post);
- grpc_mdelem_unref(channeld->http_scheme);
- grpc_mdelem_unref(channeld->https_scheme);
- grpc_mdelem_unref(channeld->grpc_scheme);
- grpc_mdelem_unref(channeld->content_type);
- grpc_mdstr_unref(channeld->path_key);
- grpc_mdstr_unref(channeld->authority_key);
- grpc_mdstr_unref(channeld->host_key);
+ GRPC_MDELEM_UNREF(channeld->te_trailers);
+ GRPC_MDELEM_UNREF(channeld->status_ok);
+ GRPC_MDELEM_UNREF(channeld->status_not_found);
+ GRPC_MDELEM_UNREF(channeld->method_post);
+ GRPC_MDELEM_UNREF(channeld->http_scheme);
+ GRPC_MDELEM_UNREF(channeld->https_scheme);
+ GRPC_MDELEM_UNREF(channeld->grpc_scheme);
+ GRPC_MDELEM_UNREF(channeld->content_type);
+ GRPC_MDSTR_UNREF(channeld->path_key);
+ GRPC_MDSTR_UNREF(channeld->authority_key);
+ GRPC_MDSTR_UNREF(channeld->host_key);
}
const grpc_channel_filter grpc_http_server_filter = {
diff --git a/src/core/client_config/lb_policies/pick_first.h b/src/core/client_config/lb_policies/pick_first.h
index 94c2a9f0c7..31394985e5 100644
--- a/src/core/client_config/lb_policies/pick_first.h
+++ b/src/core/client_config/lb_policies/pick_first.h
@@ -36,6 +36,8 @@
#include "src/core/client_config/lb_policy.h"
+/** Returns a load balancing policy instance that picks up the first subchannel
+ * from \a subchannels to succesfully connect */
grpc_lb_policy *grpc_create_pick_first_lb_policy(grpc_subchannel **subchannels,
size_t num_subchannels);
diff --git a/src/core/client_config/resolvers/zookeeper_resolver.c b/src/core/client_config/resolvers/zookeeper_resolver.c
index 758ca4d7bc..a0db6059b4 100644
--- a/src/core/client_config/resolvers/zookeeper_resolver.c
+++ b/src/core/client_config/resolvers/zookeeper_resolver.c
@@ -207,7 +207,6 @@ static char *zookeeper_parse_address(char *buffer, int buffer_len) {
grpc_json *json;
grpc_json *cur;
- gpr_log(GPR_INFO, buffer);
address = NULL;
json = grpc_json_parse_string_with_len(buffer, buffer_len);
if (json != NULL) {
@@ -231,7 +230,6 @@ static char *zookeeper_parse_address(char *buffer, int buffer_len) {
strcat(address, host);
strcat(address, ":");
strcat(address, port);
- gpr_log(GPR_INFO, address);
}
grpc_json_destroy(json);
}
@@ -259,7 +257,6 @@ static void zookeeper_resolve_address(zookeeper_resolver *r) {
/* Get zookeeper node of given path r->name
If not containing address(i.e. service node), get its children */
- gpr_log(GPR_INFO, r->name);
status = zoo_get(r->zookeeper_handle, r->name, GRPC_ZOOKEEPER_WATCH,
buffer, &buffer_len, NULL);
if (!status) {
@@ -291,7 +288,6 @@ static void zookeeper_resolve_address(zookeeper_resolver *r) {
strcat(path, r->name);
strcat(path, "/");
strcat(path, children.data[i]);
- gpr_log(GPR_INFO, path);
memset(buffer, 0, GRPC_MAX_ZOOKEEPER_BUFFER_SIZE);
status = zoo_get(r->zookeeper_handle, path, GRPC_ZOOKEEPER_WATCH,
buffer, &buffer_len, NULL);
diff --git a/src/core/client_config/subchannel.c b/src/core/client_config/subchannel.c
index 6cf9062ab0..8cdad1015f 100644
--- a/src/core/client_config/subchannel.c
+++ b/src/core/client_config/subchannel.c
@@ -300,7 +300,7 @@ static void continue_connect(grpc_subchannel *c) {
}
static void start_connect(grpc_subchannel *c) {
- gpr_timespec now = gpr_now();
+ gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
c->next_attempt = now;
c->backoff_delta = gpr_time_from_seconds(1);
@@ -585,7 +585,7 @@ static void subchannel_connected(void *arg, int iomgr_success) {
c->have_alarm = 1;
c->next_attempt = gpr_time_add(c->next_attempt, c->backoff_delta);
c->backoff_delta = gpr_time_add(c->backoff_delta, c->backoff_delta);
- grpc_alarm_init(&c->alarm, c->next_attempt, on_alarm, c, gpr_now());
+ grpc_alarm_init(&c->alarm, c->next_attempt, on_alarm, c, gpr_now(GPR_CLOCK_REALTIME));
gpr_mu_unlock(&c->mu);
}
}
diff --git a/src/core/httpcli/httpcli.c b/src/core/httpcli/httpcli.c
index 3f5557e08e..65997d5f44 100644
--- a/src/core/httpcli/httpcli.c
+++ b/src/core/httpcli/httpcli.c
@@ -165,6 +165,7 @@ static void start_write(internal_request *req) {
static void on_secure_transport_setup_done(void *rp,
grpc_security_status status,
+ grpc_endpoint *wrapped_endpoint,
grpc_endpoint *secure_endpoint) {
internal_request *req = rp;
if (status != GRPC_SECURITY_OK) {
diff --git a/src/core/httpcli/httpcli.h b/src/core/httpcli/httpcli.h
index 06699e88c2..ab98178f8a 100644
--- a/src/core/httpcli/httpcli.h
+++ b/src/core/httpcli/httpcli.h
@@ -85,7 +85,7 @@ typedef struct grpc_httpcli_response {
char *body;
} grpc_httpcli_response;
-/* Callback for grpc_httpcli_get */
+/* Callback for grpc_httpcli_get and grpc_httpcli_post. */
typedef void (*grpc_httpcli_response_cb)(void *user_data,
const grpc_httpcli_response *response);
@@ -100,8 +100,6 @@ void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
'request' contains request parameters - these are caller owned and can be
destroyed once the call returns
'deadline' contains a deadline for the request (or gpr_inf_future)
- 'em' points to a caller owned event manager that must be alive for the
- lifetime of the request
'on_response' is a callback to report results to (and 'user_data' is a user
supplied pointer to pass to said call) */
void grpc_httpcli_get(grpc_httpcli_context *context, grpc_pollset *pollset,
diff --git a/src/core/iomgr/alarm.h b/src/core/iomgr/alarm.h
index e5262e2199..c067a0b8a3 100644
--- a/src/core/iomgr/alarm.h
+++ b/src/core/iomgr/alarm.h
@@ -41,9 +41,9 @@
typedef struct grpc_alarm {
gpr_timespec deadline;
gpr_uint32 heap_index; /* INVALID_HEAP_INDEX if not in heap */
+ int triggered;
struct grpc_alarm *next;
struct grpc_alarm *prev;
- int triggered;
grpc_iomgr_cb_func cb;
void *cb_arg;
} grpc_alarm;
diff --git a/src/core/iomgr/iocp_windows.c b/src/core/iomgr/iocp_windows.c
index 0c62bfccd5..3d3a193d00 100644
--- a/src/core/iomgr/iocp_windows.c
+++ b/src/core/iomgr/iocp_windows.c
@@ -127,7 +127,6 @@ static void iocp_loop(void *p) {
grpc_maybe_call_delayed_callbacks(NULL, 1);
do_iocp_work();
}
- gpr_log(GPR_DEBUG, "iocp_loop is done");
gpr_event_set(&g_iocp_done, (void *)1);
}
diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c
index c507e7c26a..cca92d3b32 100644
--- a/src/core/iomgr/iomgr.c
+++ b/src/core/iomgr/iomgr.c
@@ -59,7 +59,7 @@ static void background_callback_executor(void *ignored) {
while (!g_shutdown) {
gpr_timespec deadline = gpr_inf_future;
gpr_timespec short_deadline =
- gpr_time_add(gpr_now(), gpr_time_from_millis(100));
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100));
if (g_cbs_head) {
grpc_iomgr_closure *closure = g_cbs_head;
g_cbs_head = closure->next;
@@ -67,7 +67,8 @@ static void background_callback_executor(void *ignored) {
gpr_mu_unlock(&g_mu);
closure->cb(closure->cb_arg, closure->success);
gpr_mu_lock(&g_mu);
- } else if (grpc_alarm_check(&g_mu, gpr_now(), &deadline)) {
+ } else if (grpc_alarm_check(&g_mu, gpr_now(GPR_CLOCK_REALTIME),
+ &deadline)) {
} else {
gpr_mu_unlock(&g_mu);
gpr_sleep_until(gpr_time_min(short_deadline, deadline));
@@ -89,7 +90,7 @@ void grpc_iomgr_init(void) {
gpr_thd_id id;
gpr_mu_init(&g_mu);
gpr_cv_init(&g_rcv);
- grpc_alarm_list_init(gpr_now());
+ grpc_alarm_list_init(gpr_now(GPR_CLOCK_REALTIME));
g_root_object.next = g_root_object.prev = &g_root_object;
g_root_object.name = "root";
grpc_iomgr_platform_init();
@@ -110,21 +111,27 @@ void grpc_iomgr_shutdown(void) {
grpc_iomgr_object *obj;
grpc_iomgr_closure *closure;
gpr_timespec shutdown_deadline =
- gpr_time_add(gpr_now(), gpr_time_from_seconds(10));
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10));
+ gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
gpr_mu_lock(&g_mu);
g_shutdown = 1;
while (g_cbs_head != NULL || g_root_object.next != &g_root_object) {
- if (g_cbs_head != NULL && g_root_object.next != &g_root_object) {
- gpr_log(GPR_DEBUG,
- "Waiting for %d iomgr objects to be destroyed and executing "
- "final callbacks",
- count_objects());
- } else if (g_cbs_head != NULL) {
- gpr_log(GPR_DEBUG, "Executing final iomgr callbacks");
- } else {
- gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed",
- count_objects());
+ if (gpr_time_cmp(
+ gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), last_warning_time),
+ gpr_time_from_seconds(1)) >= 0) {
+ if (g_cbs_head != NULL && g_root_object.next != &g_root_object) {
+ gpr_log(GPR_DEBUG,
+ "Waiting for %d iomgr objects to be destroyed and executing "
+ "final callbacks",
+ count_objects());
+ } else if (g_cbs_head != NULL) {
+ gpr_log(GPR_DEBUG, "Executing final iomgr callbacks");
+ } else {
+ gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed",
+ count_objects());
+ }
+ last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
}
if (g_cbs_head) {
do {
@@ -145,9 +152,9 @@ void grpc_iomgr_shutdown(void) {
if (g_root_object.next != &g_root_object) {
int timeout = 0;
gpr_timespec short_deadline =
- gpr_time_add(gpr_now(), gpr_time_from_millis(100));
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100));
while (gpr_cv_wait(&g_rcv, &g_mu, short_deadline) && g_cbs_head == NULL) {
- if (gpr_time_cmp(gpr_now(), shutdown_deadline) > 0) {
+ if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) {
timeout = 1;
break;
}
diff --git a/src/core/iomgr/pollset_multipoller_with_epoll.c b/src/core/iomgr/pollset_multipoller_with_epoll.c
index 1900bbf9e1..3746c8edaf 100644
--- a/src/core/iomgr/pollset_multipoller_with_epoll.c
+++ b/src/core/iomgr/pollset_multipoller_with_epoll.c
@@ -105,10 +105,11 @@ static void multipoll_with_epoll_pollset_maybe_work(
* here.
*/
- timeout_ms = grpc_poll_deadline_to_millis_timeout(deadline, now);
pollset->counter += 1;
gpr_mu_unlock(&pollset->mu);
+ timeout_ms = grpc_poll_deadline_to_millis_timeout(deadline, now);
+
do {
ep_rv = epoll_wait(h->epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, timeout_ms);
if (ep_rv < 0) {
diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c
index 12496440de..85101764d2 100644
--- a/src/core/iomgr/pollset_posix.c
+++ b/src/core/iomgr/pollset_posix.c
@@ -122,7 +122,7 @@ static void finish_shutdown(grpc_pollset *pollset) {
int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
/* pollset->mu already held */
- gpr_timespec now = gpr_now();
+ gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
if (gpr_time_cmp(now, deadline) > 0) {
return 0;
}
@@ -187,15 +187,16 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {
gpr_mu_destroy(&pollset->mu);
}
-int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline, gpr_timespec now) {
+int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline,
+ gpr_timespec now) {
gpr_timespec timeout;
static const int max_spin_polling_us = 10;
if (gpr_time_cmp(deadline, gpr_inf_future) == 0) {
return -1;
}
if (gpr_time_cmp(
- deadline,
- gpr_time_add(now, gpr_time_from_micros(max_spin_polling_us))) <= 0) {
+ deadline,
+ gpr_time_add(now, gpr_time_from_micros(max_spin_polling_us))) <= 0) {
return 0;
}
timeout = gpr_time_sub(deadline, now);
diff --git a/src/core/iomgr/pollset_set.h b/src/core/iomgr/pollset_set.h
index 98e3b552a7..6d73951c70 100644
--- a/src/core/iomgr/pollset_set.h
+++ b/src/core/iomgr/pollset_set.h
@@ -38,7 +38,7 @@
/* A grpc_pollset_set is a set of pollsets that are interested in an
action. Adding a pollset to a pollset_set automatically adds any
- fd's (etc) that have been registered with the set_set with that pollset.
+ fd's (etc) that have been registered with the set_set to that pollset.
Registering fd's automatically adds them to all current pollsets. */
#ifdef GPR_POSIX_SOCKET
diff --git a/src/core/iomgr/pollset_windows.c b/src/core/iomgr/pollset_windows.c
index 8d6bc79c96..24226cc980 100644
--- a/src/core/iomgr/pollset_windows.c
+++ b/src/core/iomgr/pollset_windows.c
@@ -70,7 +70,7 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {
int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
gpr_timespec now;
- now = gpr_now();
+ now = gpr_now(GPR_CLOCK_REALTIME);
if (gpr_time_cmp(now, deadline) > 0) {
return 0 /* GPR_FALSE */;
}
@@ -86,8 +86,6 @@ int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
return 1 /* GPR_TRUE */;
}
-void grpc_pollset_kick(grpc_pollset *p) {
- gpr_cv_signal(&p->cv);
-}
+void grpc_pollset_kick(grpc_pollset *p) { gpr_cv_signal(&p->cv); }
#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c
index fbf3fdc949..f6ddfff0ad 100644
--- a/src/core/iomgr/socket_windows.c
+++ b/src/core/iomgr/socket_windows.c
@@ -37,6 +37,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
#include "src/core/iomgr/iocp_windows.h"
#include "src/core/iomgr/iomgr_internal.h"
@@ -45,11 +46,14 @@
#include "src/core/iomgr/socket_windows.h"
grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) {
+ char *final_name;
grpc_winsocket *r = gpr_malloc(sizeof(grpc_winsocket));
memset(r, 0, sizeof(grpc_winsocket));
r->socket = socket;
gpr_mu_init(&r->state_mu);
- grpc_iomgr_register_object(&r->iomgr_object, name);
+ gpr_asprintf(&final_name, "%s:socket=0x%p", name, r);
+ grpc_iomgr_register_object(&r->iomgr_object, final_name);
+ gpr_free(final_name);
grpc_iocp_add_socket(r);
return r;
}
@@ -58,22 +62,27 @@ grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) {
operations to abort them. We need to do that this way because of the
various callsites of that function, which happens to be in various
mutex hold states, and that'd be unsafe to call them directly. */
-int grpc_winsocket_shutdown(grpc_winsocket *socket) {
+int grpc_winsocket_shutdown(grpc_winsocket *winsocket) {
int callbacks_set = 0;
- gpr_mu_lock(&socket->state_mu);
- if (socket->read_info.cb) {
+ SOCKET socket;
+ gpr_mu_lock(&winsocket->state_mu);
+ socket = winsocket->socket;
+ if (winsocket->read_info.cb) {
callbacks_set++;
- grpc_iomgr_closure_init(&socket->shutdown_closure, socket->read_info.cb,
- socket->read_info.opaque);
- grpc_iomgr_add_delayed_callback(&socket->shutdown_closure, 0);
+ grpc_iomgr_closure_init(&winsocket->shutdown_closure,
+ winsocket->read_info.cb,
+ winsocket->read_info.opaque);
+ grpc_iomgr_add_delayed_callback(&winsocket->shutdown_closure, 0);
}
- if (socket->write_info.cb) {
+ if (winsocket->write_info.cb) {
callbacks_set++;
- grpc_iomgr_closure_init(&socket->shutdown_closure, socket->write_info.cb,
- socket->write_info.opaque);
- grpc_iomgr_add_delayed_callback(&socket->shutdown_closure, 0);
+ grpc_iomgr_closure_init(&winsocket->shutdown_closure,
+ winsocket->write_info.cb,
+ winsocket->write_info.opaque);
+ grpc_iomgr_add_delayed_callback(&winsocket->shutdown_closure, 0);
}
- gpr_mu_unlock(&socket->state_mu);
+ gpr_mu_unlock(&winsocket->state_mu);
+ closesocket(socket);
return callbacks_set;
}
@@ -84,14 +93,12 @@ int grpc_winsocket_shutdown(grpc_winsocket *socket) {
an "idle" socket which is neither trying to read or write, we'd start leaking
both memory and sockets. */
void grpc_winsocket_orphan(grpc_winsocket *winsocket) {
- SOCKET socket = winsocket->socket;
grpc_iomgr_unregister_object(&winsocket->iomgr_object);
if (winsocket->read_info.outstanding || winsocket->write_info.outstanding) {
grpc_iocp_socket_orphan(winsocket);
} else {
grpc_winsocket_destroy(winsocket);
}
- closesocket(socket);
}
void grpc_winsocket_destroy(grpc_winsocket *winsocket) {
diff --git a/src/core/iomgr/tcp_client_posix.c b/src/core/iomgr/tcp_client_posix.c
index d981aaf028..dc0489e64f 100644
--- a/src/core/iomgr/tcp_client_posix.c
+++ b/src/core/iomgr/tcp_client_posix.c
@@ -114,6 +114,7 @@ static void on_writable(void *acp, int success) {
void (*cb)(void *arg, grpc_endpoint *tcp) = ac->cb;
void *cb_arg = ac->cb_arg;
+ gpr_mu_lock(&ac->mu);
if (success) {
do {
so_error_size = sizeof(so_error);
@@ -139,6 +140,7 @@ static void on_writable(void *acp, int success) {
opened too many network connections. The "easy" fix:
don't do that! */
gpr_log(GPR_ERROR, "kernel out of buffers");
+ gpr_mu_unlock(&ac->mu);
grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
return;
} else {
@@ -165,10 +167,11 @@ static void on_writable(void *acp, int success) {
abort();
finish:
- gpr_mu_lock(&ac->mu);
- if (!ep) {
+ if (ep == NULL) {
grpc_pollset_set_del_fd(ac->interested_parties, ac->fd);
grpc_fd_orphan(ac->fd, NULL, "tcp_client_orphan");
+ } else {
+ ac->fd = NULL;
}
done = (--ac->refs == 0);
gpr_mu_unlock(&ac->mu);
@@ -250,7 +253,8 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
ac->write_closure.cb_arg = ac;
gpr_mu_lock(&ac->mu);
- grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now());
+ grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac,
+ gpr_now(GPR_CLOCK_REALTIME));
grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
gpr_mu_unlock(&ac->mu);
diff --git a/src/core/iomgr/tcp_client_windows.c b/src/core/iomgr/tcp_client_windows.c
index b1a169b519..16741452b9 100644
--- a/src/core/iomgr/tcp_client_windows.c
+++ b/src/core/iomgr/tcp_client_windows.c
@@ -215,7 +215,8 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp),
ac->refs = 2;
ac->aborted = 0;
- grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now());
+ grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac,
+ gpr_now(GPR_CLOCK_REALTIME));
socket->write_info.outstanding = 1;
grpc_socket_notify_on_write(socket, on_connect, ac);
return;
diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c
index 9ad089af66..b6d6efc9fb 100644
--- a/src/core/iomgr/tcp_posix.c
+++ b/src/core/iomgr/tcp_posix.c
@@ -313,9 +313,7 @@ static void call_read_cb(grpc_tcp *tcp, gpr_slice *slices, size_t nslices,
size_t i;
gpr_log(GPR_DEBUG, "read: status=%d", status);
for (i = 0; i < nslices; i++) {
- char *dump =
- gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]),
- GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT);
+ char *dump = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "READ: %s", dump);
gpr_free(dump);
}
@@ -540,9 +538,7 @@ static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep,
size_t i;
for (i = 0; i < nslices; i++) {
- char *data =
- gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]),
- GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT);
+ char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "WRITE %p: %s", tcp, data);
gpr_free(data);
}
diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c
index d70968de88..e6e1d1499e 100644
--- a/src/core/iomgr/tcp_server_windows.c
+++ b/src/core/iomgr/tcp_server_windows.c
@@ -108,9 +108,10 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s,
size_t i;
gpr_mu_lock(&s->mu);
/* First, shutdown all fd's. This will queue abortion calls for all
- of the pending accepts. */
+ of the pending accepts due to the normal operation mechanism. */
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
+ sp->shutting_down = 1;
grpc_winsocket_shutdown(sp->socket);
}
/* This happens asynchronously. Wait while that happens. */
@@ -242,63 +243,52 @@ static void on_accept(void *arg, int from_iocp) {
SOCKET sock = sp->new_socket;
grpc_winsocket_callback_info *info = &sp->socket->read_info;
grpc_endpoint *ep = NULL;
-
- /* The shutdown sequence is done in two parts. This is the second
- part here, acknowledging the IOCP notification, and doing nothing
- else, especially not queuing a new accept. */
- if (sp->shutting_down) {
- GPR_ASSERT(from_iocp);
- sp->shutting_down = 0;
- sp->socket->read_info.outstanding = 0;
- gpr_mu_lock(&sp->server->mu);
- if (0 == --sp->server->active_ports) {
- gpr_cv_broadcast(&sp->server->cv);
- }
- gpr_mu_unlock(&sp->server->mu);
- return;
- }
-
- if (from_iocp) {
- /* The IOCP notified us of a completed operation. Let's grab the results,
- and act accordingly. */
- DWORD transfered_bytes = 0;
- DWORD flags;
- BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
- &transfered_bytes, FALSE, &flags);
- if (!wsa_success) {
+ DWORD transfered_bytes;
+ DWORD flags;
+ BOOL wsa_success;
+
+ /* The general mechanism for shutting down is to queue abortion calls. While
+ this is necessary in the read/write case, it's useless for the accept
+ case. Let's do nothing. */
+ if (!from_iocp) return;
+
+ /* The IOCP notified us of a completed operation. Let's grab the results,
+ and act accordingly. */
+ transfered_bytes = 0;
+ wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
+ &transfered_bytes, FALSE, &flags);
+ if (!wsa_success) {
+ if (sp->shutting_down) {
+ /* During the shutdown case, we ARE expecting an error. So that's swell,
+ and we can wake up the shutdown thread. */
+ sp->shutting_down = 0;
+ sp->socket->read_info.outstanding = 0;
+ gpr_mu_lock(&sp->server->mu);
+ if (0 == --sp->server->active_ports) {
+ gpr_cv_broadcast(&sp->server->cv);
+ }
+ gpr_mu_unlock(&sp->server->mu);
+ return;
+ } else {
char *utf8_message = gpr_format_message(WSAGetLastError());
gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message);
gpr_free(utf8_message);
closesocket(sock);
- } else {
- /* TODO(ctiller): add sockaddr address to label */
- ep = grpc_tcp_create(grpc_winsocket_create(sock, "server"));
}
} else {
- /* If we're not notified from the IOCP, it means we are asked to shutdown.
- This will initiate that shutdown. Calling closesocket will trigger an
- IOCP notification, that will call this function a second time, from
- the IOCP thread. Of course, this only works if the socket was, in fact,
- listening. If that's not the case, we'd wait indefinitely. That's a bit
- of a degenerate case, but it can happen if you create a server, but
- don't start it. So let's support that by recursing once. */
- sp->shutting_down = 1;
- sp->new_socket = INVALID_SOCKET;
- if (sock != INVALID_SOCKET) {
- closesocket(sock);
- } else {
- on_accept(sp, 1);
+ if (!sp->shutting_down) {
+ /* TODO(ctiller): add sockaddr address to label */
+ ep = grpc_tcp_create(grpc_winsocket_create(sock, "server"));
}
- return;
}
/* The only time we should call our callback, is where we successfully
managed to accept a connection, and created an endpoint. */
if (ep) sp->server->cb(sp->server->cb_arg, ep);
/* As we were notified from the IOCP of one and exactly one accept,
- the former socked we created has now either been destroy or assigned
- to the new connection. We need to create a new one for the next
- connection. */
+ the former socked we created has now either been destroy or assigned
+ to the new connection. We need to create a new one for the next
+ connection. */
start_accept(sp);
}
diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c
index 15759c398a..1bf81a73e0 100644
--- a/src/core/iomgr/tcp_windows.c
+++ b/src/core/iomgr/tcp_windows.c
@@ -148,9 +148,11 @@ static void on_read(void *tcpp, int from_iocp) {
GPR_ASSERT(tcp->socket->read_info.outstanding);
if (socket->read_info.wsa_error != 0) {
- char *utf8_message = gpr_format_message(info->wsa_error);
- gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message);
- gpr_free(utf8_message);
+ if (socket->read_info.wsa_error != WSAECONNRESET) {
+ char *utf8_message = gpr_format_message(info->wsa_error);
+ gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message);
+ gpr_free(utf8_message);
+ }
status = GRPC_ENDPOINT_CB_ERROR;
} else {
if (info->bytes_transfered != 0) {
@@ -259,9 +261,11 @@ static void on_write(void *tcpp, int from_iocp) {
GPR_ASSERT(tcp->socket->write_info.outstanding);
if (info->wsa_error != 0) {
- char *utf8_message = gpr_format_message(info->wsa_error);
- gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message);
- gpr_free(utf8_message);
+ if (info->wsa_error != WSAECONNRESET) {
+ char *utf8_message = gpr_format_message(info->wsa_error);
+ gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message);
+ gpr_free(utf8_message);
+ }
status = GRPC_ENDPOINT_CB_ERROR;
} else {
GPR_ASSERT(info->bytes_transfered == tcp->write_slices.length);
@@ -325,9 +329,11 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep,
ret = GRPC_ENDPOINT_WRITE_DONE;
GPR_ASSERT(bytes_sent == tcp->write_slices.length);
} else {
- char *utf8_message = gpr_format_message(info->wsa_error);
- gpr_log(GPR_ERROR, "WSASend error: %s", utf8_message);
- gpr_free(utf8_message);
+ if (socket->read_info.wsa_error != WSAECONNRESET) {
+ char *utf8_message = gpr_format_message(info->wsa_error);
+ gpr_log(GPR_ERROR, "WSASend error: %s", utf8_message);
+ gpr_free(utf8_message);
+ }
}
if (allocated) gpr_free(allocated);
gpr_slice_buffer_reset_and_unref(&tcp->write_slices);
diff --git a/src/core/json/json.h b/src/core/json/json.h
index b78b42a5b2..cac18ad885 100644
--- a/src/core/json/json.h
+++ b/src/core/json/json.h
@@ -53,7 +53,7 @@ typedef struct grpc_json {
} grpc_json;
/* The next two functions are going to parse the input string, and
- * destroy it in the process, in order to use its space to store
+ * modify it in the process, in order to use its space to store
* all of the keys and values for the returned object tree.
*
* They assume UTF-8 input stream, and will output UTF-8 encoded
diff --git a/src/core/profiling/timers_preciseclock.h b/src/core/profiling/timers_preciseclock.h
index 163d52b797..5c251b47e6 100644
--- a/src/core/profiling/timers_preciseclock.h
+++ b/src/core/profiling/timers_preciseclock.h
@@ -82,7 +82,7 @@ struct grpc_precise_clock {
gpr_timespec clock;
};
static void grpc_precise_clock_now(grpc_precise_clock* clk) {
- clk->clock = gpr_now();
+ clk->clock = gpr_now(GPR_CLOCK_REALTIME);
}
#define GRPC_PRECISE_CLOCK_FORMAT "%ld.%09d"
#define GRPC_PRECISE_CLOCK_PRINTF_ARGS(clk) \
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c
index f8d18d9b17..9e49a807f1 100644
--- a/src/core/security/client_auth_filter.c
+++ b/src/core/security/client_auth_filter.c
@@ -61,6 +61,7 @@ typedef struct {
grpc_transport_stream_op op;
size_t op_md_idx;
int sent_initial_metadata;
+ gpr_uint8 security_context_set;
grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
} call_data;
@@ -199,8 +200,22 @@ static void auth_start_transport_op(grpc_call_element *elem,
channel_data *chand = elem->channel_data;
grpc_linked_mdelem *l;
size_t i;
+ grpc_client_security_context* sec_ctx = NULL;
- /* TODO(jboeuf): write the call auth context. */
+ if (calld->security_context_set == 0) {
+ calld->security_context_set = 1;
+ GPR_ASSERT(op->context);
+ if (op->context[GRPC_CONTEXT_SECURITY].value == NULL) {
+ op->context[GRPC_CONTEXT_SECURITY].value =
+ grpc_client_security_context_create();
+ op->context[GRPC_CONTEXT_SECURITY].destroy =
+ grpc_client_security_context_destroy;
+ }
+ sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value;
+ GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter");
+ sec_ctx->auth_context = GRPC_AUTH_CONTEXT_REF(
+ chand->security_connector->base.auth_context, "client_auth_filter");
+ }
if (op->bind_pollset) {
calld->pollset = op->bind_pollset;
@@ -219,11 +234,11 @@ static void auth_start_transport_op(grpc_call_element *elem,
/* Pointer comparison is OK for md_elems created from the same context.
*/
if (md->key == chand->authority_string) {
- if (calld->host != NULL) grpc_mdstr_unref(calld->host);
- calld->host = grpc_mdstr_ref(md->value);
+ if (calld->host != NULL) GRPC_MDSTR_UNREF(calld->host);
+ calld->host = GRPC_MDSTR_REF(md->value);
} else if (md->key == chand->path_string) {
- if (calld->method != NULL) grpc_mdstr_unref(calld->method);
- calld->method = grpc_mdstr_ref(md->value);
+ if (calld->method != NULL) GRPC_MDSTR_UNREF(calld->method);
+ calld->method = GRPC_MDSTR_REF(md->value);
}
}
if (calld->host != NULL) {
@@ -263,6 +278,7 @@ static void init_call_elem(grpc_call_element *elem,
calld->method = NULL;
calld->pollset = NULL;
calld->sent_initial_metadata = 0;
+ calld->security_context_set = 0;
GPR_ASSERT(!initial_op || !initial_op->send_ops);
}
@@ -272,10 +288,10 @@ static void destroy_call_elem(grpc_call_element *elem) {
call_data *calld = elem->call_data;
grpc_credentials_unref(calld->creds);
if (calld->host != NULL) {
- grpc_mdstr_unref(calld->host);
+ GRPC_MDSTR_UNREF(calld->host);
}
if (calld->method != NULL) {
- grpc_mdstr_unref(calld->method);
+ GRPC_MDSTR_UNREF(calld->method);
}
}
@@ -314,16 +330,16 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
if (ctx != NULL)
GRPC_SECURITY_CONNECTOR_UNREF(&ctx->base, "client_auth_filter");
if (chand->authority_string != NULL) {
- grpc_mdstr_unref(chand->authority_string);
+ GRPC_MDSTR_UNREF(chand->authority_string);
}
if (chand->error_msg_key != NULL) {
- grpc_mdstr_unref(chand->error_msg_key);
+ GRPC_MDSTR_UNREF(chand->error_msg_key);
}
if (chand->status_key != NULL) {
- grpc_mdstr_unref(chand->status_key);
+ GRPC_MDSTR_UNREF(chand->status_key);
}
if (chand->path_string != NULL) {
- grpc_mdstr_unref(chand->path_string);
+ GRPC_MDSTR_UNREF(chand->path_string);
}
}
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index e79e9ce351..230f0dfb85 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -41,7 +41,6 @@
#include "src/core/json/json.h"
#include "src/core/httpcli/httpcli.h"
#include "src/core/iomgr/iomgr.h"
-#include "src/core/security/json_token.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
@@ -52,12 +51,12 @@
/* -- Common. -- */
-typedef struct {
+struct grpc_credentials_metadata_request {
grpc_credentials *creds;
grpc_credentials_metadata_cb cb;
grpc_iomgr_closure *on_simulated_token_fetch_done_closure;
void *user_data;
-} grpc_credentials_metadata_request;
+};
static grpc_credentials_metadata_request *
grpc_credentials_metadata_request_create(grpc_credentials *creds,
@@ -152,16 +151,6 @@ grpc_security_status grpc_server_credentials_create_security_connector(
/* -- Ssl credentials. -- */
-typedef struct {
- grpc_credentials base;
- grpc_ssl_config config;
-} grpc_ssl_credentials;
-
-typedef struct {
- grpc_server_credentials base;
- grpc_ssl_server_config config;
-} grpc_ssl_server_credentials;
-
static void ssl_destroy(grpc_credentials *creds) {
grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
@@ -326,22 +315,6 @@ grpc_server_credentials *grpc_ssl_server_credentials_create(
/* -- Jwt credentials -- */
-typedef struct {
- grpc_credentials base;
-
- /* Have a simple cache for now with just 1 entry. We could have a map based on
- the service_url for a more sophisticated one. */
- gpr_mu cache_mu;
- struct {
- grpc_credentials_md_store *jwt_md;
- char *service_url;
- gpr_timespec jwt_expiration;
- } cached;
-
- grpc_auth_json_key key;
- gpr_timespec jwt_lifetime;
-} grpc_jwt_credentials;
-
static void jwt_reset_cache(grpc_jwt_credentials *c) {
if (c->cached.jwt_md != NULL) {
grpc_credentials_md_store_unref(c->cached.jwt_md);
@@ -384,7 +357,8 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
if (c->cached.service_url != NULL &&
strcmp(c->cached.service_url, service_url) == 0 &&
c->cached.jwt_md != NULL &&
- (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now()),
+ (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
+ gpr_now(GPR_CLOCK_REALTIME)),
refresh_threshold) > 0)) {
jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
}
@@ -401,7 +375,8 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
char *md_value;
gpr_asprintf(&md_value, "Bearer %s", jwt);
gpr_free(jwt);
- c->cached.jwt_expiration = gpr_time_add(gpr_now(), c->jwt_lifetime);
+ c->cached.jwt_expiration =
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
c->cached.service_url = gpr_strdup(service_url);
c->cached.jwt_md = grpc_credentials_md_store_create(1);
grpc_credentials_md_store_add_cstrings(
@@ -424,10 +399,9 @@ static grpc_credentials_vtable jwt_vtable = {
jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
jwt_get_request_metadata, NULL};
-grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
- gpr_timespec token_lifetime) {
+grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key(
+ grpc_auth_json_key key, gpr_timespec token_lifetime) {
grpc_jwt_credentials *c;
- grpc_auth_json_key key = grpc_auth_json_key_create_from_string(json_key);
if (!grpc_auth_json_key_is_valid(&key)) {
gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
return NULL;
@@ -444,26 +418,13 @@ grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
return &c->base;
}
-/* -- Oauth2TokenFetcher credentials -- */
-
-/* This object is a base for credentials that need to acquire an oauth2 token
- from an http service. */
-
-typedef void (*grpc_fetch_oauth2_func)(grpc_credentials_metadata_request *req,
- grpc_httpcli_context *http_context,
- grpc_pollset *pollset,
- grpc_httpcli_response_cb response_cb,
- gpr_timespec deadline);
+grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
+ gpr_timespec token_lifetime) {
+ return grpc_jwt_credentials_create_from_auth_json_key(
+ grpc_auth_json_key_create_from_string(json_key), token_lifetime);
+}
-typedef struct {
- grpc_credentials base;
- gpr_mu mu;
- grpc_credentials_md_store *access_token_md;
- gpr_timespec token_expiration;
- grpc_httpcli_context httpcli_context;
- grpc_pollset_set pollset_set;
- grpc_fetch_oauth2_func fetch_func;
-} grpc_oauth2_token_fetcher_credentials;
+/* -- Oauth2TokenFetcher credentials -- */
static void oauth2_token_fetcher_destroy(grpc_credentials *creds) {
grpc_oauth2_token_fetcher_credentials *c =
@@ -586,7 +547,8 @@ static void on_oauth2_token_fetcher_http_response(
status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
response, &c->access_token_md, &token_lifetime);
if (status == GRPC_CREDENTIALS_OK) {
- c->token_expiration = gpr_time_add(gpr_now(), token_lifetime);
+ c->token_expiration =
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
r->cb(r->user_data, c->access_token_md->entries,
c->access_token_md->num_entries, status);
} else {
@@ -608,8 +570,9 @@ static void oauth2_token_fetcher_get_request_metadata(
{
gpr_mu_lock(&c->mu);
if (c->access_token_md != NULL &&
- (gpr_time_cmp(gpr_time_sub(c->token_expiration, gpr_now()),
- refresh_threshold) > 0)) {
+ (gpr_time_cmp(
+ gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
+ refresh_threshold) > 0)) {
cached_access_token_md =
grpc_credentials_md_store_ref(c->access_token_md);
}
@@ -623,7 +586,7 @@ static void oauth2_token_fetcher_get_request_metadata(
c->fetch_func(
grpc_credentials_metadata_request_create(creds, cb, user_data),
&c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response,
- gpr_time_add(gpr_now(), refresh_threshold));
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
}
}
@@ -635,7 +598,7 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
gpr_mu_init(&c->mu);
c->token_expiration = gpr_inf_past;
c->fetch_func = fetch_func;
- grpc_pollset_set_init(&c->pollset_set);
+ grpc_httpcli_context_init(&c->httpcli_context);
}
/* -- ComputeEngine credentials. -- */
@@ -670,13 +633,6 @@ grpc_credentials *grpc_compute_engine_credentials_create(void) {
/* -- ServiceAccount credentials. -- */
-typedef struct {
- grpc_oauth2_token_fetcher_credentials base;
- grpc_auth_json_key key;
- char *scope;
- gpr_timespec token_lifetime;
-} grpc_service_account_credentials;
-
static void service_account_destroy(grpc_credentials *creds) {
grpc_service_account_credentials *c =
(grpc_service_account_credentials *)creds;
@@ -747,11 +703,6 @@ grpc_credentials *grpc_service_account_credentials_create(
/* -- RefreshToken credentials. -- */
-typedef struct {
- grpc_oauth2_token_fetcher_credentials base;
- grpc_auth_refresh_token refresh_token;
-} grpc_refresh_token_credentials;
-
static void refresh_token_destroy(grpc_credentials *creds) {
grpc_refresh_token_credentials *c = (grpc_refresh_token_credentials *)creds;
grpc_auth_refresh_token_destruct(&c->refresh_token);
@@ -787,12 +738,9 @@ static void refresh_token_fetch_oauth2(
gpr_free(body);
}
-grpc_credentials *grpc_refresh_token_credentials_create(
- const char *json_refresh_token) {
+grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
+ grpc_auth_refresh_token refresh_token) {
grpc_refresh_token_credentials *c;
- grpc_auth_refresh_token refresh_token =
- grpc_auth_refresh_token_create_from_string(json_refresh_token);
-
if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
return NULL;
@@ -805,13 +753,13 @@ grpc_credentials *grpc_refresh_token_credentials_create(
return &c->base.base;
}
-/* -- Fake Oauth2 credentials. -- */
+grpc_credentials *grpc_refresh_token_credentials_create(
+ const char *json_refresh_token) {
+ return grpc_refresh_token_credentials_create_from_auth_refresh_token(
+ grpc_auth_refresh_token_create_from_string(json_refresh_token));
+}
-typedef struct {
- grpc_credentials base;
- grpc_credentials_md_store *access_token_md;
- int is_async;
-} grpc_fake_oauth2_credentials;
+/* -- Fake Oauth2 credentials. -- */
static void fake_oauth2_destroy(grpc_credentials *creds) {
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds;
@@ -876,6 +824,54 @@ grpc_credentials *grpc_fake_oauth2_credentials_create(
return &c->base;
}
+/* -- Oauth2 Access Token credentials. -- */
+
+static void access_token_destroy(grpc_credentials *creds) {
+ grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
+ grpc_credentials_md_store_unref(c->access_token_md);
+ gpr_free(c);
+}
+
+static int access_token_has_request_metadata(const grpc_credentials *creds) {
+ return 1;
+}
+
+static int access_token_has_request_metadata_only(
+ const grpc_credentials *creds) {
+ return 1;
+}
+
+static void access_token_get_request_metadata(grpc_credentials *creds,
+ grpc_pollset *pollset,
+ const char *service_url,
+ grpc_credentials_metadata_cb cb,
+ void *user_data) {
+ grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
+ cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
+}
+
+static grpc_credentials_vtable access_token_vtable = {
+ access_token_destroy, access_token_has_request_metadata,
+ access_token_has_request_metadata_only, access_token_get_request_metadata,
+ NULL};
+
+grpc_credentials *grpc_access_token_credentials_create(
+ const char *access_token) {
+ grpc_access_token_credentials *c =
+ gpr_malloc(sizeof(grpc_access_token_credentials));
+ char *token_md_value;
+ memset(c, 0, sizeof(grpc_access_token_credentials));
+ c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
+ c->base.vtable = &access_token_vtable;
+ gpr_ref_init(&c->base.refcount, 1);
+ c->access_token_md = grpc_credentials_md_store_create(1);
+ gpr_asprintf(&token_md_value, "Bearer %s", access_token);
+ grpc_credentials_md_store_add_cstrings(
+ c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value);
+ gpr_free(token_md_value);
+ return &c->base;
+}
+
/* -- Fake transport security credentials. -- */
static void fake_transport_security_credentials_destroy(
@@ -945,12 +941,6 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
/* -- Composite credentials. -- */
typedef struct {
- grpc_credentials base;
- grpc_credentials_array inner;
- grpc_credentials *connector_creds;
-} grpc_composite_credentials;
-
-typedef struct {
grpc_composite_credentials *composite_creds;
size_t creds_index;
grpc_credentials_md_store *md_elems;
@@ -1180,11 +1170,6 @@ grpc_credentials *grpc_credentials_contains_type(
/* -- IAM credentials. -- */
-typedef struct {
- grpc_credentials base;
- grpc_credentials_md_store *iam_md;
-} grpc_iam_credentials;
-
static void iam_destroy(grpc_credentials *creds) {
grpc_iam_credentials *c = (grpc_iam_credentials *)creds;
grpc_credentials_md_store_unref(c->iam_md);
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 75af73a0c6..d988901cf7 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -39,6 +39,8 @@
#include <grpc/grpc_security.h>
#include <grpc/support/sync.h>
+#include "src/core/httpcli/httpcli.h"
+#include "src/core/security/json_token.h"
#include "src/core/security/security_connector.h"
struct grpc_httpcli_response;
@@ -178,11 +180,22 @@ grpc_credentials_status
grpc_oauth2_token_fetcher_credentials_parse_server_response(
const struct grpc_httpcli_response *response,
grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime);
+void grpc_flush_cached_google_default_credentials(void);
/* Simulates an oauth2 token fetch with the specified value for testing. */
grpc_credentials *grpc_fake_oauth2_credentials_create(
const char *token_md_value, int is_async);
+/* Private constructor for jwt credentials from an already parsed json key.
+ Takes ownership of the key. */
+grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key(
+ grpc_auth_json_key key, gpr_timespec token_lifetime);
+
+/* Private constructor for refresh token credentials from an already parsed
+ refresh token. Takes ownership of the refresh token. */
+grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
+ grpc_auth_refresh_token token);
+
/* --- grpc_server_credentials. --- */
typedef struct {
@@ -199,4 +212,103 @@ struct grpc_server_credentials {
grpc_security_status grpc_server_credentials_create_security_connector(
grpc_server_credentials *creds, grpc_security_connector **sc);
+/* -- Ssl credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_ssl_config config;
+} grpc_ssl_credentials;
+
+typedef struct {
+ grpc_server_credentials base;
+ grpc_ssl_server_config config;
+} grpc_ssl_server_credentials;
+
+/* -- Jwt credentials -- */
+
+typedef struct {
+ grpc_credentials base;
+
+ /* Have a simple cache for now with just 1 entry. We could have a map based on
+ the service_url for a more sophisticated one. */
+ gpr_mu cache_mu;
+ struct {
+ grpc_credentials_md_store *jwt_md;
+ char *service_url;
+ gpr_timespec jwt_expiration;
+ } cached;
+
+ grpc_auth_json_key key;
+ gpr_timespec jwt_lifetime;
+} grpc_jwt_credentials;
+
+/* -- Oauth2TokenFetcher credentials --
+
+ This object is a base for credentials that need to acquire an oauth2 token
+ from an http service. */
+
+typedef struct grpc_credentials_metadata_request
+ grpc_credentials_metadata_request;
+
+typedef void (*grpc_fetch_oauth2_func)(grpc_credentials_metadata_request *req,
+ grpc_httpcli_context *http_context,
+ grpc_pollset *pollset,
+ grpc_httpcli_response_cb response_cb,
+ gpr_timespec deadline);
+
+typedef struct {
+ grpc_credentials base;
+ gpr_mu mu;
+ grpc_credentials_md_store *access_token_md;
+ gpr_timespec token_expiration;
+ grpc_httpcli_context httpcli_context;
+ grpc_fetch_oauth2_func fetch_func;
+} grpc_oauth2_token_fetcher_credentials;
+
+/* -- ServiceAccount credentials. -- */
+
+typedef struct {
+ grpc_oauth2_token_fetcher_credentials base;
+ grpc_auth_json_key key;
+ char *scope;
+ gpr_timespec token_lifetime;
+} grpc_service_account_credentials;
+
+/* -- RefreshToken credentials. -- */
+
+typedef struct {
+ grpc_oauth2_token_fetcher_credentials base;
+ grpc_auth_refresh_token refresh_token;
+} grpc_refresh_token_credentials;
+
+/* -- Oauth2 Access Token credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_credentials_md_store *access_token_md;
+} grpc_access_token_credentials;
+
+/* -- Fake Oauth2 credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_credentials_md_store *access_token_md;
+ int is_async;
+} grpc_fake_oauth2_credentials;
+
+/* -- IAM credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_credentials_md_store *iam_md;
+} grpc_iam_credentials;
+
+/* -- Composite credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_credentials_array inner;
+ grpc_credentials *connector_creds;
+} grpc_composite_credentials;
+
#endif /* GRPC_INTERNAL_CORE_SECURITY_CREDENTIALS_H */
diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c
index 5822ce6337..f622deff42 100644
--- a/src/core/security/google_default_credentials.c
+++ b/src/core/security/google_default_credentials.c
@@ -46,7 +46,6 @@
/* -- Constants. -- */
#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal"
-#define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS"
/* -- Default credentials. -- */
@@ -104,9 +103,10 @@ static int is_stack_running_on_compute_engine(void) {
grpc_httpcli_context_init(&context);
- grpc_httpcli_get(&context, &detector.pollset, &request,
- gpr_time_add(gpr_now(), max_detection_delay),
- on_compute_engine_detection_http_response, &detector);
+ grpc_httpcli_get(
+ &context, &detector.pollset, &request,
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
+ on_compute_engine_detection_http_response, &detector);
/* Block until we get the response. This is not ideal but this should only be
called once for the lifetime of the process by the default credentials. */
@@ -123,36 +123,40 @@ static int is_stack_running_on_compute_engine(void) {
}
/* Takes ownership of creds_path if not NULL. */
-static grpc_credentials *create_jwt_creds_from_path(char *creds_path) {
+static grpc_credentials *create_default_creds_from_path(char *creds_path) {
+ grpc_json *json = NULL;
+ grpc_auth_json_key key;
+ grpc_auth_refresh_token token;
grpc_credentials *result = NULL;
- gpr_slice creds_data;
+ gpr_slice creds_data = gpr_empty_slice();
int file_ok = 0;
- if (creds_path == NULL) return NULL;
- creds_data = gpr_load_file(creds_path, 1, &file_ok);
- gpr_free(creds_path);
- if (file_ok) {
- result = grpc_jwt_credentials_create(
- (const char *)GPR_SLICE_START_PTR(creds_data),
- grpc_max_auth_token_lifetime);
- gpr_slice_unref(creds_data);
+ if (creds_path == NULL) goto end;
+ creds_data = gpr_load_file(creds_path, 0, &file_ok);
+ if (!file_ok) goto end;
+ json = grpc_json_parse_string_with_len(
+ (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data));
+ if (json == NULL) goto end;
+
+ /* First, try an auth json key. */
+ key = grpc_auth_json_key_create_from_json(json);
+ if (grpc_auth_json_key_is_valid(&key)) {
+ result = grpc_jwt_credentials_create_from_auth_json_key(
+ key, grpc_max_auth_token_lifetime);
+ goto end;
}
- return result;
-}
-/* Takes ownership of creds_path if not NULL. */
-static grpc_credentials *create_refresh_token_creds_from_path(
- char *creds_path) {
- grpc_credentials *result = NULL;
- gpr_slice creds_data;
- int file_ok = 0;
- if (creds_path == NULL) return NULL;
- creds_data = gpr_load_file(creds_path, 1, &file_ok);
- gpr_free(creds_path);
- if (file_ok) {
- result = grpc_refresh_token_credentials_create(
- (const char *)GPR_SLICE_START_PTR(creds_data));
- gpr_slice_unref(creds_data);
+ /* Then try a refresh token if the auth json key was invalid. */
+ token = grpc_auth_refresh_token_create_from_json(json);
+ if (grpc_auth_refresh_token_is_valid(&token)) {
+ result =
+ grpc_refresh_token_credentials_create_from_auth_refresh_token(token);
+ goto end;
}
+
+end:
+ if (creds_path != NULL) gpr_free(creds_path);
+ gpr_slice_unref(creds_data);
+ if (json != NULL) grpc_json_destroy(json);
return result;
}
@@ -170,12 +174,12 @@ grpc_credentials *grpc_google_default_credentials_create(void) {
}
/* First, try the environment variable. */
- result =
- create_jwt_creds_from_path(gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
+ result = create_default_creds_from_path(
+ gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
if (result != NULL) goto end;
/* Then the well-known file. */
- result = create_refresh_token_creds_from_path(
+ result = create_default_creds_from_path(
grpc_get_well_known_google_credentials_file_path());
if (result != NULL) goto end;
@@ -193,11 +197,24 @@ end:
if (!serving_cached_credentials && result != NULL) {
/* Blend with default ssl credentials and add a global reference so that it
can be cached and re-served. */
- result = grpc_composite_credentials_create(
- grpc_ssl_credentials_create(NULL, NULL), result);
- GPR_ASSERT(result != NULL);
- default_credentials = grpc_credentials_ref(result);
+ grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL);
+ default_credentials = grpc_credentials_ref(grpc_composite_credentials_create(
+ ssl_creds, result));
+ GPR_ASSERT(default_credentials != NULL);
+ grpc_credentials_unref(ssl_creds);
+ grpc_credentials_unref(result);
+ result = default_credentials;
}
gpr_mu_unlock(&g_mu);
return result;
}
+
+void grpc_flush_cached_google_default_credentials(void) {
+ gpr_once_init(&g_once, init_default_credentials);
+ gpr_mu_lock(&g_mu);
+ if (default_credentials != NULL) {
+ grpc_credentials_unref(default_credentials);
+ default_credentials = NULL;
+ }
+ gpr_mu_unlock(&g_mu);
+}
diff --git a/src/core/security/json_token.c b/src/core/security/json_token.c
index 6116f1d767..9b1ea255ae 100644
--- a/src/core/security/json_token.c
+++ b/src/core/security/json_token.c
@@ -46,17 +46,11 @@
#include <openssl/evp.h>
#include <openssl/pem.h>
-#include "src/core/json/json.h"
-
/* --- Constants. --- */
/* 1 hour max. */
const gpr_timespec grpc_max_auth_token_lifetime = {3600, 0};
-#define GRPC_AUTH_JSON_TYPE_INVALID "invalid"
-#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account"
-#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user"
-
#define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256"
#define GRPC_JWT_TYPE "JWT"
@@ -66,7 +60,7 @@ static grpc_jwt_encode_and_sign_override g_jwt_encode_and_sign_override = NULL;
/* --- grpc_auth_json_key. --- */
-static const char *json_get_string_property(grpc_json *json,
+static const char *json_get_string_property(const grpc_json *json,
const char *prop_name) {
grpc_json *child;
for (child = json->child; child != NULL; child = child->next) {
@@ -79,7 +73,8 @@ static const char *json_get_string_property(grpc_json *json,
return child->value;
}
-static int set_json_key_string_property(grpc_json *json, const char *prop_name,
+static int set_json_key_string_property(const grpc_json *json,
+ const char *prop_name,
char **json_key_field) {
const char *prop_value = json_get_string_property(json, prop_name);
if (prop_value == NULL) return 0;
@@ -92,11 +87,8 @@ int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key) {
strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID);
}
-grpc_auth_json_key grpc_auth_json_key_create_from_string(
- const char *json_string) {
+grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json) {
grpc_auth_json_key result;
- char *scratchpad = gpr_strdup(json_string);
- grpc_json *json = grpc_json_parse_string(scratchpad);
BIO *bio = NULL;
const char *prop_value;
int success = 0;
@@ -104,7 +96,7 @@ grpc_auth_json_key grpc_auth_json_key_create_from_string(
memset(&result, 0, sizeof(grpc_auth_json_key));
result.type = GRPC_AUTH_JSON_TYPE_INVALID;
if (json == NULL) {
- gpr_log(GPR_ERROR, "Invalid json string %s", json_string);
+ gpr_log(GPR_ERROR, "Invalid json.");
goto end;
}
@@ -142,8 +134,16 @@ grpc_auth_json_key grpc_auth_json_key_create_from_string(
end:
if (bio != NULL) BIO_free(bio);
- if (json != NULL) grpc_json_destroy(json);
if (!success) grpc_auth_json_key_destruct(&result);
+ return result;
+}
+
+grpc_auth_json_key grpc_auth_json_key_create_from_string(
+ const char *json_string) {
+ char *scratchpad = gpr_strdup(json_string);
+ grpc_json *json = grpc_json_parse_string(scratchpad);
+ grpc_auth_json_key result = grpc_auth_json_key_create_from_json(json);
+ if (json != NULL) grpc_json_destroy(json);
gpr_free(scratchpad);
return result;
}
@@ -207,7 +207,7 @@ static char *encoded_jwt_claim(const grpc_auth_json_key *json_key,
grpc_json *child = NULL;
char *json_str = NULL;
char *result = NULL;
- gpr_timespec now = gpr_now();
+ gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
gpr_timespec expiration = gpr_time_add(now, token_lifetime);
char now_str[GPR_LTOA_MIN_BUFSIZE];
char expiration_str[GPR_LTOA_MIN_BUFSIZE];
@@ -218,8 +218,8 @@ static char *encoded_jwt_claim(const grpc_auth_json_key *json_key,
gpr_ltoa(now.tv_sec, now_str);
gpr_ltoa(expiration.tv_sec, expiration_str);
- child = create_child(NULL, json, "iss", json_key->client_email,
- GRPC_JSON_STRING);
+ child =
+ create_child(NULL, json, "iss", json_key->client_email, GRPC_JSON_STRING);
if (scope != NULL) {
child = create_child(child, json, "scope", scope, GRPC_JSON_STRING);
} else {
@@ -342,18 +342,16 @@ int grpc_auth_refresh_token_is_valid(
strcmp(refresh_token->type, GRPC_AUTH_JSON_TYPE_INVALID);
}
-grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
- const char *json_string) {
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
+ const grpc_json *json) {
grpc_auth_refresh_token result;
- char *scratchpad = gpr_strdup(json_string);
- grpc_json *json = grpc_json_parse_string(scratchpad);
const char *prop_value;
int success = 0;
memset(&result, 0, sizeof(grpc_auth_refresh_token));
result.type = GRPC_AUTH_JSON_TYPE_INVALID;
if (json == NULL) {
- gpr_log(GPR_ERROR, "Invalid json string %s", json_string);
+ gpr_log(GPR_ERROR, "Invalid json.");
goto end;
}
@@ -374,8 +372,17 @@ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
success = 1;
end:
- if (json != NULL) grpc_json_destroy(json);
if (!success) grpc_auth_refresh_token_destruct(&result);
+ return result;
+}
+
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
+ const char *json_string) {
+ char *scratchpad = gpr_strdup(json_string);
+ grpc_json *json = grpc_json_parse_string(scratchpad);
+ grpc_auth_refresh_token result =
+ grpc_auth_refresh_token_create_from_json(json);
+ if (json != NULL) grpc_json_destroy(json);
gpr_free(scratchpad);
return result;
}
@@ -396,4 +403,3 @@ void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token) {
refresh_token->refresh_token = NULL;
}
}
-
diff --git a/src/core/security/json_token.h b/src/core/security/json_token.h
index 197796ab4c..091dfefb6e 100644
--- a/src/core/security/json_token.h
+++ b/src/core/security/json_token.h
@@ -37,10 +37,16 @@
#include <grpc/support/slice.h>
#include <openssl/rsa.h>
+#include "src/core/json/json.h"
+
/* --- Constants. --- */
#define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token"
+#define GRPC_AUTH_JSON_TYPE_INVALID "invalid"
+#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account"
+#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user"
+
/* --- auth_json_key parsing. --- */
typedef struct {
@@ -59,6 +65,10 @@ int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key);
grpc_auth_json_key grpc_auth_json_key_create_from_string(
const char *json_string);
+/* Creates a json_key object from parsed json. Returns an invalid object if a
+ parsing error has been encountered. */
+grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json);
+
/* Destructs the object. */
void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key);
@@ -97,6 +107,11 @@ int grpc_auth_refresh_token_is_valid(
grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
const char *json_string);
+/* Creates a refresh token object from parsed json. Returns an invalid object if
+ a parsing error has been encountered. */
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
+ const grpc_json *json);
+
/* Destructs the object. */
void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token);
diff --git a/src/core/security/jwt_verifier.c b/src/core/security/jwt_verifier.c
new file mode 100644
index 0000000000..9140eb2ef7
--- /dev/null
+++ b/src/core/security/jwt_verifier.c
@@ -0,0 +1,832 @@
+/*
+ *
+ * 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 disclaimser.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimser
+ * 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 "src/core/security/jwt_verifier.h"
+
+#include <string.h>
+
+#include "src/core/httpcli/httpcli.h"
+#include "src/core/security/base64.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+#include <openssl/pem.h>
+
+/* --- Utils. --- */
+
+const char *grpc_jwt_verifier_status_to_string(
+ grpc_jwt_verifier_status status) {
+ switch (status) {
+ case GRPC_JWT_VERIFIER_OK:
+ return "OK";
+ case GRPC_JWT_VERIFIER_BAD_SIGNATURE:
+ return "BAD_SIGNATURE";
+ case GRPC_JWT_VERIFIER_BAD_FORMAT:
+ return "BAD_FORMAT";
+ case GRPC_JWT_VERIFIER_BAD_AUDIENCE:
+ return "BAD_AUDIENCE";
+ case GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR:
+ return "KEY_RETRIEVAL_ERROR";
+ case GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE:
+ return "TIME_CONSTRAINT_FAILURE";
+ case GRPC_JWT_VERIFIER_GENERIC_ERROR:
+ return "GENERIC_ERROR";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const EVP_MD *evp_md_from_alg(const char *alg) {
+ if (strcmp(alg, "RS256") == 0) {
+ return EVP_sha256();
+ } else if (strcmp(alg, "RS384") == 0) {
+ return EVP_sha384();
+ } else if (strcmp(alg, "RS512") == 0) {
+ return EVP_sha512();
+ } else {
+ return NULL;
+ }
+}
+
+static grpc_json *parse_json_part_from_jwt(const char *str, size_t len,
+ gpr_slice *buffer) {
+ grpc_json *json;
+
+ *buffer = grpc_base64_decode_with_len(str, len, 1);
+ if (GPR_SLICE_IS_EMPTY(*buffer)) {
+ gpr_log(GPR_ERROR, "Invalid base64.");
+ return NULL;
+ }
+ json = grpc_json_parse_string_with_len((char *)GPR_SLICE_START_PTR(*buffer),
+ GPR_SLICE_LENGTH(*buffer));
+ if (json == NULL) {
+ gpr_slice_unref(*buffer);
+ gpr_log(GPR_ERROR, "JSON parsing error.");
+ }
+ return json;
+}
+
+static const char *validate_string_field(const grpc_json *json,
+ const char *key) {
+ if (json->type != GRPC_JSON_STRING) {
+ gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value);
+ return NULL;
+ }
+ return json->value;
+}
+
+static gpr_timespec validate_time_field(const grpc_json *json,
+ const char *key) {
+ gpr_timespec result = gpr_time_0;
+ if (json->type != GRPC_JSON_NUMBER) {
+ gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value);
+ return result;
+ }
+ result.tv_sec = strtol(json->value, NULL, 10);
+ return result;
+}
+
+/* --- JOSE header. see http://tools.ietf.org/html/rfc7515#section-4 --- */
+
+typedef struct {
+ const char *alg;
+ const char *kid;
+ const char *typ;
+ /* TODO(jboeuf): Add others as needed (jku, jwk, x5u, x5c and so on...). */
+ gpr_slice buffer;
+} jose_header;
+
+static void jose_header_destroy(jose_header *h) {
+ gpr_slice_unref(h->buffer);
+ gpr_free(h);
+}
+
+/* Takes ownership of json and buffer. */
+static jose_header *jose_header_from_json(grpc_json *json, gpr_slice buffer) {
+ grpc_json *cur;
+ jose_header *h = gpr_malloc(sizeof(jose_header));
+ memset(h, 0, sizeof(jose_header));
+ h->buffer = buffer;
+ for (cur = json->child; cur != NULL; cur = cur->next) {
+ if (strcmp(cur->key, "alg") == 0) {
+ /* We only support RSA-1.5 signatures for now.
+ Beware of this if we add HMAC support:
+ https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
+ */
+ if (cur->type != GRPC_JSON_STRING || strncmp(cur->value, "RS", 2) ||
+ evp_md_from_alg(cur->value) == NULL) {
+ gpr_log(GPR_ERROR, "Invalid alg field [%s]", cur->value);
+ goto error;
+ }
+ h->alg = cur->value;
+ } else if (strcmp(cur->key, "typ") == 0) {
+ h->typ = validate_string_field(cur, "typ");
+ if (h->typ == NULL) goto error;
+ } else if (strcmp(cur->key, "kid") == 0) {
+ h->kid = validate_string_field(cur, "kid");
+ if (h->kid == NULL) goto error;
+ }
+ }
+ if (h->alg == NULL) {
+ gpr_log(GPR_ERROR, "Missing alg field.");
+ goto error;
+ }
+ grpc_json_destroy(json);
+ h->buffer = buffer;
+ return h;
+
+error:
+ grpc_json_destroy(json);
+ jose_header_destroy(h);
+ return NULL;
+}
+
+/* --- JWT claims. see http://tools.ietf.org/html/rfc7519#section-4.1 */
+
+struct grpc_jwt_claims {
+ /* Well known properties already parsed. */
+ const char *sub;
+ const char *iss;
+ const char *aud;
+ const char *jti;
+ gpr_timespec iat;
+ gpr_timespec exp;
+ gpr_timespec nbf;
+
+ grpc_json *json;
+ gpr_slice buffer;
+};
+
+void grpc_jwt_claims_destroy(grpc_jwt_claims *claims) {
+ grpc_json_destroy(claims->json);
+ gpr_slice_unref(claims->buffer);
+ gpr_free(claims);
+}
+
+const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims) {
+ if (claims == NULL) return NULL;
+ return claims->json;
+}
+
+const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims) {
+ if (claims == NULL) return NULL;
+ return claims->sub;
+}
+
+const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims) {
+ if (claims == NULL) return NULL;
+ return claims->iss;
+}
+
+const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims) {
+ if (claims == NULL) return NULL;
+ return claims->jti;
+}
+
+const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims) {
+ if (claims == NULL) return NULL;
+ return claims->aud;
+}
+
+gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims) {
+ if (claims == NULL) return gpr_inf_past;
+ return claims->iat;
+}
+
+gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims) {
+ if (claims == NULL) return gpr_inf_future;
+ return claims->exp;
+}
+
+gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims) {
+ if (claims == NULL) return gpr_inf_past;
+ return claims->nbf;
+}
+
+/* Takes ownership of json and buffer even in case of failure. */
+grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, gpr_slice buffer) {
+ grpc_json *cur;
+ grpc_jwt_claims *claims = gpr_malloc(sizeof(grpc_jwt_claims));
+ memset(claims, 0, sizeof(grpc_jwt_claims));
+ claims->json = json;
+ claims->buffer = buffer;
+ claims->iat = gpr_inf_past;
+ claims->nbf = gpr_inf_past;
+ claims->exp = gpr_inf_future;
+
+ /* Per the spec, all fields are optional. */
+ for (cur = json->child; cur != NULL; cur = cur->next) {
+ if (strcmp(cur->key, "sub") == 0) {
+ claims->sub = validate_string_field(cur, "sub");
+ if (claims->sub == NULL) goto error;
+ } else if (strcmp(cur->key, "iss") == 0) {
+ claims->iss = validate_string_field(cur, "iss");
+ if (claims->iss == NULL) goto error;
+ } else if (strcmp(cur->key, "aud") == 0) {
+ claims->aud = validate_string_field(cur, "aud");
+ if (claims->aud == NULL) goto error;
+ } else if (strcmp(cur->key, "jti") == 0) {
+ claims->jti = validate_string_field(cur, "jti");
+ if (claims->jti == NULL) goto error;
+ } else if (strcmp(cur->key, "iat") == 0) {
+ claims->iat = validate_time_field(cur, "iat");
+ if (gpr_time_cmp(claims->iat, gpr_time_0) == 0) goto error;
+ } else if (strcmp(cur->key, "exp") == 0) {
+ claims->exp = validate_time_field(cur, "exp");
+ if (gpr_time_cmp(claims->exp, gpr_time_0) == 0) goto error;
+ } else if (strcmp(cur->key, "nbf") == 0) {
+ claims->nbf = validate_time_field(cur, "nbf");
+ if (gpr_time_cmp(claims->nbf, gpr_time_0) == 0) goto error;
+ }
+ }
+ return claims;
+
+error:
+ grpc_jwt_claims_destroy(claims);
+ return NULL;
+}
+
+grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
+ const char *audience) {
+ gpr_timespec skewed_now;
+ int audience_ok;
+
+ GPR_ASSERT(claims != NULL);
+
+ skewed_now =
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
+ if (gpr_time_cmp(skewed_now, claims->nbf) < 0) {
+ gpr_log(GPR_ERROR, "JWT is not valid yet.");
+ return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
+ }
+ skewed_now =
+ gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
+ if (gpr_time_cmp(skewed_now, claims->exp) > 0) {
+ gpr_log(GPR_ERROR, "JWT is expired.");
+ return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
+ }
+
+ if (audience == NULL) {
+ audience_ok = claims->aud == NULL;
+ } else {
+ audience_ok = claims->aud != NULL && strcmp(audience, claims->aud) == 0;
+ }
+ if (!audience_ok) {
+ gpr_log(GPR_ERROR, "Audience mismatch: expected %s and found %s.",
+ audience == NULL ? "NULL" : audience,
+ claims->aud == NULL ? "NULL" : claims->aud);
+ return GRPC_JWT_VERIFIER_BAD_AUDIENCE;
+ }
+ return GRPC_JWT_VERIFIER_OK;
+}
+
+/* --- verifier_cb_ctx object. --- */
+
+typedef struct {
+ grpc_jwt_verifier *verifier;
+ grpc_pollset *pollset;
+ jose_header *header;
+ grpc_jwt_claims *claims;
+ char *audience;
+ gpr_slice signature;
+ gpr_slice signed_data;
+ void *user_data;
+ grpc_jwt_verification_done_cb user_cb;
+} verifier_cb_ctx;
+
+/* Takes ownership of the header, claims and signature. */
+static verifier_cb_ctx *verifier_cb_ctx_create(
+ grpc_jwt_verifier *verifier, grpc_pollset *pollset, jose_header *header,
+ grpc_jwt_claims *claims, const char *audience, gpr_slice signature,
+ const char *signed_jwt, size_t signed_jwt_len, void *user_data,
+ grpc_jwt_verification_done_cb cb) {
+ verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx));
+ memset(ctx, 0, sizeof(verifier_cb_ctx));
+ ctx->verifier = verifier;
+ ctx->pollset = pollset;
+ ctx->header = header;
+ ctx->audience = gpr_strdup(audience);
+ ctx->claims = claims;
+ ctx->signature = signature;
+ ctx->signed_data = gpr_slice_from_copied_buffer(signed_jwt, signed_jwt_len);
+ ctx->user_data = user_data;
+ ctx->user_cb = cb;
+ return ctx;
+}
+
+void verifier_cb_ctx_destroy(verifier_cb_ctx *ctx) {
+ if (ctx->audience != NULL) gpr_free(ctx->audience);
+ if (ctx->claims != NULL) grpc_jwt_claims_destroy(ctx->claims);
+ gpr_slice_unref(ctx->signature);
+ gpr_slice_unref(ctx->signed_data);
+ jose_header_destroy(ctx->header);
+ /* TODO: see what to do with claims... */
+ gpr_free(ctx);
+}
+
+/* --- grpc_jwt_verifier object. --- */
+
+/* Clock skew defaults to one minute. */
+gpr_timespec grpc_jwt_verifier_clock_skew = {60, 0};
+
+/* Max delay defaults to one minute. */
+gpr_timespec grpc_jwt_verifier_max_delay = {60, 0};
+
+typedef struct {
+ char *email_domain;
+ char *key_url_prefix;
+} email_key_mapping;
+
+struct grpc_jwt_verifier {
+ email_key_mapping *mappings;
+ size_t num_mappings; /* Should be very few, linear search ok. */
+ size_t allocated_mappings;
+ grpc_httpcli_context http_ctx;
+};
+
+static grpc_json *json_from_http(const grpc_httpcli_response *response) {
+ grpc_json *json = NULL;
+
+ if (response == NULL) {
+ gpr_log(GPR_ERROR, "HTTP response is NULL.");
+ return NULL;
+ }
+ if (response->status != 200) {
+ gpr_log(GPR_ERROR, "Call to http server failed with error %d.",
+ response->status);
+ return NULL;
+ }
+
+ json = grpc_json_parse_string_with_len(response->body, response->body_length);
+ if (json == NULL) {
+ gpr_log(GPR_ERROR, "Invalid JSON found in response.");
+ }
+ return json;
+}
+
+static const grpc_json *find_property_by_name(const grpc_json *json,
+ const char *name) {
+ const grpc_json *cur;
+ for (cur = json->child; cur != NULL; cur = cur->next) {
+ if (strcmp(cur->key, name) == 0) return cur;
+ }
+ return NULL;
+}
+
+static EVP_PKEY *extract_pkey_from_x509(const char *x509_str) {
+ X509 *x509 = NULL;
+ EVP_PKEY *result = NULL;
+ BIO *bio = BIO_new(BIO_s_mem());
+ BIO_write(bio, x509_str, strlen(x509_str));
+ x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ if (x509 == NULL) {
+ gpr_log(GPR_ERROR, "Unable to parse x509 cert.");
+ goto end;
+ }
+ result = X509_get_pubkey(x509);
+ if (result == NULL) {
+ gpr_log(GPR_ERROR, "Cannot find public key in X509 cert.");
+ }
+
+end:
+ BIO_free(bio);
+ if (x509 != NULL) X509_free(x509);
+ return result;
+}
+
+static BIGNUM *bignum_from_base64(const char *b64) {
+ BIGNUM *result = NULL;
+ gpr_slice bin;
+
+ if (b64 == NULL) return NULL;
+ bin = grpc_base64_decode(b64, 1);
+ if (GPR_SLICE_IS_EMPTY(bin)) {
+ gpr_log(GPR_ERROR, "Invalid base64 for big num.");
+ return NULL;
+ }
+ result = BN_bin2bn(GPR_SLICE_START_PTR(bin), GPR_SLICE_LENGTH(bin), NULL);
+ gpr_slice_unref(bin);
+ return result;
+}
+
+static EVP_PKEY *pkey_from_jwk(const grpc_json *json, const char *kty) {
+ const grpc_json *key_prop;
+ RSA *rsa = NULL;
+ EVP_PKEY *result = NULL;
+
+ GPR_ASSERT(kty != NULL && json != NULL);
+ if (strcmp(kty, "RSA") != 0) {
+ gpr_log(GPR_ERROR, "Unsupported key type %s.", kty);
+ goto end;
+ }
+ rsa = RSA_new();
+ if (rsa == NULL) {
+ gpr_log(GPR_ERROR, "Could not create rsa key.");
+ goto end;
+ }
+ for (key_prop = json->child; key_prop != NULL; key_prop = key_prop->next) {
+ if (strcmp(key_prop->key, "n") == 0) {
+ rsa->n = bignum_from_base64(validate_string_field(key_prop, "n"));
+ if (rsa->n == NULL) goto end;
+ } else if (strcmp(key_prop->key, "e") == 0) {
+ rsa->e = bignum_from_base64(validate_string_field(key_prop, "e"));
+ if (rsa->e == NULL) goto end;
+ }
+ }
+ if (rsa->e == NULL || rsa->n == NULL) {
+ gpr_log(GPR_ERROR, "Missing RSA public key field.");
+ goto end;
+ }
+ result = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(result, rsa); /* uprefs rsa. */
+
+end:
+ if (rsa != NULL) RSA_free(rsa);
+ return result;
+}
+
+static EVP_PKEY *find_verification_key(const grpc_json *json,
+ const char *header_alg,
+ const char *header_kid) {
+ const grpc_json *jkey;
+ const grpc_json *jwk_keys;
+ /* Try to parse the json as a JWK set:
+ https://tools.ietf.org/html/rfc7517#section-5. */
+ jwk_keys = find_property_by_name(json, "keys");
+ if (jwk_keys == NULL) {
+ /* Use the google proprietary format which is:
+ { <kid1>: <x5091>, <kid2>: <x5092>, ... } */
+ const grpc_json *cur = find_property_by_name(json, header_kid);
+ if (cur == NULL) return NULL;
+ return extract_pkey_from_x509(cur->value);
+ }
+
+ if (jwk_keys->type != GRPC_JSON_ARRAY) {
+ gpr_log(GPR_ERROR,
+ "Unexpected value type of keys property in jwks key set.");
+ return NULL;
+ }
+ /* Key format is specified in:
+ https://tools.ietf.org/html/rfc7518#section-6. */
+ for (jkey = jwk_keys->child; jkey != NULL; jkey = jkey->next) {
+ grpc_json *key_prop;
+ const char *alg = NULL;
+ const char *kid = NULL;
+ const char *kty = NULL;
+
+ if (jkey->type != GRPC_JSON_OBJECT) continue;
+ for (key_prop = jkey->child; key_prop != NULL; key_prop = key_prop->next) {
+ if (strcmp(key_prop->key, "alg") == 0 &&
+ key_prop->type == GRPC_JSON_STRING) {
+ alg = key_prop->value;
+ } else if (strcmp(key_prop->key, "kid") == 0 &&
+ key_prop->type == GRPC_JSON_STRING) {
+ kid = key_prop->value;
+ } else if (strcmp(key_prop->key, "kty") == 0 &&
+ key_prop->type == GRPC_JSON_STRING) {
+ kty = key_prop->value;
+ }
+ }
+ if (alg != NULL && kid != NULL && kty != NULL &&
+ strcmp(kid, header_kid) == 0 && strcmp(alg, header_alg) == 0) {
+ return pkey_from_jwk(jkey, kty);
+ }
+ }
+ gpr_log(GPR_ERROR,
+ "Could not find matching key in key set for kid=%s and alg=%s",
+ header_kid, header_alg);
+ return NULL;
+}
+
+static int verify_jwt_signature(EVP_PKEY *key, const char *alg,
+ gpr_slice signature, gpr_slice signed_data) {
+ EVP_MD_CTX *md_ctx = EVP_MD_CTX_create();
+ const EVP_MD *md = evp_md_from_alg(alg);
+ int result = 0;
+
+ GPR_ASSERT(md != NULL); /* Checked before. */
+ if (md_ctx == NULL) {
+ gpr_log(GPR_ERROR, "Could not create EVP_MD_CTX.");
+ goto end;
+ }
+ if (EVP_DigestVerifyInit(md_ctx, NULL, md, NULL, key) != 1) {
+ gpr_log(GPR_ERROR, "EVP_DigestVerifyInit failed.");
+ goto end;
+ }
+ if (EVP_DigestVerifyUpdate(md_ctx, GPR_SLICE_START_PTR(signed_data),
+ GPR_SLICE_LENGTH(signed_data)) != 1) {
+ gpr_log(GPR_ERROR, "EVP_DigestVerifyUpdate failed.");
+ goto end;
+ }
+ if (EVP_DigestVerifyFinal(md_ctx, GPR_SLICE_START_PTR(signature),
+ GPR_SLICE_LENGTH(signature)) != 1) {
+ gpr_log(GPR_ERROR, "JWT signature verification failed.");
+ goto end;
+ }
+ result = 1;
+
+end:
+ if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx);
+ return result;
+}
+
+static void on_keys_retrieved(void *user_data,
+ const grpc_httpcli_response *response) {
+ grpc_json *json = json_from_http(response);
+ verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
+ EVP_PKEY *verification_key = NULL;
+ grpc_jwt_verifier_status status = GRPC_JWT_VERIFIER_GENERIC_ERROR;
+ grpc_jwt_claims *claims = NULL;
+
+ if (json == NULL) {
+ status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR;
+ goto end;
+ }
+ verification_key =
+ find_verification_key(json, ctx->header->alg, ctx->header->kid);
+ if (verification_key == NULL) {
+ gpr_log(GPR_ERROR, "Could not find verification key with kid %s.",
+ ctx->header->kid);
+ status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR;
+ goto end;
+ }
+
+ if (!verify_jwt_signature(verification_key, ctx->header->alg, ctx->signature,
+ ctx->signed_data)) {
+ status = GRPC_JWT_VERIFIER_BAD_SIGNATURE;
+ goto end;
+ }
+
+ status = grpc_jwt_claims_check(ctx->claims, ctx->audience);
+ if (status == GRPC_JWT_VERIFIER_OK) {
+ /* Pass ownership. */
+ claims = ctx->claims;
+ ctx->claims = NULL;
+ }
+
+end:
+ if (json != NULL) grpc_json_destroy(json);
+ if (verification_key != NULL) EVP_PKEY_free(verification_key);
+ ctx->user_cb(ctx->user_data, status, claims);
+ verifier_cb_ctx_destroy(ctx);
+}
+
+static void on_openid_config_retrieved(void *user_data,
+ const grpc_httpcli_response *response) {
+ const grpc_json *cur;
+ grpc_json *json = json_from_http(response);
+ verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
+ grpc_httpcli_request req;
+ const char *jwks_uri;
+
+ /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time.*/
+ if (json == NULL) goto error;
+ cur = find_property_by_name(json, "jwks_uri");
+ if (cur == NULL) {
+ gpr_log(GPR_ERROR, "Could not find jwks_uri in openid config.");
+ goto error;
+ }
+ jwks_uri = validate_string_field(cur, "jwks_uri");
+ if (jwks_uri == NULL) goto error;
+ if (strstr(jwks_uri, "https://") != jwks_uri) {
+ gpr_log(GPR_ERROR, "Invalid non https jwks_uri: %s.", jwks_uri);
+ goto error;
+ }
+ jwks_uri += 8;
+ req.use_ssl = 1;
+ req.host = gpr_strdup(jwks_uri);
+ req.path = strchr(jwks_uri, '/');
+ if (req.path == NULL) {
+ req.path = "";
+ } else {
+ *(req.host + (req.path - jwks_uri)) = '\0';
+ }
+ grpc_httpcli_get(
+ &ctx->verifier->http_ctx, ctx->pollset, &req,
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
+ on_keys_retrieved, ctx);
+ grpc_json_destroy(json);
+ gpr_free(req.host);
+ return;
+
+error:
+ if (json != NULL) grpc_json_destroy(json);
+ ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
+ verifier_cb_ctx_destroy(ctx);
+}
+
+static email_key_mapping *verifier_get_mapping(grpc_jwt_verifier *v,
+ const char *email_domain) {
+ size_t i;
+ if (v->mappings == NULL) return NULL;
+ for (i = 0; i < v->num_mappings; i++) {
+ if (strcmp(email_domain, v->mappings[i].email_domain) == 0) {
+ return &v->mappings[i];
+ }
+ }
+ return NULL;
+}
+
+static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain,
+ const char *key_url_prefix) {
+ email_key_mapping *mapping = verifier_get_mapping(v, email_domain);
+ GPR_ASSERT(v->num_mappings < v->allocated_mappings);
+ if (mapping != NULL) {
+ gpr_free(mapping->key_url_prefix);
+ mapping->key_url_prefix = gpr_strdup(key_url_prefix);
+ return;
+ }
+ v->mappings[v->num_mappings].email_domain = gpr_strdup(email_domain);
+ v->mappings[v->num_mappings].key_url_prefix = gpr_strdup(key_url_prefix);
+ v->num_mappings++;
+ GPR_ASSERT(v->num_mappings <= v->allocated_mappings);
+}
+
+/* Takes ownership of ctx. */
+static void retrieve_key_and_verify(verifier_cb_ctx *ctx) {
+ const char *at_sign;
+ grpc_httpcli_response_cb http_cb;
+ char *path_prefix = NULL;
+ const char *iss;
+ grpc_httpcli_request req;
+ memset(&req, 0, sizeof(grpc_httpcli_request));
+ req.use_ssl = 1;
+
+ GPR_ASSERT(ctx != NULL && ctx->header != NULL && ctx->claims != NULL);
+ iss = ctx->claims->iss;
+ if (ctx->header->kid == NULL) {
+ gpr_log(GPR_ERROR, "Missing kid in jose header.");
+ goto error;
+ }
+ if (iss == NULL) {
+ gpr_log(GPR_ERROR, "Missing iss in claims.");
+ goto error;
+ }
+
+ /* This code relies on:
+ https://openid.net/specs/openid-connect-discovery-1_0.html
+ Nobody seems to implement the account/email/webfinger part 2. of the spec
+ so we will rely instead on email/url mappings if we detect such an issuer.
+ Part 4, on the other hand is implemented by both google and salesforce. */
+
+ /* Very non-sophisticated way to detect an email address. Should be good
+ enough for now... */
+ at_sign = strchr(iss, '@');
+ if (at_sign != NULL) {
+ email_key_mapping *mapping;
+ const char *email_domain = at_sign + 1;
+ GPR_ASSERT(ctx->verifier != NULL);
+ mapping = verifier_get_mapping(ctx->verifier, email_domain);
+ if (mapping == NULL) {
+ gpr_log(GPR_ERROR, "Missing mapping for issuer email.");
+ goto error;
+ }
+ req.host = gpr_strdup(mapping->key_url_prefix);
+ path_prefix = strchr(req.host, '/');
+ if (path_prefix == NULL) {
+ gpr_asprintf(&req.path, "/%s", iss);
+ } else {
+ *(path_prefix++) = '\0';
+ gpr_asprintf(&req.path, "/%s/%s", path_prefix, iss);
+ }
+ http_cb = on_keys_retrieved;
+ } else {
+ req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss);
+ path_prefix = strchr(req.host, '/');
+ if (path_prefix == NULL) {
+ req.path = gpr_strdup(GRPC_OPENID_CONFIG_URL_SUFFIX);
+ } else {
+ *(path_prefix++) = 0;
+ gpr_asprintf(&req.path, "/%s%s", path_prefix,
+ GRPC_OPENID_CONFIG_URL_SUFFIX);
+ }
+ http_cb = on_openid_config_retrieved;
+ }
+
+ grpc_httpcli_get(
+ &ctx->verifier->http_ctx, ctx->pollset, &req,
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
+ http_cb, ctx);
+ gpr_free(req.host);
+ gpr_free(req.path);
+ return;
+
+error:
+ ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
+ verifier_cb_ctx_destroy(ctx);
+}
+
+void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier,
+ grpc_pollset *pollset, const char *jwt,
+ const char *audience,
+ grpc_jwt_verification_done_cb cb,
+ void *user_data) {
+ const char *dot = NULL;
+ grpc_json *json;
+ jose_header *header = NULL;
+ grpc_jwt_claims *claims = NULL;
+ gpr_slice header_buffer;
+ gpr_slice claims_buffer;
+ gpr_slice signature;
+ size_t signed_jwt_len;
+ const char *cur = jwt;
+
+ GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL);
+ dot = strchr(cur, '.');
+ if (dot == NULL) goto error;
+ json = parse_json_part_from_jwt(cur, dot - cur, &header_buffer);
+ if (json == NULL) goto error;
+ header = jose_header_from_json(json, header_buffer);
+ if (header == NULL) goto error;
+
+ cur = dot + 1;
+ dot = strchr(cur, '.');
+ if (dot == NULL) goto error;
+ json = parse_json_part_from_jwt(cur, dot - cur, &claims_buffer);
+ if (json == NULL) goto error;
+ claims = grpc_jwt_claims_from_json(json, claims_buffer);
+ if (claims == NULL) goto error;
+
+ signed_jwt_len = (size_t)(dot - jwt);
+ cur = dot + 1;
+ signature = grpc_base64_decode(cur, 1);
+ if (GPR_SLICE_IS_EMPTY(signature)) goto error;
+ retrieve_key_and_verify(
+ verifier_cb_ctx_create(verifier, pollset, header, claims, audience,
+ signature, jwt, signed_jwt_len, user_data, cb));
+ return;
+
+error:
+ if (header != NULL) jose_header_destroy(header);
+ if (claims != NULL) grpc_jwt_claims_destroy(claims);
+ cb(user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL);
+}
+
+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_httpcli_context_init(&v->http_ctx);
+
+ /* We know at least of one mapping. */
+ v->allocated_mappings = 1 + num_mappings;
+ v->mappings = gpr_malloc(v->allocated_mappings * sizeof(email_key_mapping));
+ verifier_put_mapping(v, GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN,
+ GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX);
+ /* User-Provided mappings. */
+ if (mappings != NULL) {
+ size_t i;
+ for (i = 0; i < num_mappings; i++) {
+ verifier_put_mapping(v, mappings[i].email_domain,
+ mappings[i].key_url_prefix);
+ }
+ }
+ return v;
+}
+
+void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v) {
+ size_t i;
+ if (v == NULL) return;
+ grpc_httpcli_context_destroy(&v->http_ctx);
+ if (v->mappings != NULL) {
+ for (i = 0; i < v->num_mappings; i++) {
+ gpr_free(v->mappings[i].email_domain);
+ gpr_free(v->mappings[i].key_url_prefix);
+ }
+ gpr_free(v->mappings);
+ }
+ gpr_free(v);
+}
diff --git a/src/core/security/jwt_verifier.h b/src/core/security/jwt_verifier.h
new file mode 100644
index 0000000000..8077e24883
--- /dev/null
+++ b/src/core/security/jwt_verifier.h
@@ -0,0 +1,136 @@
+/*
+ *
+ * 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 disclaimser.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimser
+ * 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_CORE_SECURITY_JWT_VERIFIER_H
+#define GRPC_INTERNAL_CORE_SECURITY_JWT_VERIFIER_H
+
+#include "src/core/iomgr/pollset.h"
+#include "src/core/json/json.h"
+
+#include <grpc/support/slice.h>
+#include <grpc/support/time.h>
+
+/* --- Constants. --- */
+
+#define GRPC_OPENID_CONFIG_URL_SUFFIX "/.well-known/openid-configuration"
+#define GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN \
+ "developer.gserviceaccount.com"
+#define GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX \
+ "www.googleapis.com/robot/v1/metadata/x509"
+
+/* --- grpc_jwt_verifier_status. --- */
+
+typedef enum {
+ GRPC_JWT_VERIFIER_OK = 0,
+ GRPC_JWT_VERIFIER_BAD_SIGNATURE,
+ GRPC_JWT_VERIFIER_BAD_FORMAT,
+ GRPC_JWT_VERIFIER_BAD_AUDIENCE,
+ GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR,
+ GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE,
+ GRPC_JWT_VERIFIER_GENERIC_ERROR
+} grpc_jwt_verifier_status;
+
+const char *grpc_jwt_verifier_status_to_string(grpc_jwt_verifier_status status);
+
+/* --- grpc_jwt_claims. --- */
+
+typedef struct grpc_jwt_claims grpc_jwt_claims;
+
+void grpc_jwt_claims_destroy(grpc_jwt_claims *claims);
+
+/* Returns the whole JSON tree of the claims. */
+const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims);
+
+/* Access to registered claims in https://tools.ietf.org/html/rfc7519#page-9 */
+const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims);
+const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims);
+const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims);
+const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims);
+gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims);
+gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims);
+gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims);
+
+/* --- grpc_jwt_verifier. --- */
+
+typedef struct grpc_jwt_verifier grpc_jwt_verifier;
+
+typedef struct {
+ /* The email domain is the part after the @ sign. */
+ const char *email_domain;
+
+ /* The key url prefix will be used to get the public key from the issuer:
+ https://<key_url_prefix>/<issuer_email>
+ Therefore the key_url_prefix must NOT contain https://. */
+ const char *key_url_prefix;
+} grpc_jwt_verifier_email_domain_key_url_mapping;
+
+/* Globals to control the verifier. Not thread-safe. */
+extern gpr_timespec grpc_jwt_verifier_clock_skew;
+extern gpr_timespec grpc_jwt_verifier_max_delay;
+
+/* The verifier can be created with some custom mappings to help with key
+ discovery in the case where the issuer is an email address.
+ mappings can be NULL in which case num_mappings MUST be 0.
+ A verifier object has one built-in mapping (unless overridden):
+ GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN ->
+ GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX.*/
+grpc_jwt_verifier *grpc_jwt_verifier_create(
+ const grpc_jwt_verifier_email_domain_key_url_mapping *mappings,
+ 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);
+
+/* User provided callback that will be called when the verification of the JWT
+ is done (maybe in another thread).
+ It is the responsibility of the callee to call grpc_jwt_claims_destroy on
+ the claims. */
+typedef void (*grpc_jwt_verification_done_cb)(void *user_data,
+ grpc_jwt_verifier_status status,
+ grpc_jwt_claims *claims);
+
+/* Verifies for the JWT for the given expected audience. */
+void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier,
+ grpc_pollset *pollset, const char *jwt,
+ const char *audience,
+ grpc_jwt_verification_done_cb cb,
+ void *user_data);
+
+/* --- TESTING ONLY exposed functions. --- */
+
+grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, gpr_slice buffer);
+grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
+ const char *audience);
+
+#endif /* GRPC_INTERNAL_CORE_SECURITY_JWT_VERIFIER_H */
+
diff --git a/src/core/security/secure_endpoint.c b/src/core/security/secure_endpoint.c
index 73496d1153..3548198046 100644
--- a/src/core/security/secure_endpoint.c
+++ b/src/core/security/secure_endpoint.c
@@ -101,9 +101,7 @@ static void call_read_cb(secure_endpoint *ep, gpr_slice *slices, size_t nslices,
if (grpc_trace_secure_endpoint) {
size_t i;
for (i = 0; i < nslices; i++) {
- char *data =
- gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]),
- GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT);
+ char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "READ %p: %s", ep, data);
gpr_free(data);
}
@@ -235,9 +233,7 @@ static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep,
if (grpc_trace_secure_endpoint) {
for (i = 0; i < nslices; i++) {
- char *data =
- gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]),
- GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT);
+ char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data);
gpr_free(data);
}
diff --git a/src/core/security/secure_transport_setup.c b/src/core/security/secure_transport_setup.c
index 731b382f09..0c3572b53c 100644
--- a/src/core/security/secure_transport_setup.c
+++ b/src/core/security/secure_transport_setup.c
@@ -47,7 +47,8 @@ typedef struct {
tsi_handshaker *handshaker;
unsigned char *handshake_buffer;
size_t handshake_buffer_size;
- grpc_endpoint *endpoint;
+ grpc_endpoint *wrapped_endpoint;
+ grpc_endpoint *secure_endpoint;
gpr_slice_buffer left_overs;
grpc_secure_transport_setup_done_cb cb;
void *user_data;
@@ -63,13 +64,16 @@ static void on_handshake_data_sent_to_peer(void *setup,
static void secure_transport_setup_done(grpc_secure_transport_setup *s,
int is_success) {
if (is_success) {
- s->cb(s->user_data, GRPC_SECURITY_OK, s->endpoint);
+ s->cb(s->user_data, GRPC_SECURITY_OK, s->wrapped_endpoint,
+ s->secure_endpoint);
} else {
- if (s->endpoint != NULL) {
- grpc_endpoint_shutdown(s->endpoint);
- grpc_endpoint_destroy(s->endpoint);
+ if (s->secure_endpoint != NULL) {
+ grpc_endpoint_shutdown(s->secure_endpoint);
+ grpc_endpoint_destroy(s->secure_endpoint);
+ } else {
+ grpc_endpoint_destroy(s->wrapped_endpoint);
}
- s->cb(s->user_data, GRPC_SECURITY_ERROR, NULL);
+ s->cb(s->user_data, GRPC_SECURITY_ERROR, s->wrapped_endpoint, NULL);
}
if (s->handshaker != NULL) tsi_handshaker_destroy(s->handshaker);
if (s->handshake_buffer != NULL) gpr_free(s->handshake_buffer);
@@ -95,8 +99,9 @@ static void on_peer_checked(void *user_data, grpc_security_status status) {
secure_transport_setup_done(s, 0);
return;
}
- s->endpoint = grpc_secure_endpoint_create(
- protector, s->endpoint, s->left_overs.slices, s->left_overs.count);
+ s->secure_endpoint =
+ grpc_secure_endpoint_create(protector, s->wrapped_endpoint,
+ s->left_overs.slices, s->left_overs.count);
secure_transport_setup_done(s, 1);
return;
}
@@ -152,7 +157,7 @@ static void send_handshake_bytes_to_peer(grpc_secure_transport_setup *s) {
gpr_slice_from_copied_buffer((const char *)s->handshake_buffer, offset);
/* TODO(klempner,jboeuf): This should probably use the client setup
deadline */
- write_status = grpc_endpoint_write(s->endpoint, &to_send, 1,
+ write_status = grpc_endpoint_write(s->wrapped_endpoint, &to_send, 1,
on_handshake_data_sent_to_peer, s);
if (write_status == GRPC_ENDPOINT_WRITE_ERROR) {
gpr_log(GPR_ERROR, "Could not send handshake data to peer.");
@@ -198,7 +203,7 @@ static void on_handshake_data_received_from_peer(
if (result == TSI_INCOMPLETE_DATA) {
/* TODO(klempner,jboeuf): This should probably use the client setup
deadline */
- grpc_endpoint_notify_on_read(s->endpoint,
+ grpc_endpoint_notify_on_read(s->wrapped_endpoint,
on_handshake_data_received_from_peer, setup);
cleanup_slices(slices, nslices);
return;
@@ -256,7 +261,7 @@ static void on_handshake_data_sent_to_peer(void *setup,
if (tsi_handshaker_is_in_progress(s->handshaker)) {
/* TODO(klempner,jboeuf): This should probably use the client setup
deadline */
- grpc_endpoint_notify_on_read(s->endpoint,
+ grpc_endpoint_notify_on_read(s->wrapped_endpoint,
on_handshake_data_received_from_peer, setup);
} else {
check_peer(s);
@@ -280,7 +285,7 @@ void grpc_setup_secure_transport(grpc_security_connector *connector,
GRPC_SECURITY_CONNECTOR_REF(connector, "secure_transport_setup");
s->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE;
s->handshake_buffer = gpr_malloc(s->handshake_buffer_size);
- s->endpoint = nonsecure_endpoint;
+ s->wrapped_endpoint = nonsecure_endpoint;
s->user_data = user_data;
s->cb = cb;
gpr_slice_buffer_init(&s->left_overs);
diff --git a/src/core/security/secure_transport_setup.h b/src/core/security/secure_transport_setup.h
index 58701c461d..29025f5236 100644
--- a/src/core/security/secure_transport_setup.h
+++ b/src/core/security/secure_transport_setup.h
@@ -42,7 +42,7 @@
/* Ownership of the secure_endpoint is transfered. */
typedef void (*grpc_secure_transport_setup_done_cb)(
void *user_data, grpc_security_status status,
- grpc_endpoint *secure_endpoint);
+ grpc_endpoint *wrapped_endpoint, grpc_endpoint *secure_endpoint);
/* Calls the callback upon completion. */
void grpc_setup_secure_transport(grpc_security_connector *connector,
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
index 4d56549f9b..8ce7876bd8 100644
--- a/src/core/security/security_context.c
+++ b/src/core/security/security_context.c
@@ -69,12 +69,20 @@ grpc_call_error grpc_call_set_credentials(grpc_call *call,
return GRPC_CALL_OK;
}
-const grpc_auth_context *grpc_call_auth_context(grpc_call *call) {
+grpc_auth_context *grpc_call_auth_context(grpc_call *call) {
void *sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY);
if (sec_ctx == NULL) return NULL;
return grpc_call_is_client(call)
- ? ((grpc_client_security_context *)sec_ctx)->auth_context
- : ((grpc_server_security_context *)sec_ctx)->auth_context;
+ ? GRPC_AUTH_CONTEXT_REF(
+ ((grpc_client_security_context *)sec_ctx)->auth_context,
+ "grpc_call_auth_context client")
+ : GRPC_AUTH_CONTEXT_REF(
+ ((grpc_server_security_context *)sec_ctx)->auth_context,
+ "grpc_call_auth_context server");
+}
+
+void grpc_auth_context_release(grpc_auth_context *context) {
+ GRPC_AUTH_CONTEXT_UNREF(context, "grpc_auth_context_unref");
}
/* --- grpc_client_security_context --- */
diff --git a/src/core/security/security_context.h b/src/core/security/security_context.h
index 20c4390898..76a45910bb 100644
--- a/src/core/security/security_context.h
+++ b/src/core/security/security_context.h
@@ -36,6 +36,10 @@
#include "src/core/security/credentials.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* --- grpc_auth_context ---
High level authentication context object. Can optionally be chained. */
@@ -103,5 +107,9 @@ typedef struct {
grpc_server_security_context *grpc_server_security_context_create(void);
void grpc_server_security_context_destroy(void *ctx);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H */
diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c
index 8a7ada07af..3717b8989f 100644
--- a/src/core/security/server_secure_chttp2.c
+++ b/src/core/security/server_secure_chttp2.c
@@ -51,10 +51,16 @@
#include <grpc/support/sync.h>
#include <grpc/support/useful.h>
+typedef struct tcp_endpoint_list {
+ grpc_endpoint *tcp_endpoint;
+ struct tcp_endpoint_list *next;
+} tcp_endpoint_list;
+
typedef struct grpc_server_secure_state {
grpc_server *server;
grpc_tcp_server *tcp;
grpc_security_connector *sc;
+ tcp_endpoint_list *handshaking_tcp_endpoints;
int is_shutdown;
gpr_mu mu;
gpr_refcount refcount;
@@ -88,14 +94,37 @@ static void setup_transport(void *statep, grpc_transport *transport,
grpc_channel_args_destroy(args_copy);
}
+static int remove_tcp_from_list_locked(grpc_server_secure_state *state,
+ grpc_endpoint *tcp) {
+ tcp_endpoint_list *node = state->handshaking_tcp_endpoints;
+ tcp_endpoint_list *tmp = NULL;
+ if (node && node->tcp_endpoint == tcp) {
+ state->handshaking_tcp_endpoints = state->handshaking_tcp_endpoints->next;
+ gpr_free(node);
+ return 0;
+ }
+ while (node) {
+ if (node->next->tcp_endpoint == tcp) {
+ tmp = node->next;
+ node->next = node->next->next;
+ gpr_free(tmp);
+ return 0;
+ }
+ node = node->next;
+ }
+ return -1;
+}
+
static void on_secure_transport_setup_done(void *statep,
grpc_security_status status,
+ grpc_endpoint *wrapped_endpoint,
grpc_endpoint *secure_endpoint) {
grpc_server_secure_state *state = statep;
grpc_transport *transport;
grpc_mdctx *mdctx;
if (status == GRPC_SECURITY_OK) {
gpr_mu_lock(&state->mu);
+ remove_tcp_from_list_locked(state, wrapped_endpoint);
if (!state->is_shutdown) {
mdctx = grpc_mdctx_create();
transport = grpc_create_chttp2_transport(
@@ -110,6 +139,9 @@ static void on_secure_transport_setup_done(void *statep,
}
gpr_mu_unlock(&state->mu);
} else {
+ gpr_mu_lock(&state->mu);
+ remove_tcp_from_list_locked(state, wrapped_endpoint);
+ gpr_mu_unlock(&state->mu);
gpr_log(GPR_ERROR, "Secure transport failed with error %d", status);
}
state_unref(state);
@@ -117,7 +149,14 @@ static void on_secure_transport_setup_done(void *statep,
static void on_accept(void *statep, grpc_endpoint *tcp) {
grpc_server_secure_state *state = statep;
+ tcp_endpoint_list *node;
state_ref(state);
+ node = gpr_malloc(sizeof(tcp_endpoint_list));
+ node->tcp_endpoint = tcp;
+ gpr_mu_lock(&state->mu);
+ node->next = state->handshaking_tcp_endpoints;
+ state->handshaking_tcp_endpoints = node;
+ gpr_mu_unlock(&state->mu);
grpc_setup_secure_transport(state->sc, tcp, on_secure_transport_setup_done,
state);
}
@@ -132,6 +171,13 @@ static void start(grpc_server *server, void *statep, grpc_pollset **pollsets,
static void destroy_done(void *statep) {
grpc_server_secure_state *state = statep;
grpc_server_listener_destroy_done(state->server);
+ gpr_mu_lock(&state->mu);
+ while (state->handshaking_tcp_endpoints != NULL) {
+ grpc_endpoint_shutdown(state->handshaking_tcp_endpoints->tcp_endpoint);
+ remove_tcp_from_list_locked(state,
+ state->handshaking_tcp_endpoints->tcp_endpoint);
+ }
+ gpr_mu_unlock(&state->mu);
state_unref(state);
}
@@ -209,6 +255,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
state->server = server;
state->tcp = tcp;
state->sc = sc;
+ state->handshaking_tcp_endpoints = NULL;
state->is_shutdown = 0;
gpr_mu_init(&state->mu);
gpr_ref_init(&state->refcount, 1);
diff --git a/src/core/statistics/census_rpc_stats.c b/src/core/statistics/census_rpc_stats.c
index 0491c91947..3e571b1143 100644
--- a/src/core/statistics/census_rpc_stats.c
+++ b/src/core/statistics/census_rpc_stats.c
@@ -157,7 +157,7 @@ static void record_stats(census_ht* store, census_op_id op_id,
key.ptr = gpr_strdup(key.ptr);
census_ht_insert(store, key, (void*)window_stats);
}
- census_window_stats_add(window_stats, gpr_now(), stats);
+ census_window_stats_add(window_stats, gpr_now(GPR_CLOCK_REALTIME), stats);
} else {
census_internal_unlock_trace_store();
}
@@ -185,7 +185,7 @@ static void get_stats(census_ht* store, census_aggregated_rpc_stats* data) {
if (store != NULL) {
size_t n;
unsigned i, j;
- gpr_timespec now = gpr_now();
+ gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
census_ht_kv* kv = census_ht_get_all_elements(store, &n);
if (kv != NULL) {
data->num_entries = n;
diff --git a/src/core/statistics/census_tracing.c b/src/core/statistics/census_tracing.c
index 05e72b99c0..3036ba5407 100644
--- a/src/core/statistics/census_tracing.c
+++ b/src/core/statistics/census_tracing.c
@@ -94,7 +94,7 @@ census_op_id census_tracing_start_op(void) {
g_id++;
memcpy(&ret->id, &g_id, sizeof(census_op_id));
ret->rpc_stats.cnt = 1;
- ret->ts = gpr_now();
+ ret->ts = gpr_now(GPR_CLOCK_REALTIME);
census_ht_insert(g_trace_store, op_id_as_key(&ret->id), (void*)ret);
gpr_log(GPR_DEBUG, "Start tracing for id %lu", g_id);
gpr_mu_unlock(&g_mu);
@@ -122,7 +122,7 @@ void census_tracing_print(census_op_id op_id, const char* anno_txt) {
trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
if (trace != NULL) {
census_trace_annotation* anno = gpr_malloc(sizeof(census_trace_annotation));
- anno->ts = gpr_now();
+ anno->ts = gpr_now(GPR_CLOCK_REALTIME);
{
char* d = anno->txt;
const char* s = anno_txt;
@@ -143,8 +143,8 @@ void census_tracing_end_op(census_op_id op_id) {
gpr_mu_lock(&g_mu);
trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
if (trace != NULL) {
- trace->rpc_stats.elapsed_time_ms =
- gpr_timespec_to_micros(gpr_time_sub(gpr_now(), trace->ts));
+ trace->rpc_stats.elapsed_time_ms = gpr_timespec_to_micros(
+ gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), trace->ts));
gpr_log(GPR_DEBUG, "End tracing for id %lu, method %s, latency %f us",
op_id_2_uint64(&op_id), trace->method,
trace->rpc_stats.elapsed_time_ms);
@@ -194,8 +194,8 @@ const char* census_get_trace_method_name(const census_trace_obj* trace) {
static census_trace_annotation* dup_annotation_chain(
census_trace_annotation* from) {
- census_trace_annotation *ret = NULL;
- census_trace_annotation **to = &ret;
+ census_trace_annotation* ret = NULL;
+ census_trace_annotation** to = &ret;
for (; from != NULL; from = from->next) {
*to = gpr_malloc(sizeof(census_trace_annotation));
memcpy(*to, from, sizeof(census_trace_annotation));
@@ -223,9 +223,9 @@ census_trace_obj** census_get_active_ops(int* num_active_ops) {
size_t n = 0;
census_ht_kv* all_kvs = census_ht_get_all_elements(g_trace_store, &n);
*num_active_ops = (int)n;
- if (n != 0 ) {
+ if (n != 0) {
size_t i = 0;
- ret = gpr_malloc(sizeof(census_trace_obj *) * n);
+ ret = gpr_malloc(sizeof(census_trace_obj*) * n);
for (i = 0; i < n; i++) {
ret[i] = trace_obj_dup((census_trace_obj*)all_kvs[i].v);
}
diff --git a/src/core/statistics/window_stats.h b/src/core/statistics/window_stats.h
index d733d8d247..0020f6b44c 100644
--- a/src/core/statistics/window_stats.h
+++ b/src/core/statistics/window_stats.h
@@ -90,11 +90,11 @@
// Record a new event, taking 15.3ms, transferring 1784 bytes.
stat.latency = 0.153;
stat.bytes = 1784;
- census_window_stats_add(stats, gpr_now(), &stat);
+ census_window_stats_add(stats, gpr_now(GPR_CLOCK_REALTIME), &stat);
// Get sums and print them out
result[kMinInterval].statistic = &sums[kMinInterval];
result[kHourInterval].statistic = &sums[kHourInterval];
- census_window_stats_get_sums(stats, gpr_now(), result);
+ census_window_stats_get_sums(stats, gpr_now(GPR_CLOCK_REALTIME), result);
printf("%d events/min, average time %gs, average bytes %g\n",
result[kMinInterval].count,
(my_stat*)result[kMinInterval].statistic->latency /
@@ -170,4 +170,4 @@ void census_window_stats_get_sums(const struct census_window_stats* wstats,
assertion failure). This function is thread-compatible. */
void census_window_stats_destroy(struct census_window_stats* wstats);
-#endif /* GRPC_INTERNAL_CORE_STATISTICS_WINDOW_STATS_H */
+#endif /* GRPC_INTERNAL_CORE_STATISTICS_WINDOW_STATS_H */
diff --git a/src/core/support/cancellable.c b/src/core/support/cancellable.c
index 5a4d488dd3..3cbb318ab6 100644
--- a/src/core/support/cancellable.c
+++ b/src/core/support/cancellable.c
@@ -121,8 +121,8 @@ void gpr_cancellable_cancel(gpr_cancellable *c) {
} else {
gpr_event ev;
gpr_event_init(&ev);
- gpr_event_wait(&ev,
- gpr_time_add(gpr_now(), gpr_time_from_micros(1000)));
+ gpr_event_wait(&ev, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(1000)));
}
}
} while (failures != 0);
diff --git a/src/core/support/log_linux.c b/src/core/support/log_linux.c
index 48349d2c83..5ac36e7b95 100644
--- a/src/core/support/log_linux.c
+++ b/src/core/support/log_linux.c
@@ -43,7 +43,9 @@
#ifdef GPR_LINUX
+#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include <stdio.h>
#include <stdarg.h>
@@ -71,9 +73,10 @@ void gpr_log(const char *file, int line, gpr_log_severity severity,
void gpr_default_log(gpr_log_func_args *args) {
char *final_slash;
+ char *prefix;
const char *display_file;
char time_buffer[64];
- gpr_timespec now = gpr_now();
+ gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
struct tm tm;
final_slash = strrchr(args->file, '/');
@@ -89,10 +92,12 @@ void gpr_default_log(gpr_log_func_args *args) {
strcpy(time_buffer, "error:strftime");
}
- fprintf(stderr, "%s%s.%09d %7ld %s:%d] %s\n",
+ gpr_asprintf(&prefix, "%s%s.%09d %7tu %s:%d]",
gpr_log_severity_string(args->severity), time_buffer,
- (int)(now.tv_nsec), gettid(), display_file, args->line,
- args->message);
+ (int)(now.tv_nsec), gettid(), display_file, args->line);
+
+ fprintf(stderr, "%-60s %s\n", prefix, args->message);
+ gpr_free(prefix);
}
#endif
diff --git a/src/core/support/log_posix.c b/src/core/support/log_posix.c
index afca792c40..940ee20f15 100644
--- a/src/core/support/log_posix.c
+++ b/src/core/support/log_posix.c
@@ -75,7 +75,7 @@ void gpr_default_log(gpr_log_func_args *args) {
char *final_slash;
const char *display_file;
char time_buffer[64];
- gpr_timespec now = gpr_now();
+ gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
struct tm tm;
final_slash = strrchr(args->file, '/');
diff --git a/src/core/support/log_win32.c b/src/core/support/log_win32.c
index d249be7d2e..629781da8a 100644
--- a/src/core/support/log_win32.c
+++ b/src/core/support/log_win32.c
@@ -82,7 +82,7 @@ void gpr_log(const char *file, int line, gpr_log_severity severity,
/* Simple starter implementation */
void gpr_default_log(gpr_log_func_args *args) {
char time_buffer[64];
- gpr_timespec now = gpr_now();
+ gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
struct tm tm;
if (localtime_s(&tm, &now.tv_sec)) {
diff --git a/src/core/support/slice.c b/src/core/support/slice.c
index a2d62fc1e5..e4196a48c6 100644
--- a/src/core/support/slice.c
+++ b/src/core/support/slice.c
@@ -325,3 +325,10 @@ int gpr_slice_str_cmp(gpr_slice a, const char *b) {
if (d != 0) return d;
return memcmp(GPR_SLICE_START_PTR(a), b, b_length);
}
+
+char *gpr_slice_to_cstring(gpr_slice slice) {
+ char *result = gpr_malloc(GPR_SLICE_LENGTH(slice) + 1);
+ memcpy(result, GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice));
+ result[GPR_SLICE_LENGTH(slice)] = '\0';
+ return result;
+}
diff --git a/src/core/support/stack_lockfree.c b/src/core/support/stack_lockfree.c
new file mode 100644
index 0000000000..9497efbfb5
--- /dev/null
+++ b/src/core/support/stack_lockfree.c
@@ -0,0 +1,130 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/core/support/stack_lockfree.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/support/port_platform.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/atm.h>
+#include <grpc/support/log.h>
+
+/* The lockfree node structure is a single architecture-level
+ word that allows for an atomic CAS to set it up. */
+struct lockfree_node_contents {
+ /* next thing to look at. Actual index for head, next index otherwise */
+ gpr_uint16 index;
+#ifdef GPR_ARCH_64
+ gpr_uint16 pad;
+ gpr_uint32 aba_ctr;
+#else
+#ifdef GPR_ARCH_32
+ gpr_uint16 aba_ctr;
+#else
+#error Unsupported bit width architecture
+#endif
+#endif
+};
+
+/* Use a union to make sure that these are in the same bits as an atm word */
+typedef union lockfree_node {
+ gpr_atm atm;
+ struct lockfree_node_contents contents;
+} lockfree_node;
+
+#define ENTRY_ALIGNMENT_BITS 3 /* make sure that entries aligned to 8-bytes */
+#define INVALID_ENTRY_INDEX ((1 << 16) - 1) /* reserve this entry as invalid \
+ */
+
+struct gpr_stack_lockfree {
+ lockfree_node *entries;
+ lockfree_node head; /* An atomic entry describing curr head */
+};
+
+gpr_stack_lockfree *gpr_stack_lockfree_create(int entries) {
+ gpr_stack_lockfree *stack;
+ stack = gpr_malloc(sizeof(*stack));
+ /* Since we only allocate 16 bits to represent an entry number,
+ * make sure that we are within the desired range */
+ /* Reserve the highest entry number as a dummy */
+ GPR_ASSERT(entries < INVALID_ENTRY_INDEX);
+ stack->entries = gpr_malloc_aligned(entries * sizeof(stack->entries[0]),
+ ENTRY_ALIGNMENT_BITS);
+ /* Clear out all entries */
+ memset(stack->entries, 0, entries * sizeof(stack->entries[0]));
+ memset(&stack->head, 0, sizeof(stack->head));
+
+ /* Point the head at reserved dummy entry */
+ stack->head.contents.index = INVALID_ENTRY_INDEX;
+ return stack;
+}
+
+void gpr_stack_lockfree_destroy(gpr_stack_lockfree *stack) {
+ gpr_free_aligned(stack->entries);
+ gpr_free(stack);
+}
+
+void gpr_stack_lockfree_push(gpr_stack_lockfree *stack, int entry) {
+ lockfree_node head;
+ lockfree_node newhead;
+
+ /* First fill in the entry's index and aba ctr for new head */
+ newhead.contents.index = (gpr_uint16)entry;
+ /* Also post-increment the aba_ctr */
+ newhead.contents.aba_ctr = stack->entries[entry].contents.aba_ctr++;
+
+ do {
+ /* Atomically get the existing head value for use */
+ head.atm = gpr_atm_no_barrier_load(&(stack->head.atm));
+ /* Point to it */
+ stack->entries[entry].contents.index = head.contents.index;
+ } while (!gpr_atm_rel_cas(&(stack->head.atm), head.atm, newhead.atm));
+ /* Use rel_cas above to make sure that entry index is set properly */
+}
+
+int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack) {
+ lockfree_node head;
+ lockfree_node newhead;
+ do {
+ head.atm = gpr_atm_acq_load(&(stack->head.atm));
+ if (head.contents.index == INVALID_ENTRY_INDEX) {
+ return -1;
+ }
+ newhead.atm =
+ gpr_atm_no_barrier_load(&(stack->entries[head.contents.index].atm));
+
+ } while (!gpr_atm_no_barrier_cas(&(stack->head.atm), head.atm, newhead.atm));
+ return head.contents.index;
+}
diff --git a/src/core/support/stack_lockfree.h b/src/core/support/stack_lockfree.h
new file mode 100644
index 0000000000..0bcf73635d
--- /dev/null
+++ b/src/core/support/stack_lockfree.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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_INTERNAL_CORE_SUPPORT_STACK_LOCKFREE_H
+#define GRPC_INTERNAL_CORE_SUPPORT_STACK_LOCKFREE_H
+
+typedef struct gpr_stack_lockfree gpr_stack_lockfree;
+
+/* This stack must specify the maximum number of entries to track.
+ The current implementation only allows up to 65534 entries */
+gpr_stack_lockfree* gpr_stack_lockfree_create(int entries);
+void gpr_stack_lockfree_destroy(gpr_stack_lockfree* stack);
+
+/* Pass in a valid entry number for the next stack entry */
+void gpr_stack_lockfree_push(gpr_stack_lockfree* stack, int entry);
+
+/* Returns -1 on empty or the actual entry number */
+int gpr_stack_lockfree_pop(gpr_stack_lockfree* stack);
+
+#endif /* GRPC_INTERNAL_CORE_SUPPORT_STACK_LOCKFREE_H */
diff --git a/src/core/support/string.c b/src/core/support/string.c
index 6a80ccc841..09598da946 100644
--- a/src/core/support/string.c
+++ b/src/core/support/string.c
@@ -61,14 +61,14 @@ typedef struct {
size_t capacity;
size_t length;
char *data;
-} hexout;
+} dump_out;
-static hexout hexout_create(void) {
- hexout r = {0, 0, NULL};
+static dump_out dump_out_create(void) {
+ dump_out r = {0, 0, NULL};
return r;
}
-static void hexout_append(hexout *out, char c) {
+static void dump_out_append(dump_out *out, char c) {
if (out->length == out->capacity) {
out->capacity = GPR_MAX(8, 2 * out->capacity);
out->data = gpr_realloc(out->data, out->capacity);
@@ -76,34 +76,55 @@ static void hexout_append(hexout *out, char c) {
out->data[out->length++] = c;
}
-char *gpr_hexdump(const char *buf, size_t len, gpr_uint32 flags) {
+static void hexdump(dump_out *out, const char *buf, size_t len) {
static const char hex[16] = "0123456789abcdef";
- hexout out = hexout_create();
const gpr_uint8 *const beg = (const gpr_uint8 *)buf;
const gpr_uint8 *const end = beg + len;
const gpr_uint8 *cur;
for (cur = beg; cur != end; ++cur) {
- if (cur != beg) hexout_append(&out, ' ');
- hexout_append(&out, hex[*cur >> 4]);
- hexout_append(&out, hex[*cur & 0xf]);
+ if (cur != beg) dump_out_append(out, ' ');
+ dump_out_append(out, hex[*cur >> 4]);
+ dump_out_append(out, hex[*cur & 0xf]);
}
+}
- if (flags & GPR_HEXDUMP_PLAINTEXT) {
- if (len) hexout_append(&out, ' ');
- hexout_append(&out, '\'');
- for (cur = beg; cur != end; ++cur) {
- hexout_append(&out, isprint(*cur) ? *(char*)cur : '.');
- }
- hexout_append(&out, '\'');
+static void asciidump(dump_out *out, const char *buf, size_t len) {
+ const gpr_uint8 *const beg = (const gpr_uint8 *)buf;
+ const gpr_uint8 *const end = beg + len;
+ const gpr_uint8 *cur;
+ int out_was_empty = (out->length == 0);
+ if (!out_was_empty) {
+ dump_out_append(out, ' ');
+ dump_out_append(out, '\'');
}
+ for (cur = beg; cur != end; ++cur) {
+ dump_out_append(out, isprint(*cur) ? *(char *)cur : '.');
+ }
+ if (!out_was_empty) {
+ dump_out_append(out, '\'');
+ }
+}
- hexout_append(&out, 0);
-
+char *gpr_dump(const char *buf, size_t len, gpr_uint32 flags) {
+ dump_out out = dump_out_create();
+ if (flags & GPR_DUMP_HEX) {
+ hexdump(&out, buf, len);
+ }
+ if (flags & GPR_DUMP_ASCII) {
+ asciidump(&out, buf, len);
+ }
+ dump_out_append(&out, 0);
return out.data;
}
+char *gpr_dump_slice(gpr_slice s, gpr_uint32 flags) {
+ return gpr_dump((const char *)GPR_SLICE_START_PTR(s), GPR_SLICE_LENGTH(s),
+ flags);
+}
+
+
int gpr_parse_bytes_to_uint32(const char *buf, size_t len, gpr_uint32 *result) {
gpr_uint32 out = 0;
gpr_uint32 new;
diff --git a/src/core/support/string.h b/src/core/support/string.h
index 31e9fcb5e9..d950d908d6 100644
--- a/src/core/support/string.h
+++ b/src/core/support/string.h
@@ -37,6 +37,7 @@
#include <stddef.h>
#include <grpc/support/port_platform.h>
+#include <grpc/support/slice.h>
#ifdef __cplusplus
extern "C" {
@@ -44,12 +45,16 @@ extern "C" {
/* String utility functions */
-/* flag to include plaintext after a hexdump */
-#define GPR_HEXDUMP_PLAINTEXT 0x00000001
+/* Flags for gpr_dump function. */
+#define GPR_DUMP_HEX 0x00000001
+#define GPR_DUMP_ASCII 0x00000002
-/* Converts array buf, of length len, into a hexadecimal dump. Result should
- be freed with gpr_free() */
-char *gpr_hexdump(const char *buf, size_t len, gpr_uint32 flags);
+/* Converts array buf, of length len, into a C string according to the flags.
+ Result should be freed with gpr_free() */
+char *gpr_dump(const char *buf, size_t len, gpr_uint32 flags);
+
+/* Calls gpr_dump on a slice. */
+char *gpr_dump_slice(gpr_slice slice, gpr_uint32 flags);
/* Parses an array of bytes into an integer (base 10). Returns 1 on success,
0 on failure. */
diff --git a/src/core/support/sync_win32.c b/src/core/support/sync_win32.c
index 72f39f8d46..29b77fc4c2 100644
--- a/src/core/support/sync_win32.c
+++ b/src/core/support/sync_win32.c
@@ -86,7 +86,7 @@ int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline) {
if (gpr_time_cmp(abs_deadline, gpr_inf_future) == 0) {
SleepConditionVariableCS(cv, &mu->cs, INFINITE);
} else {
- gpr_timespec now = gpr_now();
+ gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
gpr_int64 now_ms = now.tv_sec * 1000 + now.tv_nsec / 1000000;
gpr_int64 deadline_ms =
abs_deadline.tv_sec * 1000 + abs_deadline.tv_nsec / 1000000;
diff --git a/src/core/support/time_posix.c b/src/core/support/time_posix.c
index afb58ef231..f9b7958783 100644
--- a/src/core/support/time_posix.c
+++ b/src/core/support/time_posix.c
@@ -55,22 +55,52 @@ static gpr_timespec gpr_from_timespec(struct timespec ts) {
return rv;
}
-gpr_timespec gpr_now(void) {
+/** maps gpr_clock_type --> clockid_t for clock_gettime */
+static clockid_t clockid_for_gpr_clock[] = {CLOCK_MONOTONIC, CLOCK_REALTIME};
+
+void gpr_time_init(void) {}
+
+gpr_timespec gpr_now(gpr_clock_type clock) {
struct timespec now;
- clock_gettime(CLOCK_REALTIME, &now);
+ clock_gettime(clockid_for_gpr_clock[clock], &now);
return gpr_from_timespec(now);
}
#else
/* For some reason Apple's OSes haven't implemented clock_gettime. */
#include <sys/time.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+
+static double g_time_scale;
+static uint64_t g_time_start;
+
+void gpr_time_init(void) {
+ mach_timebase_info_data_t tb = {0, 1};
+ mach_timebase_info(&tb);
+ g_time_scale = tb.numer;
+ g_time_scale /= tb.denom;
+ g_time_start = mach_absolute_time();
+}
-gpr_timespec gpr_now(void) {
+gpr_timespec gpr_now(gpr_clock_type clock) {
gpr_timespec now;
struct timeval now_tv;
- gettimeofday(&now_tv, NULL);
- now.tv_sec = now_tv.tv_sec;
- now.tv_nsec = now_tv.tv_usec * 1000;
+ double now_dbl;
+
+ switch (clock) {
+ case GPR_CLOCK_REALTIME:
+ gettimeofday(&now_tv, NULL);
+ now.tv_sec = now_tv.tv_sec;
+ now.tv_nsec = now_tv.tv_usec * 1000;
+ break;
+ case GPR_CLOCK_MONOTONIC:
+ now_dbl = (mach_absolute_time() - g_time_start) * g_time_scale;
+ now.tv_sec = now_dbl * 1e-9;
+ now.tv_nsec = now_dbl - now.tv_sec * 1e9;
+ break;
+ }
+
return now;
}
#endif
@@ -83,7 +113,7 @@ void gpr_sleep_until(gpr_timespec until) {
for (;;) {
/* We could simplify by using clock_nanosleep instead, but it might be
* slightly less portable. */
- now = gpr_now();
+ now = gpr_now(GPR_CLOCK_REALTIME);
if (gpr_time_cmp(until, now) <= 0) {
return;
}
diff --git a/src/core/support/time_win32.c b/src/core/support/time_win32.c
index 9db267c01b..fa77c74eeb 100644
--- a/src/core/support/time_win32.c
+++ b/src/core/support/time_win32.c
@@ -40,12 +40,34 @@
#include <grpc/support/time.h>
#include <sys/timeb.h>
-gpr_timespec gpr_now(void) {
+static LARGE_INTEGER g_start_time;
+static double g_time_scale;
+
+void gpr_time_init(void) {
+ LARGE_INTEGER frequency;
+ QueryPerformanceFrequency(&frequency);
+ QueryPerformanceCounter(&g_start_time);
+ g_time_scale = 1.0 / frequency.QuadPart;
+}
+
+gpr_timespec gpr_now(gpr_clock_type clock) {
gpr_timespec now_tv;
struct _timeb now_tb;
- _ftime_s(&now_tb);
- now_tv.tv_sec = now_tb.time;
- now_tv.tv_nsec = now_tb.millitm * 1000000;
+ LARGE_INTEGER timestamp;
+ double now_dbl;
+ switch (clock) {
+ case GPR_CLOCK_REALTIME:
+ _ftime_s(&now_tb);
+ now_tv.tv_sec = now_tb.time;
+ now_tv.tv_nsec = now_tb.millitm * 1000000;
+ break;
+ case GPR_CLOCK_MONOTONIC:
+ QueryPerformanceCounter(&timestamp);
+ now_dbl = (timestamp.QuadPart - g_start_time.QuadPart) * g_time_scale;
+ now_tv.tv_sec = (time_t)now_dbl;
+ now_tv.tv_nsec = (int)((now_dbl - (double)now_tv.tv_sec) * 1e9);
+ break;
+ }
return now_tv;
}
@@ -57,13 +79,14 @@ void gpr_sleep_until(gpr_timespec until) {
for (;;) {
/* We could simplify by using clock_nanosleep instead, but it might be
* slightly less portable. */
- now = gpr_now();
+ now = gpr_now(GPR_CLOCK_REALTIME);
if (gpr_time_cmp(until, now) <= 0) {
return;
}
delta = gpr_time_sub(until, now);
- sleep_millis = (DWORD)delta.tv_sec * GPR_MS_PER_SEC + delta.tv_nsec / GPR_NS_PER_MS;
+ sleep_millis =
+ (DWORD)delta.tv_sec * GPR_MS_PER_SEC + delta.tv_nsec / GPR_NS_PER_MS;
Sleep(sleep_millis);
}
}
diff --git a/src/core/surface/byte_buffer_queue.c b/src/core/surface/byte_buffer_queue.c
index 7c31bfe5da..e47dc4f4ce 100644
--- a/src/core/surface/byte_buffer_queue.c
+++ b/src/core/surface/byte_buffer_queue.c
@@ -62,6 +62,7 @@ int grpc_bbq_empty(grpc_byte_buffer_queue *q) {
}
void grpc_bbq_push(grpc_byte_buffer_queue *q, grpc_byte_buffer *buffer) {
+ q->bytes += grpc_byte_buffer_length(buffer);
bba_push(&q->filling, buffer);
}
@@ -72,8 +73,11 @@ void grpc_bbq_flush(grpc_byte_buffer_queue *q) {
}
}
+size_t grpc_bbq_bytes(grpc_byte_buffer_queue *q) { return q->bytes; }
+
grpc_byte_buffer *grpc_bbq_pop(grpc_byte_buffer_queue *q) {
grpc_bbq_array temp_array;
+ grpc_byte_buffer *out;
if (q->drain_pos == q->draining.count) {
if (q->filling.count == 0) {
@@ -87,5 +91,7 @@ grpc_byte_buffer *grpc_bbq_pop(grpc_byte_buffer_queue *q) {
q->draining = temp_array;
}
- return q->draining.data[q->drain_pos++];
+ out = q->draining.data[q->drain_pos++];
+ q->bytes -= grpc_byte_buffer_length(out);
+ return out;
}
diff --git a/src/core/surface/byte_buffer_queue.h b/src/core/surface/byte_buffer_queue.h
index 32c57f8756..f01958984f 100644
--- a/src/core/surface/byte_buffer_queue.h
+++ b/src/core/surface/byte_buffer_queue.h
@@ -49,6 +49,7 @@ typedef struct {
size_t drain_pos;
grpc_bbq_array filling;
grpc_bbq_array draining;
+ size_t bytes;
} grpc_byte_buffer_queue;
void grpc_bbq_destroy(grpc_byte_buffer_queue *q);
@@ -56,5 +57,6 @@ grpc_byte_buffer *grpc_bbq_pop(grpc_byte_buffer_queue *q);
void grpc_bbq_flush(grpc_byte_buffer_queue *q);
int grpc_bbq_empty(grpc_byte_buffer_queue *q);
void grpc_bbq_push(grpc_byte_buffer_queue *q, grpc_byte_buffer *bb);
+size_t grpc_bbq_bytes(grpc_byte_buffer_queue *q);
#endif /* GRPC_INTERNAL_CORE_SURFACE_BYTE_BUFFER_QUEUE_H */
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index ae1b215767..71f4235571 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -49,6 +49,17 @@
#include <stdlib.h>
#include <string.h>
+/** The maximum number of completions possible.
+ Based upon the maximum number of individually queueable ops in the batch
+ api:
+ - initial metadata send
+ - message send
+ - status/close send (depending on client/server)
+ - initial metadata recv
+ - message recv
+ - status/close recv (depending on client/server) */
+#define MAX_CONCURRENT_COMPLETIONS 6
+
typedef enum { REQ_INITIAL = 0, REQ_READY, REQ_DONE } req_state;
typedef enum {
@@ -76,14 +87,14 @@ typedef struct {
typedef struct {
/* Overall status of the operation: starts OK, may degrade to
non-OK */
- int success;
- /* Completion function to call at the end of the operation */
- grpc_ioreq_completion_func on_complete;
- void *user_data;
+ gpr_uint8 success;
/* a bit mask of which request ops are needed (1u << opid) */
gpr_uint16 need_mask;
/* a bit mask of which request ops are now completed */
gpr_uint16 complete_mask;
+ /* Completion function to call at the end of the operation */
+ grpc_ioreq_completion_func on_complete;
+ void *user_data;
} reqinfo_master;
/* Status data for a request can come from several sources; this
@@ -135,6 +146,7 @@ struct grpc_call {
grpc_mdctx *metadata_context;
/* TODO(ctiller): share with cq if possible? */
gpr_mu mu;
+ gpr_mu completion_mu;
/* how far through the stream have we read? */
read_state read_state;
@@ -162,6 +174,8 @@ struct grpc_call {
gpr_uint8 error_status_set;
/** should the alarm be cancelled */
gpr_uint8 cancel_alarm;
+ /** bitmask of allocated completion events in completions */
+ gpr_uint8 allocated_completions;
/* flags with bits corresponding to write states allowing us to determine
what was sent */
@@ -250,6 +264,9 @@ struct grpc_call {
grpc_iomgr_closure on_done_recv;
grpc_iomgr_closure on_done_send;
grpc_iomgr_closure on_done_bind;
+
+ /** completion events - for completion queue use */
+ grpc_cq_completion completions[MAX_CONCURRENT_COMPLETIONS];
};
#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
@@ -286,6 +303,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size);
memset(call, 0, sizeof(grpc_call));
gpr_mu_init(&call->mu);
+ gpr_mu_init(&call->completion_mu);
call->channel = channel;
call->cq = cq;
if (cq) {
@@ -298,8 +316,6 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
if (call->is_client) {
call->request_set[GRPC_IOREQ_SEND_TRAILING_METADATA] = REQSET_DONE;
call->request_set[GRPC_IOREQ_SEND_STATUS] = REQSET_DONE;
- call->context[GRPC_CONTEXT_TRACING].value = grpc_census_context_create();
- call->context[GRPC_CONTEXT_TRACING].destroy = grpc_census_context_destroy;
}
GPR_ASSERT(add_initial_metadata_count < MAX_SEND_INITIAL_METADATA_COUNT);
for (i = 0; i < add_initial_metadata_count; i++) {
@@ -351,6 +367,29 @@ grpc_completion_queue *grpc_call_get_completion_queue(grpc_call *call) {
return call->cq;
}
+static grpc_cq_completion *allocate_completion(grpc_call *call) {
+ gpr_uint8 i;
+ gpr_mu_lock(&call->completion_mu);
+ for (i = 0; i < GPR_ARRAY_SIZE(call->completions); i++) {
+ if (call->allocated_completions & (1u << i)) {
+ continue;
+ }
+ call->allocated_completions |= 1u << i;
+ gpr_mu_unlock(&call->completion_mu);
+ return &call->completions[i];
+ }
+ gpr_log(GPR_ERROR, "should never reach here");
+ abort();
+}
+
+static void done_completion(void *call, grpc_cq_completion *completion) {
+ grpc_call *c = call;
+ gpr_mu_lock(&c->completion_mu);
+ c->allocated_completions &= ~(1u << (completion - c->completions));
+ gpr_mu_unlock(&c->completion_mu);
+ GRPC_CALL_INTERNAL_UNREF(c, "completion", 1);
+}
+
#ifdef GRPC_CALL_REF_COUNT_DEBUG
void grpc_call_internal_ref(grpc_call *c, const char *reason) {
gpr_log(GPR_DEBUG, "CALL: ref %p %d -> %d [%s]", c,
@@ -367,20 +406,21 @@ static void destroy_call(void *call, int ignored_success) {
grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c));
GRPC_CHANNEL_INTERNAL_UNREF(c->channel, "call");
gpr_mu_destroy(&c->mu);
+ gpr_mu_destroy(&c->completion_mu);
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (c->status[i].details) {
- grpc_mdstr_unref(c->status[i].details);
+ GRPC_MDSTR_UNREF(c->status[i].details);
}
}
for (i = 0; i < c->owned_metadata_count; i++) {
- grpc_mdelem_unref(c->owned_metadata[i]);
+ GRPC_MDELEM_UNREF(c->owned_metadata[i]);
}
gpr_free(c->owned_metadata);
for (i = 0; i < GPR_ARRAY_SIZE(c->buffered_metadata); i++) {
gpr_free(c->buffered_metadata[i].metadata);
}
for (i = 0; i < c->send_initial_metadata_count; i++) {
- grpc_mdelem_unref(c->send_initial_metadata[i].md);
+ GRPC_MDELEM_UNREF(c->send_initial_metadata[i].md);
}
for (i = 0; i < GRPC_CONTEXT_COUNT; i++) {
if (c->context[i].destroy) {
@@ -437,7 +477,7 @@ static void set_decode_compression_level(grpc_call *call,
static void set_status_details(grpc_call *call, status_source source,
grpc_mdstr *status) {
if (call->status[source].details != NULL) {
- grpc_mdstr_unref(call->status[source].details);
+ GRPC_MDSTR_UNREF(call->status[source].details);
}
call->status[source].details = status;
}
@@ -473,6 +513,8 @@ static void unlock(grpc_call *call) {
int completing_requests = 0;
int start_op = 0;
int i;
+ const gpr_uint32 MAX_RECV_PEEK_AHEAD = 65536;
+ size_t buffered_bytes;
int cancel_alarm = 0;
memset(&op, 0, sizeof(op));
@@ -488,6 +530,17 @@ static void unlock(grpc_call *call) {
op.recv_ops = &call->recv_ops;
op.recv_state = &call->recv_state;
op.on_done_recv = &call->on_done_recv;
+ if (grpc_bbq_empty(&call->incoming_queue) && call->reading_message) {
+ op.max_recv_bytes = call->incoming_message_length -
+ call->incoming_message.length + MAX_RECV_PEEK_AHEAD;
+ } else {
+ buffered_bytes = grpc_bbq_bytes(&call->incoming_queue);
+ if (buffered_bytes > MAX_RECV_PEEK_AHEAD) {
+ op.max_recv_bytes = 0;
+ } else {
+ op.max_recv_bytes = MAX_RECV_PEEK_AHEAD - buffered_bytes;
+ }
+ }
call->receiving = 1;
GRPC_CALL_INTERNAL_REF(call, "receiving");
start_op = 1;
@@ -616,7 +669,7 @@ static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op,
case GRPC_IOREQ_SEND_STATUS:
if (call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details !=
NULL) {
- grpc_mdstr_unref(
+ GRPC_MDSTR_UNREF(
call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details);
call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details =
NULL;
@@ -945,7 +998,7 @@ static int fill_send_ops(grpc_call *call, grpc_transport_stream_op *op) {
&mdb, &call->details_link,
grpc_mdelem_from_metadata_strings(
call->metadata_context,
- grpc_mdstr_ref(
+ GRPC_MDSTR_REF(
grpc_channel_get_message_string(call->channel)),
data.send_status.details));
call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details =
@@ -1053,7 +1106,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs,
reqs[i].data.send_status.code);
if (reqs[i].data.send_status.details) {
set_status_details(call, STATUS_FROM_SERVER_STATUS,
- grpc_mdstr_ref(reqs[i].data.send_status.details));
+ GRPC_MDSTR_REF(reqs[i].data.send_status.details));
}
}
have_ops |= 1u << op;
@@ -1190,7 +1243,8 @@ static void set_deadline_alarm(grpc_call *call, gpr_timespec deadline) {
}
GRPC_CALL_INTERNAL_REF(call, "alarm");
call->have_alarm = 1;
- grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now());
+ grpc_alarm_init(&call->alarm, deadline, call_alarm, call,
+ gpr_now(GPR_CLOCK_REALTIME));
}
/* we offset status by a small amount when storing it into transport metadata
@@ -1257,7 +1311,7 @@ static void recv_metadata(grpc_call *call, grpc_metadata_batch *md) {
if (key == grpc_channel_get_status_string(call->channel)) {
set_status_code(call, STATUS_FROM_WIRE, decode_status(md));
} else if (key == grpc_channel_get_message_string(call->channel)) {
- set_status_details(call, STATUS_FROM_WIRE, grpc_mdstr_ref(md->value));
+ set_status_details(call, STATUS_FROM_WIRE, GRPC_MDSTR_REF(md->value));
} else if (key ==
grpc_channel_get_compresssion_level_string(call->channel)) {
set_decode_compression_level(call, decode_compression(md));
@@ -1293,10 +1347,10 @@ static void recv_metadata(grpc_call *call, grpc_metadata_batch *md) {
grpc_mdctx_lock(mdctx);
for (l = md->list.head; l; l = l->next) {
- if (l->md) grpc_mdctx_locked_mdelem_unref(mdctx, l->md);
+ if (l->md) GRPC_MDCTX_LOCKED_MDELEM_UNREF(mdctx, l->md);
}
for (l = md->garbage.head; l; l = l->next) {
- grpc_mdctx_locked_mdelem_unref(mdctx, l->md);
+ GRPC_MDCTX_LOCKED_MDELEM_UNREF(mdctx, l->md);
}
grpc_mdctx_unlock(mdctx);
}
@@ -1318,11 +1372,13 @@ static void set_cancelled_value(grpc_status_code status, void *dest) {
}
static void finish_batch(grpc_call *call, int success, void *tag) {
- grpc_cq_end_op(call->cq, tag, call, success);
+ grpc_cq_end_op(call->cq, tag, success, done_completion, call,
+ allocate_completion(call));
}
static void finish_batch_with_close(grpc_call *call, int success, void *tag) {
- grpc_cq_end_op(call->cq, tag, call, 1);
+ grpc_cq_end_op(call->cq, tag, 1, done_completion, call,
+ allocate_completion(call));
}
static int are_write_flags_valid(gpr_uint32 flags) {
@@ -1345,8 +1401,10 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, tag);
if (nops == 0) {
- grpc_cq_begin_op(call->cq, call);
- grpc_cq_end_op(call->cq, tag, call, 1);
+ grpc_cq_begin_op(call->cq);
+ GRPC_CALL_INTERNAL_REF(call, "completion");
+ grpc_cq_end_op(call->cq, tag, 1, done_completion, call,
+ allocate_completion(call));
return GRPC_CALL_OK;
}
@@ -1468,7 +1526,8 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
}
}
- grpc_cq_begin_op(call->cq, call);
+ GRPC_CALL_INTERNAL_REF(call, "completion");
+ grpc_cq_begin_op(call->cq);
return grpc_call_start_ioreq_and_call_back(call, reqs, out, finish_func, tag);
}
diff --git a/src/core/surface/call.h b/src/core/surface/call.h
index fb3662b50d..3b6f9c942e 100644
--- a/src/core/surface/call.h
+++ b/src/core/surface/call.h
@@ -78,8 +78,8 @@ typedef union {
typedef struct {
grpc_ioreq_op op;
- grpc_ioreq_data data;
gpr_uint32 flags; /**< A copy of the write flags from grpc_op */
+ grpc_ioreq_data data;
} grpc_ioreq;
typedef void (*grpc_ioreq_completion_func)(grpc_call *call, int success,
diff --git a/src/core/surface/call_log_batch.c b/src/core/surface/call_log_batch.c
index 55663298c9..997046d954 100644
--- a/src/core/surface/call_log_batch.c
+++ b/src/core/surface/call_log_batch.c
@@ -46,8 +46,8 @@ static void add_metadata(gpr_strvec *b, const grpc_metadata *md, size_t count) {
gpr_strvec_add(b, gpr_strdup(md[i].key));
gpr_strvec_add(b, gpr_strdup(" value="));
- gpr_strvec_add(b, gpr_hexdump(md[i].value, md[i].value_length,
- GPR_HEXDUMP_PLAINTEXT));
+ gpr_strvec_add(b, gpr_dump(md[i].value, md[i].value_length,
+ GPR_DUMP_HEX | GPR_DUMP_ASCII));
}
}
diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c
index f8151c121c..b7826d4dfc 100644
--- a/src/core/surface/channel.c
+++ b/src/core/surface/channel.c
@@ -91,6 +91,7 @@ grpc_channel *grpc_channel_create_from_filters(
size_t size =
sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters);
grpc_channel *channel = gpr_malloc(size);
+ memset(channel, 0, sizeof(*channel));
GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
channel->is_client = is_client;
/* decremented by grpc_channel_destroy */
@@ -104,7 +105,7 @@ grpc_channel *grpc_channel_create_from_filters(
char buf[GPR_LTOA_MIN_BUFSIZE];
gpr_ltoa(i, buf);
channel->grpc_status_elem[i] = grpc_mdelem_from_metadata_strings(
- mdctx, grpc_mdstr_ref(channel->grpc_status_string),
+ mdctx, GRPC_MDSTR_REF(channel->grpc_status_string),
grpc_mdstr_from_string(mdctx, buf));
}
channel->path_string = grpc_mdstr_from_string(mdctx, ":path");
@@ -157,10 +158,10 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel,
return grpc_channel_create_call_internal(
channel, cq,
grpc_mdelem_from_metadata_strings(
- channel->metadata_context, grpc_mdstr_ref(channel->path_string),
+ channel->metadata_context, GRPC_MDSTR_REF(channel->path_string),
grpc_mdstr_from_string(channel->metadata_context, method)),
grpc_mdelem_from_metadata_strings(
- channel->metadata_context, grpc_mdstr_ref(channel->authority_string),
+ channel->metadata_context, GRPC_MDSTR_REF(channel->authority_string),
grpc_mdstr_from_string(channel->metadata_context, host)),
deadline);
}
@@ -169,10 +170,10 @@ void *grpc_channel_register_call(grpc_channel *channel, const char *method,
const char *host) {
registered_call *rc = gpr_malloc(sizeof(registered_call));
rc->path = grpc_mdelem_from_metadata_strings(
- channel->metadata_context, grpc_mdstr_ref(channel->path_string),
+ channel->metadata_context, GRPC_MDSTR_REF(channel->path_string),
grpc_mdstr_from_string(channel->metadata_context, method));
rc->authority = grpc_mdelem_from_metadata_strings(
- channel->metadata_context, grpc_mdstr_ref(channel->authority_string),
+ channel->metadata_context, GRPC_MDSTR_REF(channel->authority_string),
grpc_mdstr_from_string(channel->metadata_context, host));
gpr_mu_lock(&channel->registered_call_mu);
rc->next = channel->registered_calls;
@@ -186,8 +187,8 @@ grpc_call *grpc_channel_create_registered_call(
void *registered_call_handle, gpr_timespec deadline) {
registered_call *rc = registered_call_handle;
return grpc_channel_create_call_internal(
- channel, completion_queue, grpc_mdelem_ref(rc->path),
- grpc_mdelem_ref(rc->authority), deadline);
+ channel, completion_queue, GRPC_MDELEM_REF(rc->path),
+ GRPC_MDELEM_REF(rc->authority), deadline);
}
#ifdef GRPC_CHANNEL_REF_COUNT_DEBUG
@@ -205,18 +206,18 @@ static void destroy_channel(void *p, int ok) {
size_t i;
grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel));
for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) {
- grpc_mdelem_unref(channel->grpc_status_elem[i]);
+ GRPC_MDELEM_UNREF(channel->grpc_status_elem[i]);
}
- grpc_mdstr_unref(channel->grpc_status_string);
- grpc_mdstr_unref(channel->grpc_compression_level_string);
- grpc_mdstr_unref(channel->grpc_message_string);
- grpc_mdstr_unref(channel->path_string);
- grpc_mdstr_unref(channel->authority_string);
+ GRPC_MDSTR_UNREF(channel->grpc_status_string);
+ GRPC_MDSTR_UNREF(channel->grpc_compression_level_string);
+ GRPC_MDSTR_UNREF(channel->grpc_message_string);
+ GRPC_MDSTR_UNREF(channel->path_string);
+ GRPC_MDSTR_UNREF(channel->authority_string);
while (channel->registered_calls) {
registered_call *rc = channel->registered_calls;
channel->registered_calls = rc->next;
- grpc_mdelem_unref(rc->path);
- grpc_mdelem_unref(rc->authority);
+ GRPC_MDELEM_UNREF(rc->path);
+ GRPC_MDELEM_UNREF(rc->authority);
gpr_free(rc);
}
grpc_mdctx_unref(channel->metadata_context);
@@ -267,12 +268,12 @@ grpc_mdstr *grpc_channel_get_compresssion_level_string(grpc_channel *channel) {
grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) {
if (i >= 0 && i < NUM_CACHED_STATUS_ELEMS) {
- return grpc_mdelem_ref(channel->grpc_status_elem[i]);
+ return GRPC_MDELEM_REF(channel->grpc_status_elem[i]);
} else {
char tmp[GPR_LTOA_MIN_BUFSIZE];
gpr_ltoa(i, tmp);
return grpc_mdelem_from_metadata_strings(
- channel->metadata_context, grpc_mdstr_ref(channel->grpc_status_string),
+ channel->metadata_context, GRPC_MDSTR_REF(channel->grpc_status_string),
grpc_mdstr_from_string(channel->metadata_context, tmp));
}
}
diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c
index 030a8b4e6f..f3630b31dd 100644
--- a/src/core/surface/completion_queue.c
+++ b/src/core/surface/completion_queue.c
@@ -45,34 +45,20 @@
#include <grpc/support/atm.h>
#include <grpc/support/log.h>
-#define NUM_TAG_BUCKETS 31
-
-/* A single event: extends grpc_event to form a linked list with a destruction
- function (on_finish) that is hidden from outside this module */
-typedef struct event {
- grpc_event base;
- struct event *queue_next;
- struct event *queue_prev;
- struct event *bucket_next;
- struct event *bucket_prev;
-} event;
-
/* Completion queue structure */
struct grpc_completion_queue {
- /* When refs drops to zero, we are in shutdown mode, and will be destroyable
- once all queued events are drained */
- gpr_refcount refs;
- /* Once owning_refs drops to zero, we will destroy the cq */
+ /** completed events */
+ grpc_cq_completion completed_head;
+ grpc_cq_completion *completed_tail;
+ /** Number of pending events (+1 if we're not shutdown) */
+ gpr_refcount pending_events;
+ /** Once owning_refs drops to zero, we will destroy the cq */
gpr_refcount owning_refs;
- /* the set of low level i/o things that concern this cq */
+ /** the set of low level i/o things that concern this cq */
grpc_pollset pollset;
- /* 0 initially, 1 once we've begun shutting down */
+ /** 0 initially, 1 once we've begun shutting down */
int shutdown;
int shutdown_called;
- /* Head of a linked list of queued events (prev points to the last element) */
- event *queue;
- /* Fixed size chained hash table of events for pluck() */
- event *buckets[NUM_TAG_BUCKETS];
int is_server_cq;
};
@@ -80,19 +66,20 @@ grpc_completion_queue *grpc_completion_queue_create(void) {
grpc_completion_queue *cc = gpr_malloc(sizeof(grpc_completion_queue));
memset(cc, 0, sizeof(*cc));
/* Initial ref is dropped by grpc_completion_queue_shutdown */
- gpr_ref_init(&cc->refs, 1);
+ gpr_ref_init(&cc->pending_events, 1);
/* One for destroy(), one for pollset_shutdown */
gpr_ref_init(&cc->owning_refs, 2);
grpc_pollset_init(&cc->pollset);
+ cc->completed_tail = &cc->completed_head;
+ cc->completed_head.next = (gpr_uintptr)cc->completed_tail;
return cc;
}
#ifdef GRPC_CQ_REF_COUNT_DEBUG
void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
const char *file, int line) {
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p ref %d -> %d %s",
- cc, (int)cc->owning_refs.count, (int)cc->owning_refs.count + 1,
- reason);
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p ref %d -> %d %s", cc,
+ (int)cc->owning_refs.count, (int)cc->owning_refs.count + 1, reason);
#else
void grpc_cq_internal_ref(grpc_completion_queue *cc) {
#endif
@@ -107,186 +94,135 @@ static void on_pollset_destroy_done(void *arg) {
#ifdef GRPC_CQ_REF_COUNT_DEBUG
void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason,
const char *file, int line) {
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p unref %d -> %d %s",
- cc, (int)cc->owning_refs.count, (int)cc->owning_refs.count - 1,
- reason);
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p unref %d -> %d %s", cc,
+ (int)cc->owning_refs.count, (int)cc->owning_refs.count - 1, reason);
#else
void grpc_cq_internal_unref(grpc_completion_queue *cc) {
#endif
if (gpr_unref(&cc->owning_refs)) {
- GPR_ASSERT(cc->queue == NULL);
+ GPR_ASSERT(cc->completed_head.next == (gpr_uintptr)&cc->completed_head);
grpc_pollset_destroy(&cc->pollset);
gpr_free(cc);
}
}
-/* Create and append an event to the queue. Returns the event so that its data
- members can be filled in.
- Requires GRPC_POLLSET_MU(&cc->pollset) locked. */
-static event *add_locked(grpc_completion_queue *cc, grpc_completion_type type,
- void *tag, grpc_call *call) {
- event *ev = gpr_malloc(sizeof(event));
- gpr_uintptr bucket = ((gpr_uintptr)tag) % NUM_TAG_BUCKETS;
- ev->base.type = type;
- ev->base.tag = tag;
- if (cc->queue == NULL) {
- cc->queue = ev->queue_next = ev->queue_prev = ev;
- } else {
- ev->queue_next = cc->queue;
- ev->queue_prev = cc->queue->queue_prev;
- ev->queue_next->queue_prev = ev->queue_prev->queue_next = ev;
- }
- if (cc->buckets[bucket] == NULL) {
- cc->buckets[bucket] = ev->bucket_next = ev->bucket_prev = ev;
- } else {
- ev->bucket_next = cc->buckets[bucket];
- ev->bucket_prev = cc->buckets[bucket]->bucket_prev;
- ev->bucket_next->bucket_prev = ev->bucket_prev->bucket_next = ev;
- }
- grpc_pollset_kick(&cc->pollset);
- return ev;
-}
-
-void grpc_cq_begin_op(grpc_completion_queue *cc, grpc_call *call) {
- gpr_ref(&cc->refs);
- if (call) GRPC_CALL_INTERNAL_REF(call, "cq");
+void grpc_cq_begin_op(grpc_completion_queue *cc) {
+ gpr_ref(&cc->pending_events);
}
/* Signal the end of an operation - if this is the last waiting-to-be-queued
event, then enter shutdown mode */
-void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, grpc_call *call,
- int success) {
- event *ev;
- int shutdown = 0;
+/* Queue a GRPC_OP_COMPLETED operation */
+void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, int success,
+ void (*done)(void *done_arg, grpc_cq_completion *storage),
+ void *done_arg, grpc_cq_completion *storage) {
+ int shutdown;
+
+ storage->tag = tag;
+ storage->done = done;
+ storage->done_arg = done_arg;
+ storage->next =
+ ((gpr_uintptr)&cc->completed_head) | ((gpr_uintptr)(success != 0));
+
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
- ev = add_locked(cc, GRPC_OP_COMPLETE, tag, call);
- ev->base.success = success;
- if (gpr_unref(&cc->refs)) {
+ shutdown = gpr_unref(&cc->pending_events);
+ if (!shutdown) {
+ cc->completed_tail->next =
+ ((gpr_uintptr)storage) | (1u & (gpr_uintptr)cc->completed_tail->next);
+ cc->completed_tail = storage;
+ grpc_pollset_kick(&cc->pollset);
+ gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+ } else {
+ cc->completed_tail->next =
+ ((gpr_uintptr)storage) | (1u & (gpr_uintptr)cc->completed_tail->next);
+ cc->completed_tail = storage;
GPR_ASSERT(!cc->shutdown);
GPR_ASSERT(cc->shutdown_called);
cc->shutdown = 1;
- shutdown = 1;
- }
- gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
- if (call) GRPC_CALL_INTERNAL_UNREF(call, "cq", 0);
- if (shutdown) {
+ gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc);
}
}
-/* Create a GRPC_QUEUE_SHUTDOWN event without queuing it anywhere */
-static event *create_shutdown_event(void) {
- event *ev = gpr_malloc(sizeof(event));
- ev->base.type = GRPC_QUEUE_SHUTDOWN;
- ev->base.tag = NULL;
- return ev;
-}
-
grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
gpr_timespec deadline) {
- event *ev = NULL;
grpc_event ret;
GRPC_CQ_INTERNAL_REF(cc, "next");
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
for (;;) {
- if (cc->queue != NULL) {
- gpr_uintptr bucket;
- ev = cc->queue;
- bucket = ((gpr_uintptr)ev->base.tag) % NUM_TAG_BUCKETS;
- cc->queue = ev->queue_next;
- ev->queue_next->queue_prev = ev->queue_prev;
- ev->queue_prev->queue_next = ev->queue_next;
- ev->bucket_next->bucket_prev = ev->bucket_prev;
- ev->bucket_prev->bucket_next = ev->bucket_next;
- if (ev == cc->buckets[bucket]) {
- cc->buckets[bucket] = ev->bucket_next;
- if (ev == cc->buckets[bucket]) {
- cc->buckets[bucket] = NULL;
- }
- }
- if (cc->queue == ev) {
- cc->queue = NULL;
+ if (cc->completed_tail != &cc->completed_head) {
+ grpc_cq_completion *c = (grpc_cq_completion *)cc->completed_head.next;
+ cc->completed_head.next = c->next & ~(gpr_uintptr)1;
+ if (c == cc->completed_tail) {
+ cc->completed_tail = &cc->completed_head;
}
+ gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+ ret.type = GRPC_OP_COMPLETE;
+ ret.success = c->next & 1u;
+ ret.tag = c->tag;
+ c->done(c->done_arg, c);
break;
}
if (cc->shutdown) {
- ev = create_shutdown_event();
+ gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+ memset(&ret, 0, sizeof(ret));
+ ret.type = GRPC_QUEUE_SHUTDOWN;
break;
}
if (!grpc_pollset_work(&cc->pollset, deadline)) {
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
memset(&ret, 0, sizeof(ret));
ret.type = GRPC_QUEUE_TIMEOUT;
- GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
- GRPC_CQ_INTERNAL_UNREF(cc, "next");
- return ret;
+ break;
}
}
- gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
- ret = ev->base;
- gpr_free(ev);
GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
GRPC_CQ_INTERNAL_UNREF(cc, "next");
return ret;
}
-static event *pluck_event(grpc_completion_queue *cc, void *tag) {
- gpr_uintptr bucket = ((gpr_uintptr)tag) % NUM_TAG_BUCKETS;
- event *ev = cc->buckets[bucket];
- if (ev == NULL) return NULL;
- do {
- if (ev->base.tag == tag) {
- ev->queue_next->queue_prev = ev->queue_prev;
- ev->queue_prev->queue_next = ev->queue_next;
- ev->bucket_next->bucket_prev = ev->bucket_prev;
- ev->bucket_prev->bucket_next = ev->bucket_next;
- if (ev == cc->buckets[bucket]) {
- cc->buckets[bucket] = ev->bucket_next;
- if (ev == cc->buckets[bucket]) {
- cc->buckets[bucket] = NULL;
- }
- }
- if (cc->queue == ev) {
- cc->queue = ev->queue_next;
- if (cc->queue == ev) {
- cc->queue = NULL;
- }
- }
- return ev;
- }
- ev = ev->bucket_next;
- } while (ev != cc->buckets[bucket]);
- return NULL;
-}
-
grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
gpr_timespec deadline) {
- event *ev = NULL;
grpc_event ret;
+ grpc_cq_completion *c;
+ grpc_cq_completion *prev;
GRPC_CQ_INTERNAL_REF(cc, "pluck");
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
for (;;) {
- if ((ev = pluck_event(cc, tag))) {
- break;
+ prev = &cc->completed_head;
+ while ((c = (grpc_cq_completion *)(prev->next & ~(gpr_uintptr)1)) !=
+ &cc->completed_head) {
+ if (c->tag == tag) {
+ prev->next =
+ (prev->next & (gpr_uintptr)1) | (c->next & ~(gpr_uintptr)1);
+ if (c == cc->completed_tail) {
+ cc->completed_tail = prev;
+ }
+ gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+ ret.type = GRPC_OP_COMPLETE;
+ ret.success = c->next & 1u;
+ ret.tag = c->tag;
+ c->done(c->done_arg, c);
+ goto done;
+ }
+ prev = c;
}
if (cc->shutdown) {
- ev = create_shutdown_event();
+ gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+ memset(&ret, 0, sizeof(ret));
+ ret.type = GRPC_QUEUE_SHUTDOWN;
break;
}
if (!grpc_pollset_work(&cc->pollset, deadline)) {
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
memset(&ret, 0, sizeof(ret));
ret.type = GRPC_QUEUE_TIMEOUT;
- GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
- GRPC_CQ_INTERNAL_UNREF(cc, "pluck");
- return ret;
+ break;
}
}
- gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
- ret = ev->base;
- gpr_free(ev);
+done:
GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
GRPC_CQ_INTERNAL_UNREF(cc, "pluck");
return ret;
@@ -303,7 +239,7 @@ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
cc->shutdown_called = 1;
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
- if (gpr_unref(&cc->refs)) {
+ if (gpr_unref(&cc->pending_events)) {
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
GPR_ASSERT(!cc->shutdown);
cc->shutdown = 1;
@@ -324,8 +260,8 @@ grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc) {
void grpc_cq_hack_spin_pollset(grpc_completion_queue *cc) {
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
grpc_pollset_kick(&cc->pollset);
- grpc_pollset_work(&cc->pollset,
- gpr_time_add(gpr_now(), gpr_time_from_millis(100)));
+ grpc_pollset_work(&cc->pollset, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_millis(100)));
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
}
diff --git a/src/core/surface/completion_queue.h b/src/core/surface/completion_queue.h
index 1b9010f462..f944f48d8e 100644
--- a/src/core/surface/completion_queue.h
+++ b/src/core/surface/completion_queue.h
@@ -39,6 +39,17 @@
#include "src/core/iomgr/pollset.h"
#include <grpc/grpc.h>
+typedef struct grpc_cq_completion {
+ /** user supplied tag */
+ void *tag;
+ /** done callback - called when this queue element is no longer
+ needed by the completion queue */
+ void (*done)(void *done_arg, struct grpc_cq_completion *c);
+ void *done_arg;
+ /** next pointer; low bit is used to indicate success or not */
+ gpr_uintptr next;
+} grpc_cq_completion;
+
#ifdef GRPC_CQ_REF_COUNT_DEBUG
void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
const char *file, int line);
@@ -57,11 +68,12 @@ void grpc_cq_internal_unref(grpc_completion_queue *cc);
/* Flag that an operation is beginning: the completion channel will not finish
shutdown until a corrensponding grpc_cq_end_* call is made */
-void grpc_cq_begin_op(grpc_completion_queue *cc, grpc_call *call);
+void grpc_cq_begin_op(grpc_completion_queue *cc);
/* Queue a GRPC_OP_COMPLETED operation */
-void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, grpc_call *call,
- int success);
+void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, int success,
+ void (*done)(void *done_arg, grpc_cq_completion *storage),
+ void *done_arg, grpc_cq_completion *storage);
grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc);
diff --git a/src/core/surface/init.c b/src/core/surface/init.c
index a31f0960aa..f642810d12 100644
--- a/src/core/surface/init.c
+++ b/src/core/surface/init.c
@@ -38,6 +38,7 @@
#include <grpc/census.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
+#include <grpc/support/time.h>
#include "src/core/channel/channel_stack.h"
#include "src/core/client_config/resolver_registry.h"
#include "src/core/client_config/resolvers/dns_resolver.h"
@@ -91,6 +92,7 @@ void grpc_init(void) {
gpr_mu_lock(&g_init_mu);
if (++g_initializations == 1) {
+ gpr_time_init();
grpc_resolver_registry_init("dns:///");
grpc_register_resolver_type("dns", grpc_dns_resolver_factory_create());
#ifdef GPR_POSIX_SOCKET
diff --git a/src/core/surface/secure_channel_create.c b/src/core/surface/secure_channel_create.c
index 34ee3f8400..f3c7d8397b 100644
--- a/src/core/surface/secure_channel_create.c
+++ b/src/core/surface/secure_channel_create.c
@@ -75,6 +75,7 @@ static void connector_unref(grpc_connector *con) {
static void on_secure_transport_setup_done(void *arg,
grpc_security_status status,
+ grpc_endpoint *wrapped_endpoint,
grpc_endpoint *secure_endpoint) {
connector *c = arg;
grpc_iomgr_closure *notify;
diff --git a/src/core/surface/server.c b/src/core/surface/server.c
index f29d47c17c..4dc51bf031 100644
--- a/src/core/surface/server.c
+++ b/src/core/surface/server.c
@@ -51,7 +51,7 @@
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
-typedef enum { PENDING_START, ALL_CALLS, CALL_LIST_COUNT } call_list;
+typedef enum { PENDING_START, CALL_LIST_COUNT } call_list;
typedef struct listener {
void *arg;
@@ -72,12 +72,14 @@ typedef struct {
typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type;
-typedef struct {
+typedef struct requested_call {
requested_call_type type;
+ struct requested_call *next;
void *tag;
grpc_completion_queue *cq_bound_to_call;
grpc_completion_queue *cq_for_notification;
grpc_call **call;
+ grpc_cq_completion completion;
union {
struct {
grpc_call_details *details;
@@ -92,17 +94,11 @@ typedef struct {
} data;
} requested_call;
-typedef struct {
- requested_call *calls;
- size_t count;
- size_t capacity;
-} requested_call_array;
-
struct registered_method {
char *method;
char *host;
call_data *pending;
- requested_call_array requested;
+ requested_call *requests;
registered_method *next;
};
@@ -114,7 +110,6 @@ typedef struct channel_registered_method {
struct channel_data {
grpc_server *server;
- size_t num_calls;
grpc_connectivity_state connectivity_state;
grpc_channel *channel;
grpc_mdstr *path_key;
@@ -132,6 +127,7 @@ struct channel_data {
typedef struct shutdown_tag {
void *tag;
grpc_completion_queue *cq;
+ grpc_cq_completion completion;
} shutdown_tag;
struct grpc_server {
@@ -154,7 +150,7 @@ struct grpc_server {
gpr_mu mu_call; /* mutex for call-specific state */
registered_method *registered_methods;
- requested_call_array requested_calls;
+ requested_call *requests;
gpr_uint8 shutdown;
gpr_uint8 shutdown_published;
@@ -167,6 +163,9 @@ struct grpc_server {
listener *listeners;
int listeners_destroyed;
gpr_refcount internal_refcount;
+
+ /** when did we print the last shutdown progress message */
+ gpr_timespec last_shutdown_message_time;
};
typedef enum {
@@ -183,7 +182,11 @@ typedef enum {
struct call_data {
grpc_call *call;
+ /** protects state */
+ gpr_mu mu_state;
+ /** the current state of a call - see call_state */
call_state state;
+
grpc_mdstr *path;
grpc_mdstr *host;
gpr_timespec deadline;
@@ -204,9 +207,7 @@ struct call_data {
typedef struct {
grpc_channel **channels;
- grpc_channel **disconnects;
size_t num_channels;
- size_t num_disconnects;
} channel_broadcaster;
#define SERVER_FROM_CALL_ELEM(elem) \
@@ -225,26 +226,15 @@ static void maybe_finish_shutdown(grpc_server *server);
static void channel_broadcaster_init(grpc_server *s, channel_broadcaster *cb) {
channel_data *c;
size_t count = 0;
- size_t dc_count = 0;
for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
count++;
- if (c->num_calls == 0) {
- dc_count++;
- }
}
cb->num_channels = count;
- cb->num_disconnects = dc_count;
cb->channels = gpr_malloc(sizeof(*cb->channels) * cb->num_channels);
- cb->disconnects = gpr_malloc(sizeof(*cb->channels) * cb->num_disconnects);
count = 0;
- dc_count = 0;
for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
cb->channels[count++] = c->channel;
GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast");
- if (c->num_calls == 0) {
- cb->disconnects[dc_count++] = c->channel;
- GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast-disconnect");
- }
}
}
@@ -280,19 +270,15 @@ static void send_shutdown(grpc_channel *channel, int send_goaway,
}
static void channel_broadcaster_shutdown(channel_broadcaster *cb,
- int send_goaway, int send_disconnect) {
+ int send_goaway,
+ int force_disconnect) {
size_t i;
for (i = 0; i < cb->num_channels; i++) {
- send_shutdown(cb->channels[i], 1, 0);
+ send_shutdown(cb->channels[i], send_goaway, force_disconnect);
GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast");
}
- for (i = 0; i < cb->num_disconnects; i++) {
- send_shutdown(cb->disconnects[i], 0, 1);
- GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast-disconnect");
- }
gpr_free(cb->channels);
- gpr_free(cb->disconnects);
}
/* call list */
@@ -344,22 +330,6 @@ static int call_list_remove(call_data *call, call_list list) {
return 1;
}
-static void requested_call_array_destroy(requested_call_array *array) {
- gpr_free(array->calls);
-}
-
-static requested_call *requested_call_array_add(requested_call_array *array) {
- requested_call *rc;
- if (array->count == array->capacity) {
- array->capacity = GPR_MAX(array->capacity + 8, array->capacity * 2);
- array->calls =
- gpr_realloc(array->calls, sizeof(requested_call) * array->capacity);
- }
- rc = &array->calls[array->count++];
- memset(rc, 0, sizeof(*rc));
- return rc;
-}
-
static void server_ref(grpc_server *server) {
gpr_ref(&server->internal_refcount);
}
@@ -371,12 +341,10 @@ static void server_delete(grpc_server *server) {
gpr_mu_destroy(&server->mu_global);
gpr_mu_destroy(&server->mu_call);
gpr_free(server->channel_filters);
- requested_call_array_destroy(&server->requested_calls);
while ((rm = server->registered_methods) != NULL) {
server->registered_methods = rm->next;
gpr_free(rm->method);
gpr_free(rm->host);
- requested_call_array_destroy(&rm->requested);
gpr_free(rm);
}
for (i = 0; i < server->cq_count; i++) {
@@ -422,21 +390,26 @@ static void destroy_channel(channel_data *chand) {
grpc_iomgr_add_callback(&chand->finish_destroy_channel_closure);
}
-static void finish_start_new_rpc_and_unlock(grpc_server *server,
- grpc_call_element *elem,
- call_data **pending_root,
- requested_call_array *array) {
- requested_call rc;
+static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
+ call_data **pending_root,
+ requested_call **requests) {
+ requested_call *rc;
call_data *calld = elem->call_data;
- if (array->count == 0) {
+ gpr_mu_lock(&server->mu_call);
+ rc = *requests;
+ if (rc == NULL) {
+ gpr_mu_lock(&calld->mu_state);
calld->state = PENDING;
+ gpr_mu_unlock(&calld->mu_state);
call_list_join(pending_root, calld, PENDING_START);
gpr_mu_unlock(&server->mu_call);
} else {
- rc = array->calls[--array->count];
+ *requests = rc->next;
+ gpr_mu_lock(&calld->mu_state);
calld->state = ACTIVATED;
+ gpr_mu_unlock(&calld->mu_state);
gpr_mu_unlock(&server->mu_call);
- begin_call(server, calld, &rc);
+ begin_call(server, calld, rc);
}
}
@@ -448,20 +421,18 @@ static void start_new_rpc(grpc_call_element *elem) {
gpr_uint32 hash;
channel_registered_method *rm;
- gpr_mu_lock(&server->mu_call);
if (chand->registered_methods && calld->path && calld->host) {
/* TODO(ctiller): unify these two searches */
/* check for an exact match with host */
hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
- for (i = 0; i < chand->registered_method_max_probes; i++) {
+ for (i = 0; i <= chand->registered_method_max_probes; i++) {
rm = &chand->registered_methods[(hash + i) %
chand->registered_method_slots];
if (!rm) break;
if (rm->host != calld->host) continue;
if (rm->method != calld->path) continue;
- finish_start_new_rpc_and_unlock(server, elem,
- &rm->server_registered_method->pending,
- &rm->server_registered_method->requested);
+ finish_start_new_rpc(server, elem, &rm->server_registered_method->pending,
+ &rm->server_registered_method->requests);
return;
}
/* check for a wildcard method definition (no host set) */
@@ -472,14 +443,13 @@ static void start_new_rpc(grpc_call_element *elem) {
if (!rm) break;
if (rm->host != NULL) continue;
if (rm->method != calld->path) continue;
- finish_start_new_rpc_and_unlock(server, elem,
- &rm->server_registered_method->pending,
- &rm->server_registered_method->requested);
+ finish_start_new_rpc(server, elem, &rm->server_registered_method->pending,
+ &rm->server_registered_method->requests);
return;
}
}
- finish_start_new_rpc_and_unlock(server, elem, &server->lists[PENDING_START],
- &server->requested_calls);
+ finish_start_new_rpc(server, elem, &server->lists[PENDING_START],
+ &server->requests);
}
static void kill_zombie(void *elem, int success) {
@@ -495,35 +465,47 @@ static int num_listeners(grpc_server *server) {
return n;
}
+static void done_shutdown_event(void *server, grpc_cq_completion *completion) {
+ server_unref(server);
+}
+
+static int num_channels(grpc_server *server) {
+ channel_data *chand;
+ int n = 0;
+ for (chand = server->root_channel_data.next;
+ chand != &server->root_channel_data; chand = chand->next) {
+ n++;
+ }
+ return n;
+}
+
static void maybe_finish_shutdown(grpc_server *server) {
size_t i;
if (!server->shutdown || server->shutdown_published) {
return;
}
- gpr_mu_lock(&server->mu_call);
- if (server->lists[ALL_CALLS] != NULL) {
- gpr_log(GPR_DEBUG,
- "Waiting for all calls to finish before destroying server");
- gpr_mu_unlock(&server->mu_call);
- return;
- }
- gpr_mu_unlock(&server->mu_call);
-
- if (server->root_channel_data.next != &server->root_channel_data) {
- gpr_log(GPR_DEBUG,
- "Waiting for all channels to close before destroying server");
- return;
- }
- if (server->listeners_destroyed < num_listeners(server)) {
- gpr_log(GPR_DEBUG, "Waiting for all listeners to be destroyed (@ %d/%d)",
- server->listeners_destroyed, num_listeners(server));
+ if (server->root_channel_data.next != &server->root_channel_data ||
+ server->listeners_destroyed < num_listeners(server)) {
+ if (gpr_time_cmp(
+ gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), server->last_shutdown_message_time),
+ gpr_time_from_seconds(1)) >= 0) {
+ server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
+ gpr_log(GPR_DEBUG,
+ "Waiting for %d channels and %d/%d listeners to be destroyed"
+ " before shutting down server",
+ num_channels(server),
+ num_listeners(server) - server->listeners_destroyed,
+ num_listeners(server));
+ }
return;
}
server->shutdown_published = 1;
for (i = 0; i < server->num_shutdown_tags; i++) {
- grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag,
- NULL, 1);
+ server_ref(server);
+ grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag, 1,
+ done_shutdown_event, server,
+ &server->shutdown_tags[i].completion);
}
}
@@ -532,31 +514,19 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
if (md->key == chand->path_key) {
- calld->path = grpc_mdstr_ref(md->value);
+ calld->path = GRPC_MDSTR_REF(md->value);
return NULL;
} else if (md->key == chand->authority_key) {
- calld->host = grpc_mdstr_ref(md->value);
+ calld->host = GRPC_MDSTR_REF(md->value);
return NULL;
}
return md;
}
-static int decrement_call_count(channel_data *chand) {
- int disconnect = 0;
- chand->num_calls--;
- if (0 == chand->num_calls && chand->server->shutdown) {
- disconnect = 1;
- }
- maybe_finish_shutdown(chand->server);
- return disconnect;
-}
-
static void server_on_recv(void *ptr, int success) {
grpc_call_element *elem = ptr;
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
- int remove_res;
- int disconnect = 0;
if (success && !calld->got_initial_metadata) {
size_t i;
@@ -581,39 +551,33 @@ static void server_on_recv(void *ptr, int success) {
case GRPC_STREAM_SEND_CLOSED:
break;
case GRPC_STREAM_RECV_CLOSED:
- gpr_mu_lock(&chand->server->mu_call);
+ gpr_mu_lock(&calld->mu_state);
if (calld->state == NOT_STARTED) {
calld->state = ZOMBIED;
+ gpr_mu_unlock(&calld->mu_state);
grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_iomgr_add_callback(&calld->kill_zombie_closure);
+ } else {
+ gpr_mu_unlock(&calld->mu_state);
}
- gpr_mu_unlock(&chand->server->mu_call);
break;
case GRPC_STREAM_CLOSED:
- gpr_mu_lock(&chand->server->mu_call);
+ gpr_mu_lock(&calld->mu_state);
if (calld->state == NOT_STARTED) {
calld->state = ZOMBIED;
+ gpr_mu_unlock(&calld->mu_state);
grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_iomgr_add_callback(&calld->kill_zombie_closure);
} else if (calld->state == PENDING) {
- call_list_remove(calld, PENDING_START);
calld->state = ZOMBIED;
+ gpr_mu_unlock(&calld->mu_state);
+ gpr_mu_lock(&chand->server->mu_call);
+ call_list_remove(calld, PENDING_START);
+ gpr_mu_unlock(&chand->server->mu_call);
grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_iomgr_add_callback(&calld->kill_zombie_closure);
- }
- remove_res = call_list_remove(calld, ALL_CALLS);
- gpr_mu_unlock(&chand->server->mu_call);
- gpr_mu_lock(&chand->server->mu_global);
- if (remove_res) {
- disconnect = decrement_call_count(chand);
- if (disconnect) {
- GRPC_CHANNEL_INTERNAL_REF(chand->channel, "send-disconnect");
- }
- }
- gpr_mu_unlock(&chand->server->mu_global);
- if (disconnect) {
- send_shutdown(chand->channel, 0, 1);
- GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "send-disconnect");
+ } else {
+ gpr_mu_unlock(&calld->mu_state);
}
break;
}
@@ -676,17 +640,10 @@ static void init_call_elem(grpc_call_element *elem,
memset(calld, 0, sizeof(call_data));
calld->deadline = gpr_inf_future;
calld->call = grpc_call_from_top_element(elem);
+ gpr_mu_init(&calld->mu_state);
grpc_iomgr_closure_init(&calld->server_on_recv, server_on_recv, elem);
- gpr_mu_lock(&chand->server->mu_call);
- call_list_join(&chand->server->lists[ALL_CALLS], calld, ALL_CALLS);
- gpr_mu_unlock(&chand->server->mu_call);
-
- gpr_mu_lock(&chand->server->mu_global);
- chand->num_calls++;
- gpr_mu_unlock(&chand->server->mu_global);
-
server_ref(chand->server);
if (initial_op) server_mutate_op(elem, initial_op);
@@ -695,27 +652,22 @@ static void init_call_elem(grpc_call_element *elem,
static void destroy_call_elem(grpc_call_element *elem) {
channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
- int removed[CALL_LIST_COUNT];
- size_t i;
- gpr_mu_lock(&chand->server->mu_call);
- for (i = 0; i < CALL_LIST_COUNT; i++) {
- removed[i] = call_list_remove(elem->call_data, i);
- }
- gpr_mu_unlock(&chand->server->mu_call);
- if (removed[ALL_CALLS]) {
- gpr_mu_lock(&chand->server->mu_global);
- decrement_call_count(chand);
- gpr_mu_unlock(&chand->server->mu_global);
+ if (calld->state == PENDING) {
+ gpr_mu_lock(&chand->server->mu_call);
+ call_list_remove(elem->call_data, PENDING_START);
+ gpr_mu_unlock(&chand->server->mu_call);
}
if (calld->host) {
- grpc_mdstr_unref(calld->host);
+ GRPC_MDSTR_UNREF(calld->host);
}
if (calld->path) {
- grpc_mdstr_unref(calld->path);
+ GRPC_MDSTR_UNREF(calld->path);
}
+ gpr_mu_destroy(&calld->mu_state);
+
server_unref(chand->server);
}
@@ -727,7 +679,6 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
GPR_ASSERT(is_first);
GPR_ASSERT(!is_last);
chand->server = NULL;
- chand->num_calls = 0;
chand->channel = NULL;
chand->path_key = grpc_mdstr_from_string(metadata_context, ":path");
chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority");
@@ -744,10 +695,10 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
if (chand->registered_methods) {
for (i = 0; i < chand->registered_method_slots; i++) {
if (chand->registered_methods[i].method) {
- grpc_mdstr_unref(chand->registered_methods[i].method);
+ GRPC_MDSTR_UNREF(chand->registered_methods[i].method);
}
if (chand->registered_methods[i].host) {
- grpc_mdstr_unref(chand->registered_methods[i].host);
+ GRPC_MDSTR_UNREF(chand->registered_methods[i].host);
}
}
gpr_free(chand->registered_methods);
@@ -759,8 +710,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
chand->next = chand->prev = chand;
maybe_finish_shutdown(chand->server);
gpr_mu_unlock(&chand->server->mu_global);
- grpc_mdstr_unref(chand->path_key);
- grpc_mdstr_unref(chand->authority_key);
+ GRPC_MDSTR_UNREF(chand->path_key);
+ GRPC_MDSTR_UNREF(chand->authority_key);
server_unref(chand->server);
}
}
@@ -978,15 +929,14 @@ void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
void grpc_server_shutdown_and_notify(grpc_server *server,
grpc_completion_queue *cq, void *tag) {
listener *l;
- requested_call_array requested_calls;
- size_t i;
+ requested_call *requests = NULL;
registered_method *rm;
shutdown_tag *sdt;
channel_broadcaster broadcaster;
/* lock, and gather up some stuff to do */
gpr_mu_lock(&server->mu_global);
- grpc_cq_begin_op(cq, NULL);
+ grpc_cq_begin_op(cq);
server->shutdown_tags =
gpr_realloc(server->shutdown_tags,
sizeof(shutdown_tag) * (server->num_shutdown_tags + 1));
@@ -998,27 +948,21 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
return;
}
+ server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
+
channel_broadcaster_init(server, &broadcaster);
/* collect all unregistered then registered calls */
gpr_mu_lock(&server->mu_call);
- requested_calls = server->requested_calls;
- memset(&server->requested_calls, 0, sizeof(server->requested_calls));
+ requests = server->requests;
+ server->requests = NULL;
for (rm = server->registered_methods; rm; rm = rm->next) {
- if (requested_calls.count + rm->requested.count >
- requested_calls.capacity) {
- requested_calls.capacity =
- GPR_MAX(requested_calls.count + rm->requested.count,
- 2 * requested_calls.capacity);
- requested_calls.calls =
- gpr_realloc(requested_calls.calls, sizeof(*requested_calls.calls) *
- requested_calls.capacity);
+ while (rm->requests != NULL) {
+ requested_call *c = rm->requests;
+ rm->requests = c->next;
+ c->next = requests;
+ requests = c;
}
- memcpy(requested_calls.calls + requested_calls.count, rm->requested.calls,
- sizeof(*requested_calls.calls) * rm->requested.count);
- requested_calls.count += rm->requested.count;
- gpr_free(rm->requested.calls);
- memset(&rm->requested, 0, sizeof(rm->requested));
}
gpr_mu_unlock(&server->mu_call);
@@ -1027,10 +971,11 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
gpr_mu_unlock(&server->mu_global);
/* terminate all the requested calls */
- for (i = 0; i < requested_calls.count; i++) {
- fail_call(server, &requested_calls.calls[i]);
+ while (requests != NULL) {
+ requested_call *next = requests->next;
+ fail_call(server, requests);
+ requests = next;
}
- gpr_free(requested_calls.calls);
/* Shutdown listeners */
for (l = server->listeners; l; l = l->next) {
@@ -1049,47 +994,13 @@ void grpc_server_listener_destroy_done(void *s) {
}
void grpc_server_cancel_all_calls(grpc_server *server) {
- call_data *calld;
- grpc_call **calls;
- size_t call_count;
- size_t call_capacity;
- int is_first = 1;
- size_t i;
-
- gpr_mu_lock(&server->mu_call);
-
- GPR_ASSERT(server->shutdown);
-
- if (!server->lists[ALL_CALLS]) {
- gpr_mu_unlock(&server->mu_call);
- return;
- }
-
- call_capacity = 8;
- call_count = 0;
- calls = gpr_malloc(sizeof(grpc_call *) * call_capacity);
-
- for (calld = server->lists[ALL_CALLS];
- calld != server->lists[ALL_CALLS] || is_first;
- calld = calld->links[ALL_CALLS].next) {
- if (call_count == call_capacity) {
- call_capacity *= 2;
- calls = gpr_realloc(calls, sizeof(grpc_call *) * call_capacity);
- }
- calls[call_count++] = calld->call;
- GRPC_CALL_INTERNAL_REF(calld->call, "cancel_all");
- is_first = 0;
- }
-
- gpr_mu_unlock(&server->mu_call);
+ channel_broadcaster broadcaster;
- for (i = 0; i < call_count; i++) {
- grpc_call_cancel_with_status(calls[i], GRPC_STATUS_UNAVAILABLE,
- "Unavailable");
- GRPC_CALL_INTERNAL_UNREF(calls[i], "cancel_all", 1);
- }
+ gpr_mu_lock(&server->mu_global);
+ channel_broadcaster_init(server, &broadcaster);
+ gpr_mu_unlock(&server->mu_global);
- gpr_free(calls);
+ channel_broadcaster_shutdown(&broadcaster, 0, 1);
}
void grpc_server_destroy(grpc_server *server) {
@@ -1126,7 +1037,7 @@ void grpc_server_add_listener(grpc_server *server, void *arg,
static grpc_call_error queue_call_request(grpc_server *server,
requested_call *rc) {
call_data *calld = NULL;
- requested_call_array *requested_calls = NULL;
+ requested_call **requests = NULL;
gpr_mu_lock(&server->mu_call);
if (server->shutdown) {
gpr_mu_unlock(&server->mu_call);
@@ -1137,22 +1048,25 @@ static grpc_call_error queue_call_request(grpc_server *server,
case BATCH_CALL:
calld =
call_list_remove_head(&server->lists[PENDING_START], PENDING_START);
- requested_calls = &server->requested_calls;
+ requests = &server->requests;
break;
case REGISTERED_CALL:
calld = call_list_remove_head(
&rc->data.registered.registered_method->pending, PENDING_START);
- requested_calls = &rc->data.registered.registered_method->requested;
+ requests = &rc->data.registered.registered_method->requests;
break;
}
- if (calld) {
+ if (calld != NULL) {
+ gpr_mu_unlock(&server->mu_call);
+ gpr_mu_lock(&calld->mu_state);
GPR_ASSERT(calld->state == PENDING);
calld->state = ACTIVATED;
- gpr_mu_unlock(&server->mu_call);
+ gpr_mu_unlock(&calld->mu_state);
begin_call(server, calld, rc);
return GRPC_CALL_OK;
} else {
- *requested_call_array_add(requested_calls) = *rc;
+ rc->next = *requests;
+ *requests = rc;
gpr_mu_unlock(&server->mu_call);
return GRPC_CALL_OK;
}
@@ -1163,22 +1077,23 @@ grpc_call_error grpc_server_request_call(
grpc_metadata_array *initial_metadata,
grpc_completion_queue *cq_bound_to_call,
grpc_completion_queue *cq_for_notification, void *tag) {
- requested_call rc;
+ requested_call *rc = gpr_malloc(sizeof(*rc));
GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details,
initial_metadata, cq_bound_to_call,
cq_for_notification, tag);
if (!grpc_cq_is_server_cq(cq_for_notification)) {
+ gpr_free(rc);
return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
}
- grpc_cq_begin_op(cq_for_notification, NULL);
- rc.type = BATCH_CALL;
- rc.tag = tag;
- rc.cq_bound_to_call = cq_bound_to_call;
- rc.cq_for_notification = cq_for_notification;
- rc.call = call;
- rc.data.batch.details = details;
- rc.data.batch.initial_metadata = initial_metadata;
- return queue_call_request(server, &rc);
+ grpc_cq_begin_op(cq_for_notification);
+ rc->type = BATCH_CALL;
+ rc->tag = tag;
+ rc->cq_bound_to_call = cq_bound_to_call;
+ rc->cq_for_notification = cq_for_notification;
+ rc->call = call;
+ rc->data.batch.details = details;
+ rc->data.batch.initial_metadata = initial_metadata;
+ return queue_call_request(server, rc);
}
grpc_call_error grpc_server_request_registered_call(
@@ -1186,22 +1101,23 @@ grpc_call_error grpc_server_request_registered_call(
grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
grpc_completion_queue *cq_bound_to_call,
grpc_completion_queue *cq_for_notification, void *tag) {
- requested_call rc;
+ requested_call *rc = gpr_malloc(sizeof(*rc));
registered_method *registered_method = rm;
if (!grpc_cq_is_server_cq(cq_for_notification)) {
+ gpr_free(rc);
return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
}
- grpc_cq_begin_op(cq_for_notification, NULL);
- rc.type = REGISTERED_CALL;
- rc.tag = tag;
- rc.cq_bound_to_call = cq_bound_to_call;
- rc.cq_for_notification = cq_for_notification;
- rc.call = call;
- rc.data.registered.registered_method = registered_method;
- rc.data.registered.deadline = deadline;
- rc.data.registered.initial_metadata = initial_metadata;
- rc.data.registered.optional_payload = optional_payload;
- return queue_call_request(server, &rc);
+ grpc_cq_begin_op(cq_for_notification);
+ rc->type = REGISTERED_CALL;
+ rc->tag = tag;
+ rc->cq_bound_to_call = cq_bound_to_call;
+ rc->cq_for_notification = cq_for_notification;
+ rc->call = call;
+ rc->data.registered.registered_method = registered_method;
+ rc->data.registered.deadline = deadline;
+ rc->data.registered.initial_metadata = initial_metadata;
+ rc->data.registered.optional_payload = optional_payload;
+ return queue_call_request(server, rc);
}
static void publish_registered_or_batch(grpc_call *call, int success,
@@ -1268,8 +1184,11 @@ static void begin_call(grpc_server *server, call_data *calld,
}
GRPC_CALL_INTERNAL_REF(calld->call, "server");
- grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish,
- rc->tag);
+ grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish, rc);
+}
+
+static void done_request_event(void *req, grpc_cq_completion *c) {
+ gpr_free(req);
}
static void fail_call(grpc_server *server, requested_call *rc) {
@@ -1282,15 +1201,19 @@ static void fail_call(grpc_server *server, requested_call *rc) {
rc->data.registered.initial_metadata->count = 0;
break;
}
- grpc_cq_end_op(rc->cq_for_notification, rc->tag, NULL, 0);
+ grpc_cq_end_op(rc->cq_for_notification, rc->tag, 0, done_request_event, rc,
+ &rc->completion);
}
static void publish_registered_or_batch(grpc_call *call, int success,
- void *tag) {
+ void *prc) {
grpc_call_element *elem =
grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
+ requested_call *rc = prc;
call_data *calld = elem->call_data;
- grpc_cq_end_op(calld->cq_new, tag, call, success);
+ grpc_cq_end_op(calld->cq_new, rc->tag, success, done_request_event, rc,
+ &rc->completion);
+ GRPC_CALL_INTERNAL_UNREF(call, "server", 0);
}
const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
diff --git a/src/core/surface/version.c b/src/core/surface/version.c
new file mode 100644
index 0000000000..4f5d648371
--- /dev/null
+++ b/src/core/surface/version.c
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* This file is autogenerated from:
+ templates/src/core/surface/version.c.template */
+
+#include <grpc/grpc.h>
+
+const char *grpc_version_string(void) {
+ return "0.10.0.0";
+}
diff --git a/src/core/transport/chttp2/frame_data.c b/src/core/transport/chttp2/frame_data.c
index 0ad62a9999..7e3980159e 100644
--- a/src/core/transport/chttp2/frame_data.c
+++ b/src/core/transport/chttp2/frame_data.c
@@ -89,12 +89,9 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
fh_0:
case GRPC_CHTTP2_DATA_FH_0:
p->frame_type = *cur;
- if (++cur == end) {
- p->state = GRPC_CHTTP2_DATA_FH_1;
- return GRPC_CHTTP2_PARSE_OK;
- }
switch (p->frame_type) {
case 0:
+ /* noop */
break;
case 1:
gpr_log(GPR_ERROR, "Compressed GRPC frames not yet supported");
@@ -103,6 +100,10 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
gpr_log(GPR_ERROR, "Bad GRPC frame type 0x%02x", p->frame_type);
return GRPC_CHTTP2_STREAM_ERROR;
}
+ if (++cur == end) {
+ p->state = GRPC_CHTTP2_DATA_FH_1;
+ return GRPC_CHTTP2_PARSE_OK;
+ }
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_1:
p->frame_size = ((gpr_uint32)*cur) << 24;
diff --git a/src/core/transport/chttp2/frame_window_update.c b/src/core/transport/chttp2/frame_window_update.c
index b817df7745..d624298ad2 100644
--- a/src/core/transport/chttp2/frame_window_update.c
+++ b/src/core/transport/chttp2/frame_window_update.c
@@ -94,8 +94,8 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
}
GPR_ASSERT(is_last);
- if (transport_parsing->incoming_stream_id) {
- if (stream_parsing) {
+ if (transport_parsing->incoming_stream_id != 0) {
+ if (stream_parsing != NULL) {
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("update", transport_parsing,
stream_parsing, outgoing_window_update,
p->amount);
diff --git a/src/core/transport/chttp2/hpack_parser.c b/src/core/transport/chttp2/hpack_parser.c
index b8ab664db5..f8bff42ed6 100644
--- a/src/core/transport/chttp2/hpack_parser.c
+++ b/src/core/transport/chttp2/hpack_parser.c
@@ -622,7 +622,7 @@ static const gpr_uint8 inverse_base64[256] = {
static void on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
int add_to_table) {
if (add_to_table) {
- grpc_mdelem_ref(md);
+ GRPC_MDELEM_REF(md);
grpc_chttp2_hptbl_add(&p->table, md);
}
p->on_header(p->on_header_user_data, md);
@@ -711,7 +711,7 @@ static int parse_stream_dep0(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
static int finish_indexed_field(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
- grpc_mdelem_ref(md);
+ GRPC_MDELEM_REF(md);
on_hdr(p, md, 0);
return parse_begin(p, cur, end);
}
@@ -740,7 +740,7 @@ static int finish_lithdr_incidx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
- grpc_mdstr_ref(md->key),
+ GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)),
1);
return parse_begin(p, cur, end);
@@ -793,7 +793,7 @@ static int finish_lithdr_notidx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
- grpc_mdstr_ref(md->key),
+ GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)),
0);
return parse_begin(p, cur, end);
@@ -846,7 +846,7 @@ static int finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
- grpc_mdstr_ref(md->key),
+ GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)),
0);
return parse_begin(p, cur, end);
@@ -1329,17 +1329,14 @@ static int parse_value_string_with_literal_key(grpc_chttp2_hpack_parser *p,
/* PUBLIC INTERFACE */
static void on_header_not_set(void *user_data, grpc_mdelem *md) {
- char *keyhex =
- gpr_hexdump(grpc_mdstr_as_c_string(md->key),
- GPR_SLICE_LENGTH(md->key->slice), GPR_HEXDUMP_PLAINTEXT);
+ char *keyhex = gpr_dump_slice(md->key->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
char *valuehex =
- gpr_hexdump(grpc_mdstr_as_c_string(md->value),
- GPR_SLICE_LENGTH(md->value->slice), GPR_HEXDUMP_PLAINTEXT);
+ gpr_dump_slice(md->value->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_ERROR, "on_header callback not set; key=%s value=%s", keyhex,
valuehex);
gpr_free(keyhex);
gpr_free(valuehex);
- grpc_mdelem_unref(md);
+ GRPC_MDELEM_UNREF(md);
abort();
}
diff --git a/src/core/transport/chttp2/hpack_table.c b/src/core/transport/chttp2/hpack_table.c
index 372e71d68f..4fc154380e 100644
--- a/src/core/transport/chttp2/hpack_table.c
+++ b/src/core/transport/chttp2/hpack_table.c
@@ -122,10 +122,10 @@ void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl, grpc_mdctx *mdctx) {
void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl) {
size_t i;
for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
- grpc_mdelem_unref(tbl->static_ents[i]);
+ GRPC_MDELEM_UNREF(tbl->static_ents[i]);
}
for (i = 0; i < tbl->num_ents; i++) {
- grpc_mdelem_unref(
+ GRPC_MDELEM_UNREF(
tbl->ents[(tbl->first_ent + i) % GRPC_CHTTP2_MAX_TABLE_COUNT]);
}
}
@@ -155,7 +155,7 @@ static void evict1(grpc_chttp2_hptbl *tbl) {
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
tbl->first_ent = (tbl->first_ent + 1) % GRPC_CHTTP2_MAX_TABLE_COUNT;
tbl->num_ents--;
- grpc_mdelem_unref(first_ent);
+ GRPC_MDELEM_UNREF(first_ent);
}
void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
diff --git a/src/core/transport/chttp2/incoming_metadata.c b/src/core/transport/chttp2/incoming_metadata.c
index 68e0912b9c..77162a6864 100644
--- a/src/core/transport/chttp2/incoming_metadata.c
+++ b/src/core/transport/chttp2/incoming_metadata.c
@@ -49,7 +49,7 @@ void grpc_chttp2_incoming_metadata_buffer_destroy(
grpc_chttp2_incoming_metadata_buffer *buffer) {
size_t i;
for (i = 0; i < buffer->count; i++) {
- grpc_mdelem_unref(buffer->elems[i].md);
+ GRPC_MDELEM_UNREF(buffer->elems[i].md);
}
gpr_free(buffer->elems);
}
diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h
index 7f98a5bd71..e5e6f445b7 100644
--- a/src/core/transport/chttp2/internal.h
+++ b/src/core/transport/chttp2/internal.h
@@ -173,6 +173,8 @@ typedef struct {
/** have we seen a goaway */
gpr_uint8 seen_goaway;
+ /** have we sent a goaway */
+ gpr_uint8 sent_goaway;
/** is this transport a client? */
gpr_uint8 is_client;
@@ -351,7 +353,19 @@ typedef struct {
/** window available for us to send to peer */
gpr_int64 outgoing_window;
- /** window available for peer to send to us - updated after parse */
+ /** The number of bytes the upper layers have offered to receive.
+ As the upper layer offers more bytes, this value increases.
+ As bytes are read, this value decreases. */
+ gpr_uint32 max_recv_bytes;
+ /** The number of bytes the upper layer has offered to read but we have
+ not yet announced to HTTP2 flow control.
+ As the upper layers offer to read more bytes, this value increases.
+ As we advertise incoming flow control window, this value decreases. */
+ gpr_uint32 unannounced_incoming_window;
+ /** The number of bytes of HTTP2 flow control we have advertised.
+ As we advertise incoming flow control window, this value increases.
+ As bytes are read, this value decreases.
+ Updated after parse. */
gpr_uint32 incoming_window;
/** stream ops the transport user would like to send */
grpc_stream_op_buffer *outgoing_sopb;
@@ -389,6 +403,8 @@ typedef struct {
grpc_stream_op_buffer sopb;
/** how strongly should we indicate closure with the next write */
grpc_chttp2_send_closed send_closed;
+ /** how much window should we announce? */
+ gpr_uint32 announce_window;
} grpc_chttp2_stream_writing;
struct grpc_chttp2_stream_parsing {
@@ -499,7 +515,9 @@ void grpc_chttp2_list_add_writable_window_update_stream(
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
- grpc_chttp2_stream_global **stream_global);
+ grpc_chttp2_transport_writing *transport_writing,
+ grpc_chttp2_stream_global **stream_global,
+ grpc_chttp2_stream_writing **stream_writing);
void grpc_chttp2_list_remove_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
@@ -557,8 +575,10 @@ void grpc_chttp2_add_incoming_goaway(
void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
-void grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
- grpc_chttp2_stream *s);
+/* returns 1 if this is the last stream, 0 otherwise */
+int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
+ grpc_chttp2_stream *s) GRPC_MUST_USE_RESULT;
+int grpc_chttp2_has_streams(grpc_chttp2_transport *t);
void grpc_chttp2_for_all_streams(
grpc_chttp2_transport_global *transport_global, void *user_data,
void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
diff --git a/src/core/transport/chttp2/parsing.c b/src/core/transport/chttp2/parsing.c
index 4664a0895c..82362544d5 100644
--- a/src/core/transport/chttp2/parsing.c
+++ b/src/core/transport/chttp2/parsing.c
@@ -173,7 +173,14 @@ void grpc_chttp2_publish_reads(
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
"parsed", transport_parsing, stream_parsing, incoming_window_delta,
-(gpr_int64)stream_parsing->incoming_window_delta);
+ GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
+ "parsed", transport_parsing, stream_global, max_recv_bytes,
+ -(gpr_int64)stream_parsing->incoming_window_delta);
stream_global->incoming_window -= stream_parsing->incoming_window_delta;
+ GPR_ASSERT(stream_global->max_recv_bytes >=
+ stream_parsing->incoming_window_delta);
+ stream_global->max_recv_bytes -=
+ stream_parsing->incoming_window_delta;
stream_parsing->incoming_window_delta = 0;
grpc_chttp2_list_add_writable_window_update_stream(transport_global,
stream_global);
@@ -205,7 +212,8 @@ void grpc_chttp2_publish_reads(
}
if (stream_parsing->saw_rst_stream) {
stream_global->cancelled = 1;
- stream_global->cancelled_status = grpc_chttp2_http2_error_to_grpc_status(stream_parsing->rst_stream_reason);
+ stream_global->cancelled_status = grpc_chttp2_http2_error_to_grpc_status(
+ stream_parsing->rst_stream_reason);
if (stream_parsing->rst_stream_reason == GRPC_CHTTP2_NO_ERROR) {
stream_global->published_cancelled = 1;
}
@@ -463,7 +471,7 @@ static grpc_chttp2_parse_error skip_parser(
return GRPC_CHTTP2_PARSE_OK;
}
-static void skip_header(void *tp, grpc_mdelem *md) { grpc_mdelem_unref(md); }
+static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
static int init_skip_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing, int is_header) {
@@ -599,8 +607,8 @@ static void on_header(void *tp, grpc_mdelem *md) {
}
grpc_chttp2_incoming_metadata_buffer_set_deadline(
&stream_parsing->incoming_metadata,
- gpr_time_add(gpr_now(), *cached_timeout));
- grpc_mdelem_unref(md);
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), *cached_timeout));
+ GRPC_MDELEM_UNREF(md);
} else {
grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata,
md);
diff --git a/src/core/transport/chttp2/stream_encoder.c b/src/core/transport/chttp2/stream_encoder.c
index cf78ac50cc..d553d80085 100644
--- a/src/core/transport/chttp2/stream_encoder.c
+++ b/src/core/transport/chttp2/stream_encoder.c
@@ -247,19 +247,19 @@ static grpc_mdelem *add_elem(grpc_chttp2_hpack_compressor *c,
} else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key) {
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
} else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == NULL) {
- c->entries_keys[HASH_FRAGMENT_2(key_hash)] = grpc_mdstr_ref(elem->key);
+ c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
} else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == NULL) {
- c->entries_keys[HASH_FRAGMENT_3(key_hash)] = grpc_mdstr_ref(elem->key);
+ c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
} else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] <
c->indices_keys[HASH_FRAGMENT_3(key_hash)]) {
- grpc_mdstr_unref(c->entries_keys[HASH_FRAGMENT_2(key_hash)]);
- c->entries_keys[HASH_FRAGMENT_2(key_hash)] = grpc_mdstr_ref(elem->key);
+ GRPC_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_2(key_hash)]);
+ c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
} else {
- grpc_mdstr_unref(c->entries_keys[HASH_FRAGMENT_3(key_hash)]);
- c->entries_keys[HASH_FRAGMENT_3(key_hash)] = grpc_mdstr_ref(elem->key);
+ GRPC_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_3(key_hash)]);
+ c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
}
@@ -437,12 +437,13 @@ static void deadline_enc(grpc_chttp2_hpack_compressor *c, gpr_timespec deadline,
framer_state *st) {
char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
grpc_mdelem *mdelem;
- grpc_chttp2_encode_timeout(gpr_time_sub(deadline, gpr_now()), timeout_str);
+ grpc_chttp2_encode_timeout(
+ gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME)), timeout_str);
mdelem = grpc_mdelem_from_metadata_strings(
- c->mdctx, grpc_mdstr_ref(c->timeout_key_str),
+ c->mdctx, GRPC_MDSTR_REF(c->timeout_key_str),
grpc_mdstr_from_string(c->mdctx, timeout_str));
mdelem = hpack_enc(c, mdelem, st);
- if (mdelem) grpc_mdelem_unref(mdelem);
+ if (mdelem) GRPC_MDELEM_UNREF(mdelem);
}
gpr_slice grpc_chttp2_data_frame_create_empty_close(gpr_uint32 id) {
@@ -461,10 +462,10 @@ void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c,
void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
int i;
for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) {
- if (c->entries_keys[i]) grpc_mdstr_unref(c->entries_keys[i]);
- if (c->entries_elems[i]) grpc_mdelem_unref(c->entries_elems[i]);
+ if (c->entries_keys[i]) GRPC_MDSTR_UNREF(c->entries_keys[i]);
+ if (c->entries_elems[i]) GRPC_MDELEM_UNREF(c->entries_elems[i]);
}
- grpc_mdstr_unref(c->timeout_key_str);
+ GRPC_MDSTR_UNREF(c->timeout_key_str);
}
gpr_uint32 grpc_chttp2_preencode(grpc_stream_op *inops, size_t *inops_count,
@@ -620,10 +621,10 @@ void grpc_chttp2_encode(grpc_stream_op *ops, size_t ops_count, int eof,
op = &ops[unref_op];
if (op->type != GRPC_OP_METADATA) continue;
for (l = op->data.metadata.list.head; l; l = l->next) {
- if (l->md) grpc_mdctx_locked_mdelem_unref(mdctx, l->md);
+ if (l->md) GRPC_MDCTX_LOCKED_MDELEM_UNREF(mdctx, l->md);
}
for (l = op->data.metadata.garbage.head; l; l = l->next) {
- grpc_mdctx_locked_mdelem_unref(mdctx, l->md);
+ GRPC_MDCTX_LOCKED_MDELEM_UNREF(mdctx, l->md);
}
}
grpc_mdctx_unlock(mdctx);
diff --git a/src/core/transport/chttp2/stream_lists.c b/src/core/transport/chttp2/stream_lists.c
index 85691b32d2..590f6abfbc 100644
--- a/src/core/transport/chttp2/stream_lists.c
+++ b/src/core/transport/chttp2/stream_lists.c
@@ -139,6 +139,7 @@ static void stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
void grpc_chttp2_list_add_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
+ GPR_ASSERT(stream_global->id != 0);
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_WRITABLE);
}
@@ -204,6 +205,7 @@ int grpc_chttp2_list_pop_written_stream(
void grpc_chttp2_list_add_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
+ GPR_ASSERT(stream_global->id != 0);
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE);
@@ -211,11 +213,14 @@ void grpc_chttp2_list_add_writable_window_update_stream(
int grpc_chttp2_list_pop_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
- grpc_chttp2_stream_global **stream_global) {
+ grpc_chttp2_transport_writing *transport_writing,
+ grpc_chttp2_stream_global **stream_global,
+ grpc_chttp2_stream_writing **stream_writing) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE);
*stream_global = &stream->global;
+ *stream_writing = &stream->writing;
return r;
}
@@ -354,9 +359,14 @@ void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
stream_list_add_tail(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
}
-void grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
+int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s) {
- stream_list_remove(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
+ stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
+ return stream_list_empty(t, GRPC_CHTTP2_LIST_ALL_STREAMS);
+}
+
+int grpc_chttp2_has_streams(grpc_chttp2_transport *t) {
+ return !stream_list_empty(t, GRPC_CHTTP2_LIST_ALL_STREAMS);
}
void grpc_chttp2_for_all_streams(
diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c
index fdcc300099..d8ec117aa5 100644
--- a/src/core/transport/chttp2/writing.c
+++ b/src/core/transport/chttp2/writing.c
@@ -66,11 +66,9 @@ int grpc_chttp2_unlocking_check_writes(
/* for each grpc_chttp2_stream that's become writable, frame it's data
(according to
available window sizes) and add to the output buffer */
- while (transport_global->outgoing_window &&
- grpc_chttp2_list_pop_writable_stream(transport_global,
+ while (grpc_chttp2_list_pop_writable_stream(transport_global,
transport_writing, &stream_global,
- &stream_writing) &&
- stream_global->outgoing_window > 0) {
+ &stream_writing)) {
stream_writing->id = stream_global->id;
window_delta = grpc_chttp2_preencode(
stream_global->outgoing_sopb->ops, &stream_global->outgoing_sopb->nops,
@@ -97,12 +95,8 @@ int grpc_chttp2_unlocking_check_writes(
grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
}
- /* we should either exhaust window or have no ops left, but not both */
- if (stream_global->outgoing_sopb->nops == 0) {
- stream_global->outgoing_sopb = NULL;
- grpc_chttp2_schedule_closure(transport_global,
- stream_global->send_done_closure, 1);
- } else if (stream_global->outgoing_window > 0) {
+ if (stream_global->outgoing_window > 0 &&
+ stream_global->outgoing_sopb->nops != 0) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
}
}
@@ -110,20 +104,21 @@ int grpc_chttp2_unlocking_check_writes(
/* for each grpc_chttp2_stream that wants to update its window, add that
* window here */
while (grpc_chttp2_list_pop_writable_window_update_stream(transport_global,
- &stream_global)) {
- window_delta =
- transport_global->settings[GRPC_LOCAL_SETTINGS]
- [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] -
- stream_global->incoming_window;
- if (!stream_global->read_closed && window_delta > 0) {
- gpr_slice_buffer_add(
- &transport_writing->outbuf,
- grpc_chttp2_window_update_create(stream_global->id, window_delta));
+ transport_writing,
+ &stream_global,
+ &stream_writing)) {
+ stream_writing->id = stream_global->id;
+ if (!stream_global->read_closed && stream_global->unannounced_incoming_window > 0) {
+ stream_writing->announce_window = stream_global->unannounced_incoming_window;
+ GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("write", transport_global, stream_global,
+ incoming_window, stream_global->unannounced_incoming_window);
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("write", transport_global, stream_global,
- incoming_window, window_delta);
- stream_global->incoming_window += window_delta;
+ unannounced_incoming_window, -(gpr_int64)stream_global->unannounced_incoming_window);
+ stream_global->incoming_window += stream_global->unannounced_incoming_window;
+ stream_global->unannounced_incoming_window = 0;
grpc_chttp2_list_add_incoming_window_updated(transport_global,
stream_global);
+ grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
}
}
@@ -173,10 +168,19 @@ static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) {
while (
grpc_chttp2_list_pop_writing_stream(transport_writing, &stream_writing)) {
- grpc_chttp2_encode(stream_writing->sopb.ops, stream_writing->sopb.nops,
- stream_writing->send_closed != GRPC_DONT_SEND_CLOSED,
- stream_writing->id, &transport_writing->hpack_compressor,
- &transport_writing->outbuf);
+ if (stream_writing->sopb.nops > 0 || stream_writing->send_closed != GRPC_DONT_SEND_CLOSED) {
+ grpc_chttp2_encode(stream_writing->sopb.ops, stream_writing->sopb.nops,
+ stream_writing->send_closed != GRPC_DONT_SEND_CLOSED,
+ stream_writing->id, &transport_writing->hpack_compressor,
+ &transport_writing->outbuf);
+ }
+ if (stream_writing->announce_window > 0) {
+ gpr_slice_buffer_add(
+ &transport_writing->outbuf,
+ grpc_chttp2_window_update_create(
+ stream_writing->id, stream_writing->announce_window));
+ stream_writing->announce_window = 0;
+ }
stream_writing->sopb.nops = 0;
if (stream_writing->send_closed == GRPC_SEND_CLOSED_WITH_RST_STREAM) {
gpr_slice_buffer_add(&transport_writing->outbuf,
@@ -201,6 +205,12 @@ void grpc_chttp2_cleanup_writing(
while (grpc_chttp2_list_pop_written_stream(
transport_global, transport_writing, &stream_global, &stream_writing)) {
+ if (stream_global->outgoing_sopb != NULL &&
+ stream_global->outgoing_sopb->nops == 0) {
+ stream_global->outgoing_sopb = NULL;
+ grpc_chttp2_schedule_closure(transport_global,
+ stream_global->send_done_closure, 1);
+ }
if (stream_writing->send_closed != GRPC_DONT_SEND_CLOSED) {
stream_global->write_state = GRPC_WRITE_STATE_SENT_CLOSE;
if (!transport_global->is_client) {
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index 3483512ab8..c923d5e42f 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -139,7 +139,7 @@ static void destruct_transport(grpc_chttp2_transport *t) {
grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser);
grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser);
- grpc_mdstr_unref(t->parsing.str_grpc_timeout);
+ GRPC_MDSTR_UNREF(t->parsing.str_grpc_timeout);
for (i = 0; i < STREAM_LIST_COUNT; i++) {
GPR_ASSERT(t->lists[i].head == NULL);
@@ -358,7 +358,9 @@ static int init_stream(grpc_transport *gt, grpc_stream *gs,
s->global.outgoing_window =
t->global.settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
- s->parsing.incoming_window = s->global.incoming_window =
+ s->global.max_recv_bytes =
+ s->parsing.incoming_window =
+ s->global.incoming_window =
t->global.settings[GRPC_SENT_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
*t->accepting_stream = s;
@@ -382,7 +384,9 @@ static void destroy_stream(grpc_transport *gt, grpc_stream *gs) {
GPR_ASSERT(s->global.published_state == GRPC_STREAM_CLOSED ||
s->global.id == 0);
GPR_ASSERT(!s->global.in_stream_map);
- grpc_chttp2_unregister_stream(t, s);
+ if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
+ close_transport_locked(t);
+ }
if (!t->parsing_active && s->global.id) {
GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map,
s->global.id) == NULL);
@@ -521,8 +525,7 @@ static void writing_action(void *gt, int iomgr_success_ignored) {
void grpc_chttp2_add_incoming_goaway(
grpc_chttp2_transport_global *transport_global, gpr_uint32 goaway_error,
gpr_slice goaway_text) {
- char *msg = gpr_hexdump((char *)GPR_SLICE_START_PTR(goaway_text),
- GPR_SLICE_LENGTH(goaway_text), GPR_HEXDUMP_PLAINTEXT);
+ char *msg = gpr_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg);
gpr_free(msg);
gpr_slice_unref(goaway_text);
@@ -561,6 +564,8 @@ static void maybe_start_some_streams(
stream_global->incoming_window =
transport_global->settings[GRPC_SENT_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+ stream_global->max_recv_bytes =
+ GPR_MAX(stream_global->incoming_window, stream_global->max_recv_bytes);
grpc_chttp2_stream_map_add(
&TRANSPORT_FROM_GLOBAL(transport_global)->new_stream_map,
stream_global->id, STREAM_FROM_GLOBAL(stream_global));
@@ -569,6 +574,9 @@ static void maybe_start_some_streams(
grpc_chttp2_list_add_incoming_window_updated(transport_global,
stream_global);
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+ grpc_chttp2_list_add_writable_window_update_stream(transport_global,
+ stream_global);
+
}
/* cancel out streams that will never be started */
while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID &&
@@ -619,12 +627,23 @@ static void perform_stream_op_locked(
stream_global->publish_sopb = op->recv_ops;
stream_global->publish_sopb->nops = 0;
stream_global->publish_state = op->recv_state;
+ if (stream_global->max_recv_bytes < op->max_recv_bytes) {
+ GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("op", transport_global, stream_global,
+ max_recv_bytes, op->max_recv_bytes - stream_global->max_recv_bytes);
+ GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
+ "op", transport_global, stream_global, unannounced_incoming_window,
+ op->max_recv_bytes - stream_global->max_recv_bytes);
+ stream_global->unannounced_incoming_window += op->max_recv_bytes - stream_global->max_recv_bytes;
+ stream_global->max_recv_bytes = op->max_recv_bytes;
+ }
grpc_chttp2_incoming_metadata_live_op_buffer_end(
&stream_global->outstanding_metadata);
- grpc_chttp2_list_add_read_write_state_changed(transport_global,
- stream_global);
- grpc_chttp2_list_add_writable_window_update_stream(transport_global,
- stream_global);
+ if (stream_global->id != 0) {
+ grpc_chttp2_list_add_read_write_state_changed(transport_global,
+ stream_global);
+ grpc_chttp2_list_add_writable_window_update_stream(transport_global,
+ stream_global);
+ }
}
if (op->bind_pollset) {
@@ -681,10 +700,14 @@ static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op) {
}
if (op->send_goaway) {
+ t->global.sent_goaway = 1;
grpc_chttp2_goaway_append(
t->global.last_incoming_stream_id,
grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
gpr_slice_ref(*op->goaway_message), &t->global.qbuf);
+ if (!grpc_chttp2_has_streams(t)) {
+ close_transport_locked(t);
+ }
}
if (op->set_accept_stream != NULL) {
@@ -733,6 +756,9 @@ static void remove_stream(grpc_chttp2_transport *t, gpr_uint32 id) {
t->parsing.incoming_stream = NULL;
grpc_chttp2_parsing_become_skip_parser(&t->parsing);
}
+ if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
+ close_transport_locked(t);
+ }
new_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
grpc_chttp2_stream_map_size(&t->new_stream_map);
@@ -868,11 +894,19 @@ static void update_global_window(void *args, gpr_uint32 id, void *stream) {
grpc_chttp2_stream *s = stream;
grpc_chttp2_transport_global *transport_global = &t->global;
grpc_chttp2_stream_global *stream_global = &s->global;
+ int was_zero;
+ int is_zero;
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("settings", transport_global, stream_global,
outgoing_window,
t->parsing.initial_window_update);
+ was_zero = stream_global->outgoing_window <= 0;
stream_global->outgoing_window += t->parsing.initial_window_update;
+ is_zero = stream_global->outgoing_window <= 0;
+
+ if (was_zero && !is_zero) {
+ grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+ }
}
static void read_error_locked(grpc_chttp2_transport *t) {
@@ -1022,7 +1056,7 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *reason,
identifier = gpr_strdup(context_scope);
}
gpr_log(GPR_INFO,
- "FLOWCTL: %s %-10s %8s %-23s %8lld %c %8lld = %8lld %-10s [%s:%d]",
+ "FLOWCTL: %s %-10s %8s %-27s %8lld %c %8lld = %8lld %-10s [%s:%d]",
is_client ? "client" : "server", identifier, context_thread, var,
current_value, delta < 0 ? '-' : '+', delta < 0 ? -delta : delta,
current_value + delta, reason, file, line);
diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c
index c80d67823f..e95b7a21f9 100644
--- a/src/core/transport/metadata.c
+++ b/src/core/transport/metadata.c
@@ -48,6 +48,20 @@
#define INITIAL_STRTAB_CAPACITY 4
#define INITIAL_MDTAB_CAPACITY 4
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+#define DEBUG_ARGS , const char *file, int line
+#define FWD_DEBUG_ARGS , file, line
+#define INTERNAL_STRING_REF(s) internal_string_ref((s), __FILE__, __LINE__)
+#define INTERNAL_STRING_UNREF(s) internal_string_unref((s), __FILE__, __LINE__)
+#define REF_MD_LOCKED(s) ref_md_locked((s), __FILE__, __LINE__)
+#else
+#define DEBUG_ARGS
+#define FWD_DEBUG_ARGS
+#define INTERNAL_STRING_REF(s) internal_string_ref((s))
+#define INTERNAL_STRING_UNREF(s) internal_string_unref((s))
+#define REF_MD_LOCKED(s) ref_md_locked((s))
+#endif
+
typedef struct internal_string {
/* must be byte compatible with grpc_mdstr */
gpr_slice slice;
@@ -73,6 +87,7 @@ typedef struct internal_metadata {
gpr_atm refcnt;
/* private only data */
+ gpr_mu mu_user_data;
void *user_data;
void (*destroy_user_data)(void *user_data);
@@ -96,8 +111,8 @@ struct grpc_mdctx {
size_t mdtab_capacity;
};
-static void internal_string_ref(internal_string *s);
-static void internal_string_unref(internal_string *s);
+static void internal_string_ref(internal_string *s DEBUG_ARGS);
+static void internal_string_unref(internal_string *s DEBUG_ARGS);
static void discard_metadata(grpc_mdctx *ctx);
static void gc_mdtab(grpc_mdctx *ctx);
static void metadata_context_destroy_locked(grpc_mdctx *ctx);
@@ -132,7 +147,15 @@ static void unlock(grpc_mdctx *ctx) {
gpr_mu_unlock(&ctx->mu);
}
-static void ref_md_locked(internal_metadata *md) {
+static void ref_md_locked(internal_metadata *md DEBUG_ARGS) {
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+ "ELM REF:%p:%d->%d: '%s' = '%s'", md,
+ gpr_atm_no_barrier_load(&md->refcnt),
+ gpr_atm_no_barrier_load(&md->refcnt) + 1,
+ grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
+ grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+#endif
if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) {
md->context->mdtab_free--;
}
@@ -161,7 +184,7 @@ grpc_mdctx *grpc_mdctx_create(void) {
/* This seed is used to prevent remote connections from controlling hash table
* collisions. It needs to be somewhat unpredictable to a remote connection.
*/
- return grpc_mdctx_create_with_seed(gpr_now().tv_nsec);
+ return grpc_mdctx_create_with_seed(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
}
static void discard_metadata(grpc_mdctx *ctx) {
@@ -173,11 +196,12 @@ static void discard_metadata(grpc_mdctx *ctx) {
while (cur) {
GPR_ASSERT(gpr_atm_acq_load(&cur->refcnt) == 0);
next = cur->bucket_next;
- internal_string_unref(cur->key);
- internal_string_unref(cur->value);
+ INTERNAL_STRING_UNREF(cur->key);
+ INTERNAL_STRING_UNREF(cur->value);
if (cur->user_data) {
cur->destroy_user_data(cur->user_data);
}
+ gpr_mu_destroy(&cur->mu_user_data);
gpr_free(cur);
cur = next;
ctx->mdtab_free--;
@@ -248,9 +272,19 @@ static void internal_destroy_string(internal_string *is) {
gpr_free(is);
}
-static void internal_string_ref(internal_string *s) { ++s->refs; }
+static void internal_string_ref(internal_string *s DEBUG_ARGS) {
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR REF:%p:%d->%d: '%s'", s,
+ s->refs, s->refs + 1, grpc_mdstr_as_c_string((grpc_mdstr *)s));
+#endif
+ ++s->refs;
+}
-static void internal_string_unref(internal_string *s) {
+static void internal_string_unref(internal_string *s DEBUG_ARGS) {
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR UNREF:%p:%d->%d: '%s'", s,
+ s->refs, s->refs - 1, grpc_mdstr_as_c_string((grpc_mdstr *)s));
+#endif
GPR_ASSERT(s->refs > 0);
if (0 == --s->refs) {
internal_destroy_string(s);
@@ -262,7 +296,7 @@ static void slice_ref(void *p) {
(internal_string *)((char *)p - offsetof(internal_string, refcount));
grpc_mdctx *ctx = is->context;
lock(ctx);
- internal_string_ref(is);
+ INTERNAL_STRING_REF(is);
unlock(ctx);
}
@@ -271,7 +305,7 @@ static void slice_unref(void *p) {
(internal_string *)((char *)p - offsetof(internal_string, refcount));
grpc_mdctx *ctx = is->context;
lock(ctx);
- internal_string_unref(is);
+ INTERNAL_STRING_UNREF(is);
unlock(ctx);
}
@@ -297,7 +331,7 @@ grpc_mdstr *grpc_mdstr_from_buffer(grpc_mdctx *ctx, const gpr_uint8 *buf,
for (s = ctx->strtab[hash % ctx->strtab_capacity]; s; s = s->bucket_next) {
if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length &&
0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) {
- internal_string_ref(s);
+ INTERNAL_STRING_REF(s);
unlock(ctx);
return (grpc_mdstr *)s;
}
@@ -353,8 +387,8 @@ static void gc_mdtab(grpc_mdctx *ctx) {
for (md = ctx->mdtab[i]; md; md = next) {
next = md->bucket_next;
if (gpr_atm_acq_load(&md->refcnt) == 0) {
- internal_string_unref(md->key);
- internal_string_unref(md->value);
+ INTERNAL_STRING_UNREF(md->key);
+ INTERNAL_STRING_UNREF(md->value);
if (md->user_data) {
md->destroy_user_data(md->user_data);
}
@@ -418,9 +452,9 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx,
/* search for an existing pair */
for (md = ctx->mdtab[hash % ctx->mdtab_capacity]; md; md = md->bucket_next) {
if (md->key == key && md->value == value) {
- ref_md_locked(md);
- internal_string_unref(key);
- internal_string_unref(value);
+ REF_MD_LOCKED(md);
+ INTERNAL_STRING_UNREF(key);
+ INTERNAL_STRING_UNREF(value);
unlock(ctx);
return (grpc_mdelem *)md;
}
@@ -435,6 +469,13 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx,
md->user_data = NULL;
md->destroy_user_data = NULL;
md->bucket_next = ctx->mdtab[hash % ctx->mdtab_capacity];
+ gpr_mu_init(&md->mu_user_data);
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+ gpr_log(GPR_DEBUG, "ELM NEW:%p:%d: '%s' = '%s'", md,
+ gpr_atm_no_barrier_load(&md->refcnt),
+ grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
+ grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+#endif
ctx->mdtab[hash % ctx->mdtab_capacity] = md;
ctx->mdtab_count++;
@@ -469,8 +510,16 @@ grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_mdctx *ctx,
grpc_mdstr_from_buffer(ctx, value, value_length));
}
-grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd) {
+grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) {
internal_metadata *md = (internal_metadata *)gmd;
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+ "ELM REF:%p:%d->%d: '%s' = '%s'", md,
+ gpr_atm_no_barrier_load(&md->refcnt),
+ gpr_atm_no_barrier_load(&md->refcnt) + 1,
+ grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
+ grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+#endif
/* we can assume the ref count is >= 1 as the application is calling
this function - meaning that no adjustment to mdtab_free is necessary,
simplifying the logic here to be just an atomic increment */
@@ -480,10 +529,18 @@ grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd) {
return gmd;
}
-void grpc_mdelem_unref(grpc_mdelem *gmd) {
+void grpc_mdelem_unref(grpc_mdelem *gmd DEBUG_ARGS) {
internal_metadata *md = (internal_metadata *)gmd;
grpc_mdctx *ctx = md->context;
lock(ctx);
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+ "ELM UNREF:%p:%d->%d: '%s' = '%s'", md,
+ gpr_atm_no_barrier_load(&md->refcnt),
+ gpr_atm_no_barrier_load(&md->refcnt) - 1,
+ grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
+ grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+#endif
assert(gpr_atm_no_barrier_load(&md->refcnt) >= 1);
if (1 == gpr_atm_full_fetch_add(&md->refcnt, -1)) {
ctx->mdtab_free++;
@@ -495,20 +552,20 @@ const char *grpc_mdstr_as_c_string(grpc_mdstr *s) {
return (const char *)GPR_SLICE_START_PTR(s->slice);
}
-grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs) {
+grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) {
internal_string *s = (internal_string *)gs;
grpc_mdctx *ctx = s->context;
lock(ctx);
- internal_string_ref(s);
+ internal_string_ref(s FWD_DEBUG_ARGS);
unlock(ctx);
return gs;
}
-void grpc_mdstr_unref(grpc_mdstr *gs) {
+void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) {
internal_string *s = (internal_string *)gs;
grpc_mdctx *ctx = s->context;
lock(ctx);
- internal_string_unref(s);
+ internal_string_unref(s FWD_DEBUG_ARGS);
unlock(ctx);
}
@@ -527,18 +584,29 @@ size_t grpc_mdctx_get_mdtab_free_test_only(grpc_mdctx *ctx) {
void *grpc_mdelem_get_user_data(grpc_mdelem *md,
void (*if_destroy_func)(void *)) {
internal_metadata *im = (internal_metadata *)md;
- return im->destroy_user_data == if_destroy_func ? im->user_data : NULL;
+ void *result;
+ gpr_mu_lock(&im->mu_user_data);
+ result = im->destroy_user_data == if_destroy_func ? im->user_data : NULL;
+ gpr_mu_unlock(&im->mu_user_data);
+ return result;
}
void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
void *user_data) {
internal_metadata *im = (internal_metadata *)md;
GPR_ASSERT((user_data == NULL) == (destroy_func == NULL));
+ gpr_mu_lock(&im->mu_user_data);
if (im->destroy_user_data) {
- im->destroy_user_data(im->user_data);
+ /* user data can only be set once */
+ gpr_mu_unlock(&im->mu_user_data);
+ if (destroy_func != NULL) {
+ destroy_func(user_data);
+ }
+ return;
}
im->destroy_user_data = destroy_func;
im->user_data = user_data;
+ gpr_mu_unlock(&im->mu_user_data);
}
gpr_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *gs) {
@@ -558,10 +626,19 @@ gpr_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *gs) {
void grpc_mdctx_lock(grpc_mdctx *ctx) { lock(ctx); }
-void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx, grpc_mdelem *gmd) {
+void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx,
+ grpc_mdelem *gmd DEBUG_ARGS) {
internal_metadata *md = (internal_metadata *)gmd;
grpc_mdctx *elem_ctx = md->context;
GPR_ASSERT(ctx == elem_ctx);
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+ "ELM UNREF:%p:%d->%d: '%s' = '%s'", md,
+ gpr_atm_no_barrier_load(&md->refcnt),
+ gpr_atm_no_barrier_load(&md->refcnt) - 1,
+ grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
+ grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+#endif
assert(gpr_atm_no_barrier_load(&md->refcnt) >= 1);
if (1 == gpr_atm_full_fetch_add(&md->refcnt, -1)) {
ctx->mdtab_free++;
diff --git a/src/core/transport/metadata.h b/src/core/transport/metadata.h
index 76e3f3c1f8..99b15322c3 100644
--- a/src/core/transport/metadata.h
+++ b/src/core/transport/metadata.h
@@ -127,11 +127,25 @@ void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
void *user_data);
/* Reference counting */
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s), __FILE__, __LINE__)
+#define GRPC_MDSTR_UNREF(s) grpc_mdstr_unref((s), __FILE__, __LINE__)
+#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__)
+#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s), __FILE__, __LINE__)
+grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s, const char *file, int line);
+void grpc_mdstr_unref(grpc_mdstr *s, const char *file, int line);
+grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md, const char *file, int line);
+void grpc_mdelem_unref(grpc_mdelem *md, const char *file, int line);
+#else
+#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s))
+#define GRPC_MDSTR_UNREF(s) grpc_mdstr_unref((s))
+#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s))
+#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s))
grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s);
void grpc_mdstr_unref(grpc_mdstr *s);
-
grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md);
void grpc_mdelem_unref(grpc_mdelem *md);
+#endif
/* Recover a char* from a grpc_mdstr. The returned string is null terminated.
Does not promise that the returned string has no embedded nulls however. */
@@ -147,8 +161,18 @@ int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s);
/* Lock the metadata context: it's only safe to call _locked_ functions against
this context from the calling thread until grpc_mdctx_unlock is called */
void grpc_mdctx_lock(grpc_mdctx *ctx);
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+#define GRPC_MDCTX_LOCKED_MDELEM_UNREF(ctx, elem) \
+ grpc_mdctx_locked_mdelem_unref((ctx), (elem), __FILE__, __LINE__)
+/* Unref a metadata element */
+void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx, grpc_mdelem *elem,
+ const char *file, int line);
+#else
+#define GRPC_MDCTX_LOCKED_MDELEM_UNREF(ctx, elem) \
+ grpc_mdctx_locked_mdelem_unref((ctx), (elem))
/* Unref a metadata element */
void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx, grpc_mdelem *elem);
+#endif
/* Unlock the metadata context */
void grpc_mdctx_unlock(grpc_mdctx *ctx);
diff --git a/src/core/transport/stream_op.c b/src/core/transport/stream_op.c
index 81df5455f6..fdb50c6b71 100644
--- a/src/core/transport/stream_op.c
+++ b/src/core/transport/stream_op.c
@@ -211,10 +211,10 @@ void grpc_metadata_batch_init(grpc_metadata_batch *batch) {
void grpc_metadata_batch_destroy(grpc_metadata_batch *batch) {
grpc_linked_mdelem *l;
for (l = batch->list.head; l; l = l->next) {
- grpc_mdelem_unref(l->md);
+ GRPC_MDELEM_UNREF(l->md);
}
for (l = batch->garbage.head; l; l = l->next) {
- grpc_mdelem_unref(l->md);
+ GRPC_MDELEM_UNREF(l->md);
}
}
@@ -315,7 +315,7 @@ void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
assert_valid_list(&batch->list);
link_head(&batch->garbage, l);
} else if (filt != orig) {
- grpc_mdelem_unref(orig);
+ GRPC_MDELEM_UNREF(orig);
l->md = filt;
}
}
diff --git a/src/core/transport/stream_op.h b/src/core/transport/stream_op.h
index 842fc932b9..964d39d14f 100644
--- a/src/core/transport/stream_op.h
+++ b/src/core/transport/stream_op.h
@@ -41,7 +41,7 @@
#include "src/core/transport/metadata.h"
/* this many stream ops are inlined into a sopb before allocating */
-#define GRPC_SOPB_INLINE_ELEMENTS 16
+#define GRPC_SOPB_INLINE_ELEMENTS 4
/* Operations that can be performed on a stream.
Used by grpc_stream_op. */
diff --git a/src/core/transport/transport.c b/src/core/transport/transport.c
index fe565944ed..2689e3028a 100644
--- a/src/core/transport/transport.c
+++ b/src/core/transport/transport.c
@@ -85,6 +85,6 @@ void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
op->cancel_with_status = status;
}
if (message) {
- grpc_mdstr_unref(message);
+ GRPC_MDSTR_UNREF(message);
}
}
diff --git a/src/core/transport/transport.h b/src/core/transport/transport.h
index 579bcc943f..64503604ee 100644
--- a/src/core/transport/transport.h
+++ b/src/core/transport/transport.h
@@ -72,6 +72,10 @@ typedef struct grpc_transport_stream_op {
grpc_stream_op_buffer *recv_ops;
grpc_stream_state *recv_state;
+ /** The number of bytes this peer is currently prepared to receive.
+ These bytes will be eventually used to replenish per-stream flow control
+ windows. */
+ gpr_uint32 max_recv_bytes;
grpc_iomgr_closure *on_done_recv;
grpc_pollset *bind_pollset;
@@ -91,7 +95,9 @@ typedef struct grpc_transport_op {
grpc_connectivity_state *connectivity_state;
/** should the transport be disconnected */
int disconnect;
- /** should we send a goaway? */
+ /** should we send a goaway?
+ after a goaway is sent, once there are no more active calls on
+ the transport, the transport should disconnect */
int send_goaway;
/** what should the goaway contain? */
grpc_status_code goaway_status;
diff --git a/src/core/transport/transport_op_string.c b/src/core/transport/transport_op_string.c
index 1ffdb5be94..862eb40c4b 100644
--- a/src/core/transport/transport_op_string.c
+++ b/src/core/transport/transport_op_string.c
@@ -47,14 +47,12 @@
static void put_metadata(gpr_strvec *b, grpc_mdelem *md) {
gpr_strvec_add(b, gpr_strdup("key="));
- gpr_strvec_add(
- b, gpr_hexdump((char *)GPR_SLICE_START_PTR(md->key->slice),
- GPR_SLICE_LENGTH(md->key->slice), GPR_HEXDUMP_PLAINTEXT));
+ gpr_strvec_add(b,
+ gpr_dump_slice(md->key->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
gpr_strvec_add(b, gpr_strdup(" value="));
- gpr_strvec_add(b, gpr_hexdump((char *)GPR_SLICE_START_PTR(md->value->slice),
- GPR_SLICE_LENGTH(md->value->slice),
- GPR_HEXDUMP_PLAINTEXT));
+ gpr_strvec_add(
+ b, gpr_dump_slice(md->value->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
}
static void put_metadata_list(gpr_strvec *b, grpc_metadata_batch md) {
@@ -130,7 +128,8 @@ char *grpc_transport_stream_op_string(grpc_transport_stream_op *op) {
if (op->recv_ops) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = 0;
- gpr_strvec_add(&b, gpr_strdup("RECV"));
+ gpr_asprintf(&tmp, "RECV:max_recv_bytes=%d", op->max_recv_bytes);
+ gpr_strvec_add(&b, tmp);
}
if (op->bind_pollset) {
diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc
index 72593f877e..da31d000b3 100644
--- a/src/cpp/client/channel.cc
+++ b/src/cpp/client/channel.cc
@@ -39,6 +39,7 @@
#include <grpc/support/log.h>
#include <grpc/support/slice.h>
+#include "src/core/census/grpc_context.h"
#include "src/core/profiling/timers.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/client_context.h>
@@ -59,7 +60,7 @@ Channel::~Channel() { grpc_channel_destroy(c_channel_); }
Call Channel::CreateCall(const RpcMethod& method, ClientContext* context,
CompletionQueue* cq) {
auto c_call =
- method.channel_tag()
+ method.channel_tag() && context->authority().empty()
? grpc_channel_create_registered_call(c_channel_, cq->cq(),
method.channel_tag(),
context->raw_deadline())
@@ -68,6 +69,7 @@ Call Channel::CreateCall(const RpcMethod& method, ClientContext* context,
? target_.c_str()
: context->authority().c_str(),
context->raw_deadline());
+ grpc_census_call_set_context(c_call, context->get_census_context());
GRPC_TIMER_MARK(GRPC_PTAG_CPP_CALL_CREATED, c_call);
context->set_call(c_call, shared_from_this());
return Call(c_call, this, cq);
diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc
index 72cdd49d19..c68f6dd9f8 100644
--- a/src/cpp/client/client_context.cc
+++ b/src/cpp/client/client_context.cc
@@ -36,6 +36,7 @@
#include <grpc/grpc.h>
#include <grpc++/credentials.h>
#include <grpc++/time.h>
+#include "src/cpp/common/create_auth_context.h"
namespace grpc {
@@ -75,6 +76,13 @@ void ClientContext::set_call(grpc_call* call,
}
}
+std::shared_ptr<const AuthContext> ClientContext::auth_context() const {
+ if (auth_context_.get() == nullptr) {
+ auth_context_ = CreateAuthContext(call_);
+ }
+ return auth_context_;
+}
+
void ClientContext::TryCancel() {
if (call_) {
grpc_call_cancel(call_);
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index b5134b3140..4d200908fb 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -117,6 +117,13 @@ std::shared_ptr<Credentials> RefreshTokenCredentials(
grpc_refresh_token_credentials_create(json_refresh_token.c_str()));
}
+// Builds access token credentials.
+std::shared_ptr<Credentials> AccessTokenCredentials(
+ const grpc::string& access_token) {
+ return WrapCredentials(
+ grpc_access_token_credentials_create(access_token.c_str()));
+}
+
// Builds IAM credentials.
std::shared_ptr<Credentials> IAMCredentials(
const grpc::string& authorization_token,
diff --git a/src/cpp/common/auth_property_iterator.cc b/src/cpp/common/auth_property_iterator.cc
new file mode 100644
index 0000000000..e706c6c921
--- /dev/null
+++ b/src/cpp/common/auth_property_iterator.cc
@@ -0,0 +1,87 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc++/auth_property_iterator.h>
+
+#include <grpc/grpc_security.h>
+
+namespace grpc {
+
+AuthPropertyIterator::AuthPropertyIterator()
+ : property_(nullptr), ctx_(nullptr), index_(0), name_(nullptr) {}
+
+AuthPropertyIterator::AuthPropertyIterator(
+ const grpc_auth_property* property, const grpc_auth_property_iterator* iter)
+ : property_(property),
+ ctx_(iter->ctx),
+ index_(iter->index),
+ name_(iter->name) {}
+
+AuthPropertyIterator::~AuthPropertyIterator() {}
+
+AuthPropertyIterator& AuthPropertyIterator::operator++() {
+ grpc_auth_property_iterator iter = {ctx_, index_, name_};
+ property_ = grpc_auth_property_iterator_next(&iter);
+ ctx_ = iter.ctx;
+ index_ = iter.index;
+ name_ = iter.name;
+ return *this;
+}
+
+AuthPropertyIterator AuthPropertyIterator::operator++(int) {
+ AuthPropertyIterator tmp(*this);
+ operator++();
+ return tmp;
+}
+
+bool AuthPropertyIterator::operator==(
+ const AuthPropertyIterator& rhs) const {
+ if (property_ == nullptr || rhs.property_ == nullptr) {
+ return property_ == rhs.property_;
+ } else {
+ return index_ == rhs.index_;
+ }
+}
+
+bool AuthPropertyIterator::operator!=(
+ const AuthPropertyIterator& rhs) const {
+ return !operator==(rhs);
+}
+
+const AuthProperty AuthPropertyIterator::operator*() {
+ return std::make_pair<grpc::string, grpc::string>(
+ grpc::string(property_->name),
+ grpc::string(property_->value, property_->value_length));
+}
+
+} // namespace grpc
diff --git a/src/cpp/common/create_auth_context.h b/src/cpp/common/create_auth_context.h
new file mode 100644
index 0000000000..9082a90c6d
--- /dev/null
+++ b/src/cpp/common/create_auth_context.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+#include <memory>
+
+#include <grpc/grpc.h>
+#include <grpc++/auth_context.h>
+
+namespace grpc {
+
+std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call);
+
+} // namespace grpc
diff --git a/src/cpp/common/insecure_create_auth_context.cc b/src/cpp/common/insecure_create_auth_context.cc
new file mode 100644
index 0000000000..07fc0bd549
--- /dev/null
+++ b/src/cpp/common/insecure_create_auth_context.cc
@@ -0,0 +1,45 @@
+/*
+ *
+ * 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.
+ *
+ */
+#include <memory>
+
+#include <grpc/grpc.h>
+#include <grpc++/auth_context.h>
+
+namespace grpc {
+
+std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call) {
+ (void)call;
+ return std::shared_ptr<const AuthContext>();
+}
+
+} // namespace grpc
diff --git a/src/cpp/common/secure_auth_context.cc b/src/cpp/common/secure_auth_context.cc
new file mode 100644
index 0000000000..87d7bab75c
--- /dev/null
+++ b/src/cpp/common/secure_auth_context.cc
@@ -0,0 +1,96 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/cpp/common/secure_auth_context.h"
+
+#include <grpc/grpc_security.h>
+
+namespace grpc {
+
+SecureAuthContext::SecureAuthContext(grpc_auth_context* ctx) : ctx_(ctx) {}
+
+SecureAuthContext::~SecureAuthContext() { grpc_auth_context_release(ctx_); }
+
+std::vector<grpc::string> SecureAuthContext::GetPeerIdentity() const {
+ if (!ctx_) {
+ return std::vector<grpc::string>();
+ }
+ grpc_auth_property_iterator iter = grpc_auth_context_peer_identity(ctx_);
+ std::vector<grpc::string> identity;
+ const grpc_auth_property* property = nullptr;
+ while ((property = grpc_auth_property_iterator_next(&iter))) {
+ identity.push_back(grpc::string(property->value, property->value_length));
+ }
+ return identity;
+}
+
+grpc::string SecureAuthContext::GetPeerIdentityPropertyName() const {
+ if (!ctx_) {
+ return "";
+ }
+ const char* name = grpc_auth_context_peer_identity_property_name(ctx_);
+ return name == nullptr ? "" : name;
+}
+
+std::vector<grpc::string> SecureAuthContext::FindPropertyValues(
+ const grpc::string& name) const {
+ if (!ctx_) {
+ return std::vector<grpc::string>();
+ }
+ grpc_auth_property_iterator iter =
+ grpc_auth_context_find_properties_by_name(ctx_, name.c_str());
+ const grpc_auth_property* property = nullptr;
+ std::vector<grpc::string> values;
+ while ((property = grpc_auth_property_iterator_next(&iter))) {
+ values.push_back(grpc::string(property->value, property->value_length));
+ }
+ return values;
+}
+
+AuthPropertyIterator SecureAuthContext::begin() const {
+ if (ctx_) {
+ grpc_auth_property_iterator iter =
+ grpc_auth_context_property_iterator(ctx_);
+ const grpc_auth_property* property =
+ grpc_auth_property_iterator_next(&iter);
+ return AuthPropertyIterator(property, &iter);
+ } else {
+ return end();
+ }
+}
+
+AuthPropertyIterator SecureAuthContext::end() const {
+ return AuthPropertyIterator();
+}
+
+} // namespace grpc
diff --git a/src/cpp/common/secure_auth_context.h b/src/cpp/common/secure_auth_context.h
new file mode 100644
index 0000000000..264ed620a3
--- /dev/null
+++ b/src/cpp/common/secure_auth_context.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H
+#define GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H
+
+#include <grpc++/auth_context.h>
+
+struct grpc_auth_context;
+
+namespace grpc {
+
+class SecureAuthContext GRPC_FINAL : public AuthContext {
+ public:
+ SecureAuthContext(grpc_auth_context* ctx);
+
+ ~SecureAuthContext() GRPC_OVERRIDE;
+
+ std::vector<grpc::string> GetPeerIdentity() const GRPC_OVERRIDE;
+
+ grpc::string GetPeerIdentityPropertyName() const GRPC_OVERRIDE;
+
+ std::vector<grpc::string> FindPropertyValues(const grpc::string& name) const
+ GRPC_OVERRIDE;
+
+ AuthPropertyIterator begin() const GRPC_OVERRIDE;
+
+ AuthPropertyIterator end() const GRPC_OVERRIDE;
+
+ private:
+ grpc_auth_context* ctx_;
+};
+
+} // namespace grpc
+
+#endif // GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H
diff --git a/src/cpp/common/secure_create_auth_context.cc b/src/cpp/common/secure_create_auth_context.cc
new file mode 100644
index 0000000000..d81f4bbc4a
--- /dev/null
+++ b/src/cpp/common/secure_create_auth_context.cc
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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.
+ *
+ */
+#include <memory>
+
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+#include <grpc++/auth_context.h>
+#include "src/cpp/common/secure_auth_context.h"
+
+namespace grpc {
+
+std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call) {
+ if (call == nullptr) {
+ return std::shared_ptr<const AuthContext>();
+ }
+ return std::shared_ptr<const AuthContext>(
+ new SecureAuthContext(grpc_call_auth_context(call)));
+}
+
+} // namespace grpc
diff --git a/src/cpp/server/async_server_context.cc b/src/cpp/server/async_server_context.cc
deleted file mode 100644
index e1f29452a4..0000000000
--- a/src/cpp/server/async_server_context.cc
+++ /dev/null
@@ -1,99 +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.
- *
- */
-
-#include <grpc++/async_server_context.h>
-
-#include <grpc/grpc.h>
-#include <grpc/support/log.h>
-#include "src/cpp/proto/proto_utils.h"
-#include <grpc++/config.h>
-#include <grpc++/status.h>
-
-namespace grpc {
-
-AsyncServerContext::AsyncServerContext(
- grpc_call* call, const grpc::string& method, const grpc::string& host,
- system_clock::time_point absolute_deadline)
- : method_(method),
- host_(host),
- absolute_deadline_(absolute_deadline),
- request_(nullptr),
- call_(call) {}
-
-AsyncServerContext::~AsyncServerContext() { grpc_call_destroy(call_); }
-
-void AsyncServerContext::Accept(grpc_completion_queue* cq) {
- GPR_ASSERT(grpc_call_server_accept_old(call_, cq, this) == GRPC_CALL_OK);
- GPR_ASSERT(grpc_call_server_end_initial_metadata_old(
- call_, GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK);
-}
-
-bool AsyncServerContext::StartRead(grpc::protobuf::Message* request) {
- GPR_ASSERT(request);
- request_ = request;
- grpc_call_error err = grpc_call_start_read_old(call_, this);
- return err == GRPC_CALL_OK;
-}
-
-bool AsyncServerContext::StartWrite(const grpc::protobuf::Message& response,
- int flags) {
- grpc_byte_buffer* buffer = nullptr;
- GRPC_TIMER_MARK(SER_PROTO_BEGIN, call_->call());
- if (!SerializeProto(response, &buffer)) {
- return false;
- }
- GRPC_TIMER_MARK(SER_PROTO_END, call_->call());
- grpc_call_error err = grpc_call_start_write_old(call_, buffer, this, flags);
- grpc_byte_buffer_destroy(buffer);
- return err == GRPC_CALL_OK;
-}
-
-bool AsyncServerContext::StartWriteStatus(const Status& status) {
- grpc_call_error err = grpc_call_start_write_status_old(
- call_, static_cast<grpc_status_code>(status.code()),
- status.details().empty() ? nullptr
- : const_cast<char*>(status.details().c_str()),
- this);
- return err == GRPC_CALL_OK;
-}
-
-bool AsyncServerContext::ParseRead(grpc_byte_buffer* read_buffer) {
- GPR_ASSERT(request_);
- GRPC_TIMER_MARK(DESER_PROTO_BEGIN, call_->call());
- bool success = DeserializeProto(read_buffer, request_);
- GRPC_TIMER_MARK(DESER_PROTO_END, call_->call());
- request_ = nullptr;
- return success;
-}
-
-} // namespace grpc
diff --git a/src/cpp/server/create_default_thread_pool.cc b/src/cpp/server/create_default_thread_pool.cc
index 89c1d7e929..cc182f59f4 100644
--- a/src/cpp/server/create_default_thread_pool.cc
+++ b/src/cpp/server/create_default_thread_pool.cc
@@ -32,7 +32,7 @@
*/
#include <grpc/support/cpu.h>
-#include "src/cpp/server/thread_pool.h"
+#include <grpc++/fixed_size_thread_pool.h>
#ifndef GRPC_CUSTOM_DEFAULT_THREAD_POOL
@@ -41,7 +41,7 @@ namespace grpc {
ThreadPoolInterface* CreateDefaultThreadPool() {
int cores = gpr_cpu_num_cores();
if (!cores) cores = 4;
- return new ThreadPool(cores);
+ return new FixedSizeThreadPool(cores);
}
} // namespace grpc
diff --git a/src/cpp/server/thread_pool.cc b/src/cpp/server/fixed_size_thread_pool.cc
index 118cabcb61..710bcbb573 100644
--- a/src/cpp/server/thread_pool.cc
+++ b/src/cpp/server/fixed_size_thread_pool.cc
@@ -33,12 +33,11 @@
#include <grpc++/impl/sync.h>
#include <grpc++/impl/thd.h>
-
-#include "src/cpp/server/thread_pool.h"
+#include <grpc++/fixed_size_thread_pool.h>
namespace grpc {
-void ThreadPool::ThreadFunc() {
+void FixedSizeThreadPool::ThreadFunc() {
for (;;) {
// Wait until work is available or we are shutting down.
grpc::unique_lock<grpc::mutex> lock(mu_);
@@ -58,13 +57,14 @@ void ThreadPool::ThreadFunc() {
}
}
-ThreadPool::ThreadPool(int num_threads) : shutdown_(false) {
+FixedSizeThreadPool::FixedSizeThreadPool(int num_threads) : shutdown_(false) {
for (int i = 0; i < num_threads; i++) {
- threads_.push_back(new grpc::thread(&ThreadPool::ThreadFunc, this));
+ threads_.push_back(
+ new grpc::thread(&FixedSizeThreadPool::ThreadFunc, this));
}
}
-ThreadPool::~ThreadPool() {
+FixedSizeThreadPool::~FixedSizeThreadPool() {
{
grpc::lock_guard<grpc::mutex> lock(mu_);
shutdown_ = true;
@@ -76,7 +76,8 @@ ThreadPool::~ThreadPool() {
}
}
-void ThreadPool::ScheduleCallback(const std::function<void()>& callback) {
+void FixedSizeThreadPool::ScheduleCallback(
+ const std::function<void()>& callback) {
grpc::lock_guard<grpc::mutex> lock(mu_);
callbacks_.push(callback);
cv_.notify_one();
diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc
index 1437b2dea7..e6761d6244 100644
--- a/src/cpp/server/server.cc
+++ b/src/cpp/server/server.cc
@@ -118,7 +118,7 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
has_request_payload_(mrd->has_request_payload_),
request_payload_(mrd->request_payload_),
method_(mrd->method_) {
- ctx_.call_ = mrd->call_;
+ ctx_.set_call(mrd->call_);
ctx_.cq_ = &cq_;
GPR_ASSERT(mrd->in_flight_);
mrd->in_flight_ = false;
@@ -207,10 +207,11 @@ Server::~Server() {
delete sync_methods_;
}
-bool Server::RegisterService(RpcService* service) {
+bool Server::RegisterService(const grpc::string *host, RpcService* service) {
for (int i = 0; i < service->GetMethodCount(); ++i) {
RpcServiceMethod* method = service->GetMethod(i);
- void* tag = grpc_server_register_method(server_, method->name(), nullptr);
+ void* tag = grpc_server_register_method(
+ server_, method->name(), host ? host->c_str() : nullptr);
if (!tag) {
gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
method->name());
@@ -222,14 +223,14 @@ bool Server::RegisterService(RpcService* service) {
return true;
}
-bool Server::RegisterAsyncService(AsynchronousService* service) {
+bool Server::RegisterAsyncService(const grpc::string *host, AsynchronousService* service) {
GPR_ASSERT(service->server_ == nullptr &&
"Can only register an asynchronous service against one server.");
service->server_ = this;
service->request_args_ = new void*[service->method_count_];
for (size_t i = 0; i < service->method_count_; ++i) {
void* tag = grpc_server_register_method(server_, service->method_names_[i],
- nullptr);
+ host ? host->c_str() : nullptr);
if (!tag) {
gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
service->method_names_[i]);
@@ -325,7 +326,7 @@ bool Server::BaseAsyncRequest::FinalizeResult(void** tag, bool* status) {
}
}
grpc_metadata_array_destroy(&initial_metadata_array_);
- context_->call_ = call_;
+ context_->set_call(call_);
context_->cq_ = call_cq_;
Call call(call_, server_, call_cq_, server_->max_message_size_);
if (*status && call_) {
diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc
index 3ee1d54e76..f723d4611a 100644
--- a/src/cpp/server/server_builder.cc
+++ b/src/cpp/server/server_builder.cc
@@ -37,7 +37,7 @@
#include <grpc/support/log.h>
#include <grpc++/impl/service_type.h>
#include <grpc++/server.h>
-#include "src/cpp/server/thread_pool.h"
+#include <grpc++/thread_pool_interface.h>
namespace grpc {
@@ -51,11 +51,21 @@ std::unique_ptr<ServerCompletionQueue> ServerBuilder::AddCompletionQueue() {
}
void ServerBuilder::RegisterService(SynchronousService* service) {
- services_.push_back(service->service());
+ services_.emplace_back(new NamedService<RpcService>(service->service()));
}
void ServerBuilder::RegisterAsyncService(AsynchronousService* service) {
- async_services_.push_back(service);
+ async_services_.emplace_back(new NamedService<AsynchronousService>(service));
+}
+
+void ServerBuilder::RegisterService(
+ const grpc::string& addr, SynchronousService* service) {
+ services_.emplace_back(new NamedService<RpcService>(addr, service->service()));
+}
+
+void ServerBuilder::RegisterAsyncService(
+ const grpc::string& addr, AsynchronousService* service) {
+ async_services_.emplace_back(new NamedService<AsynchronousService>(addr, service));
}
void ServerBuilder::RegisterAsyncGenericService(AsyncGenericService* service) {
@@ -97,13 +107,13 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
}
for (auto service = services_.begin(); service != services_.end();
service++) {
- if (!server->RegisterService(*service)) {
+ if (!server->RegisterService((*service)->host.get(), (*service)->service)) {
return nullptr;
}
}
for (auto service = async_services_.begin();
service != async_services_.end(); service++) {
- if (!server->RegisterAsyncService(*service)) {
+ if (!server->RegisterAsyncService((*service)->host.get(), (*service)->service)) {
return nullptr;
}
}
diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc
index 699895a3cf..3b8a026996 100644
--- a/src/cpp/server/server_context.cc
+++ b/src/cpp/server/server_context.cc
@@ -39,6 +39,8 @@
#include <grpc++/impl/sync.h>
#include <grpc++/time.h>
+#include "src/cpp/common/create_auth_context.h"
+
namespace grpc {
// CompletionOp
@@ -142,8 +144,20 @@ void ServerContext::AddTrailingMetadata(const grpc::string& key,
trailing_metadata_.insert(std::make_pair(key, value));
}
-bool ServerContext::IsCancelled() {
+bool ServerContext::IsCancelled() const {
return completion_op_ && completion_op_->CheckCancelled(cq_);
}
+void ServerContext::set_call(grpc_call* call) {
+ call_ = call;
+ auth_context_ = CreateAuthContext(call);
+}
+
+std::shared_ptr<const AuthContext> ServerContext::auth_context() const {
+ if (auth_context_.get() == nullptr) {
+ auth_context_ = CreateAuthContext(call_);
+ }
+ return auth_context_;
+}
+
} // namespace grpc
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.csproj b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
index e6abbbfdf0..fdec2e7bd7 100644
--- a/src/csharp/Grpc.Auth/Grpc.Auth.csproj
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
@@ -68,6 +68,9 @@
<Reference Include="System.Net.Http.WebRequest" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="GoogleCredential.cs" />
<Compile Include="OAuth2InterceptorFactory.cs" />
@@ -81,6 +84,7 @@
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
+ <None Include="Grpc.Auth.nuspec" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
index e7a538b21b..1262bdbdab 100644
--- a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
@@ -5,19 +5,19 @@
<title>gRPC C# Auth</title>
<summary>Auth library for C# implementation of gRPC - an RPC library and framework</summary>
<description>Auth library for C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
- <version>0.5.1</version>
+ <version>$version$</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
- <releaseNotes>Release 0.5.1 of gRPC C#</releaseNotes>
+ <releaseNotes>Release $version$ of gRPC C#</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2 Auth OAuth2</tags>
<dependencies>
<dependency id="BouncyCastle" version="1.7.0" />
<dependency id="Google.Apis.Auth" version="1.9.1" />
- <dependency id="Grpc.Core" version="0.5.1" />
+ <dependency id="Grpc.Core" version="$version$" />
</dependencies>
</metadata>
<files>
diff --git a/src/csharp/Grpc.Auth/OAuth2InterceptorFactory.cs b/src/csharp/Grpc.Auth/OAuth2InterceptorFactory.cs
index ca384d1a6e..420c4cb537 100644
--- a/src/csharp/Grpc.Auth/OAuth2InterceptorFactory.cs
+++ b/src/csharp/Grpc.Auth/OAuth2InterceptorFactory.cs
@@ -52,10 +52,10 @@ namespace Grpc.Auth
/// <summary>
/// Creates OAuth2 interceptor.
/// </summary>
- public static HeaderInterceptorDelegate Create(GoogleCredential googleCredential)
+ public static MetadataInterceptorDelegate Create(GoogleCredential googleCredential)
{
var interceptor = new OAuth2Interceptor(googleCredential.InternalCredential, SystemClock.Default);
- return new HeaderInterceptorDelegate(interceptor.InterceptHeaders);
+ return new MetadataInterceptorDelegate(interceptor.InterceptHeaders);
}
/// <summary>
@@ -94,10 +94,10 @@ namespace Grpc.Auth
return credential.Token.AccessToken;
}
- public void InterceptHeaders(Metadata.Builder headerBuilder)
+ public void InterceptHeaders(Metadata metadata)
{
var accessToken = GetAccessToken(CancellationToken.None);
- headerBuilder.Add(new Metadata.MetadataEntry(AuthorizationHeader, Schema + " " + accessToken));
+ metadata.Add(new Metadata.Entry(AuthorizationHeader, Schema + " " + accessToken));
}
}
}
diff --git a/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs
index c442ccc977..70cb32d5b2 100644
--- a/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs
@@ -9,6 +9,5 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.5.*")]
[assembly: InternalsVisibleTo("Grpc.Auth.Tests")]
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index 21f94d3cf5..e797dd82f2 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -73,12 +73,6 @@ namespace Grpc.Core.Tests
Server server;
Channel channel;
- [TestFixtureSetUp]
- public void InitClass()
- {
- GrpcEnvironment.Initialize();
- }
-
[SetUp]
public void Init()
{
diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
index 92e28b7d74..927954c448 100644
--- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
+++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
@@ -37,6 +37,9 @@
</Reference>
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ClientServerTest.cs" />
<Compile Include="ServerTest.cs" />
@@ -63,4 +66,4 @@
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
index 6a132a5b22..9ae12776f3 100644
--- a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
+++ b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
@@ -43,16 +43,17 @@ namespace Grpc.Core.Tests
[Test]
public void InitializeAndShutdownGrpcEnvironment()
{
- GrpcEnvironment.Initialize();
- Assert.IsNotNull(GrpcEnvironment.ThreadPool.CompletionQueue);
+ var env = GrpcEnvironment.GetInstance();
+ Assert.IsNotNull(env.CompletionQueue);
GrpcEnvironment.Shutdown();
}
[Test]
public void SubsequentInvocations()
{
- GrpcEnvironment.Initialize();
- GrpcEnvironment.Initialize();
+ var env1 = GrpcEnvironment.GetInstance();
+ var env2 = GrpcEnvironment.GetInstance();
+ Assert.IsTrue(object.ReferenceEquals(env1, env2));
GrpcEnvironment.Shutdown();
GrpcEnvironment.Shutdown();
}
@@ -60,15 +61,13 @@ namespace Grpc.Core.Tests
[Test]
public void InitializeAfterShutdown()
{
- GrpcEnvironment.Initialize();
- var tp1 = GrpcEnvironment.ThreadPool;
+ var env1 = GrpcEnvironment.GetInstance();
GrpcEnvironment.Shutdown();
- GrpcEnvironment.Initialize();
- var tp2 = GrpcEnvironment.ThreadPool;
+ var env2 = GrpcEnvironment.GetInstance();
GrpcEnvironment.Shutdown();
- Assert.IsFalse(object.ReferenceEquals(tp1, tp2));
+ Assert.IsFalse(object.ReferenceEquals(env1, env2));
}
}
}
diff --git a/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs b/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs
index 2f6013483d..320423b245 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs
@@ -44,17 +44,17 @@ namespace Grpc.Core.Internal.Tests
[Test]
public void CreateEmptyAndDestroy()
{
- var metadata = Metadata.CreateBuilder().Build();
- var nativeMetadata = MetadataArraySafeHandle.Create(metadata);
+ var nativeMetadata = MetadataArraySafeHandle.Create(new Metadata());
nativeMetadata.Dispose();
}
[Test]
public void CreateAndDestroy()
{
- var metadata = Metadata.CreateBuilder()
- .Add(new Metadata.MetadataEntry("host", "somehost"))
- .Add(new Metadata.MetadataEntry("header2", "header value")).Build();
+ var metadata = new Metadata {
+ new Metadata.Entry("host", "somehost"),
+ new Metadata.Entry("header2", "header value"),
+ };
var nativeMetadata = MetadataArraySafeHandle.Create(metadata);
nativeMetadata.Dispose();
}
diff --git a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
index 8b3c910251..714c2f7494 100644
--- a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
+++ b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
@@ -53,18 +53,6 @@ namespace Grpc.Core.Tests
[DllImport("grpc_csharp_ext.dll")]
static extern IntPtr grpcsharp_test_nop(IntPtr ptr);
- [TestFixtureSetUp]
- public void Init()
- {
- GrpcEnvironment.Initialize();
- }
-
- [TestFixtureTearDown]
- public void Cleanup()
- {
- GrpcEnvironment.Shutdown();
- }
-
/// <summary>
/// (~1.26us .NET Windows)
/// </summary>
diff --git a/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs
index 7f6133a992..c2e5e81e91 100644
--- a/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs
@@ -9,4 +9,3 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.5.*")]
diff --git a/src/csharp/Grpc.Core.Tests/ServerTest.cs b/src/csharp/Grpc.Core.Tests/ServerTest.cs
index 02c773c9cc..1119aa370e 100644
--- a/src/csharp/Grpc.Core.Tests/ServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ServerTest.cs
@@ -44,13 +44,10 @@ namespace Grpc.Core.Tests
[Test]
public void StartAndShutdownServer()
{
- GrpcEnvironment.Initialize();
-
Server server = new Server();
server.AddListeningPort("localhost", Server.PickUnusedPort);
server.Start();
server.ShutdownAsync().Wait();
-
GrpcEnvironment.Shutdown();
}
}
diff --git a/src/csharp/Grpc.Core/Calls.cs b/src/csharp/Grpc.Core/Calls.cs
index 9f8baac684..9e95182c72 100644
--- a/src/csharp/Grpc.Core/Calls.cs
+++ b/src/csharp/Grpc.Core/Calls.cs
@@ -39,7 +39,7 @@ using Grpc.Core.Internal;
namespace Grpc.Core
{
/// <summary>
- /// Helper methods for generated client stubs to make RPC calls.
+ /// Helper methods for generated clients to make RPC calls.
/// </summary>
public static class Calls
{
@@ -58,7 +58,7 @@ namespace Grpc.Core
where TResponse : class
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
- asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
+ asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name);
var asyncResult = asyncCall.UnaryCallAsync(req, call.Headers);
RegisterCancellationCallback(asyncCall, token);
return await asyncResult;
@@ -69,7 +69,7 @@ namespace Grpc.Core
where TResponse : class
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
- asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
+ asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name);
asyncCall.StartServerStreamingCall(req, call.Headers);
RegisterCancellationCallback(asyncCall, token);
var responseStream = new ClientResponseStream<TRequest, TResponse>(asyncCall);
@@ -81,7 +81,7 @@ namespace Grpc.Core
where TResponse : class
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
- asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
+ asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name);
var resultTask = asyncCall.ClientStreamingCallAsync(call.Headers);
RegisterCancellationCallback(asyncCall, token);
var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall);
@@ -93,7 +93,7 @@ namespace Grpc.Core
where TResponse : class
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
- asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
+ asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name);
asyncCall.StartDuplexStreamingCall(call.Headers);
RegisterCancellationCallback(asyncCall, token);
var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall);
@@ -108,13 +108,5 @@ namespace Grpc.Core
token.Register(() => asyncCall.Cancel());
}
}
-
- /// <summary>
- /// Gets shared completion queue used for async calls.
- /// </summary>
- private static CompletionQueueSafeHandle GetCompletionQueue()
- {
- return GrpcEnvironment.ThreadPool.CompletionQueue;
- }
}
}
diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs
index d6bfbb7bc4..5baf260003 100644
--- a/src/csharp/Grpc.Core/Channel.cs
+++ b/src/csharp/Grpc.Core/Channel.cs
@@ -42,8 +42,10 @@ namespace Grpc.Core
/// </summary>
public class Channel : IDisposable
{
+ readonly GrpcEnvironment environment;
readonly ChannelSafeHandle handle;
readonly string target;
+ bool disposed;
/// <summary>
/// Creates a channel that connects to a specific host.
@@ -54,6 +56,7 @@ namespace Grpc.Core
/// <param name="options">Channel options.</param>
public Channel(string host, Credentials credentials = null, IEnumerable<ChannelOption> options = null)
{
+ this.environment = GrpcEnvironment.GetInstance();
using (ChannelArgsSafeHandle nativeChannelArgs = ChannelOptions.CreateChannelArgs(options))
{
if (credentials != null)
@@ -105,10 +108,35 @@ namespace Grpc.Core
}
}
+ internal CompletionQueueSafeHandle CompletionQueue
+ {
+ get
+ {
+ return this.environment.CompletionQueue;
+ }
+ }
+
+ internal CompletionRegistry CompletionRegistry
+ {
+ get
+ {
+ return this.environment.CompletionRegistry;
+ }
+ }
+
+ internal GrpcEnvironment Environment
+ {
+ get
+ {
+ return this.environment;
+ }
+ }
+
protected virtual void Dispose(bool disposing)
{
- if (handle != null && !handle.IsInvalid)
+ if (disposing && handle != null && !disposed)
{
+ disposed = true;
handle.Dispose();
}
}
diff --git a/src/csharp/Grpc.Core/Stub/AbstractStub.cs b/src/csharp/Grpc.Core/ClientBase.cs
index 4a8b254357..a099f96aea 100644
--- a/src/csharp/Grpc.Core/Stub/AbstractStub.cs
+++ b/src/csharp/Grpc.Core/ClientBase.cs
@@ -32,26 +32,39 @@
#endregion
using System;
+using System.Collections.Generic;
+
using Grpc.Core.Internal;
namespace Grpc.Core
{
- // TODO: support adding timeout to methods.
+ public delegate void MetadataInterceptorDelegate(Metadata metadata);
+
/// <summary>
- /// Base for client-side stubs.
+ /// Base class for client-side stubs.
/// </summary>
- public abstract class AbstractStub<TStub, TConfig>
- where TConfig : StubConfiguration
+ public abstract class ClientBase
{
readonly Channel channel;
- readonly TConfig config;
- public AbstractStub(Channel channel, TConfig config)
+ public ClientBase(Channel channel)
{
this.channel = channel;
- this.config = config;
}
+ /// <summary>
+ /// Can be used to register a custom header (initial metadata) interceptor.
+ /// The delegate each time before a new call on this client is started.
+ /// </summary>
+ public MetadataInterceptorDelegate HeaderInterceptor
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Channel associated with this client.
+ /// </summary>
public Channel Channel
{
get
@@ -63,13 +76,19 @@ namespace Grpc.Core
/// <summary>
/// Creates a new call to given method.
/// </summary>
- protected Call<TRequest, TResponse> CreateCall<TRequest, TResponse>(string serviceName, Method<TRequest, TResponse> method)
+ protected Call<TRequest, TResponse> CreateCall<TRequest, TResponse>(string serviceName, Method<TRequest, TResponse> method, Metadata metadata)
where TRequest : class
where TResponse : class
{
- var headerBuilder = Metadata.CreateBuilder();
- config.HeaderInterceptor(headerBuilder);
- return new Call<TRequest, TResponse>(serviceName, method, channel, headerBuilder.Build());
+ var interceptor = HeaderInterceptor;
+ if (interceptor != null)
+ {
+ metadata = metadata ?? new Metadata();
+ interceptor(metadata);
+ metadata.Freeze();
+ }
+ metadata = metadata ?? Metadata.Empty;
+ return new Call<TRequest, TResponse>(serviceName, method, channel, metadata);
}
}
}
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index a36a6a5acc..a227fe5477 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -33,8 +33,9 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
- <Reference Include="System.Collections.Immutable">
- <HintPath>..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
+ <Reference Include="System.Collections.Immutable, Version=1.1.36.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
@@ -48,6 +49,7 @@
<Compile Include="IAsyncStreamWriter.cs" />
<Compile Include="IAsyncStreamReader.cs" />
<Compile Include="Internal\GrpcLog.cs" />
+ <Compile Include="Version.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RpcException.cs" />
<Compile Include="Calls.cs" />
@@ -86,8 +88,7 @@
<Compile Include="ServerCredentials.cs" />
<Compile Include="Metadata.cs" />
<Compile Include="Internal\MetadataArraySafeHandle.cs" />
- <Compile Include="Stub\AbstractStub.cs" />
- <Compile Include="Stub\StubConfiguration.cs" />
+ <Compile Include="ClientBase.cs" />
<Compile Include="Internal\ServerCalls.cs" />
<Compile Include="ServerMethods.cs" />
<Compile Include="Internal\ClientRequestStream.cs" />
@@ -103,6 +104,7 @@
<Compile Include="ChannelOptions.cs" />
</ItemGroup>
<ItemGroup>
+ <None Include="Grpc.Core.nuspec" />
<None Include="packages.config" />
</ItemGroup>
<Choose>
@@ -130,4 +132,4 @@
</Target>
<Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" />
<Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec
index 629b978fdf..5ace6dcf89 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.nuspec
+++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec
@@ -5,19 +5,19 @@
<title>gRPC C# Core</title>
<summary>Core C# implementation of gRPC - an RPC library and framework</summary>
<description>Core C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
- <version>0.5.1</version>
+ <version>$version$</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
- <releaseNotes>Release 0.5.1 of gRPC C#</releaseNotes>
+ <releaseNotes>Release $version$ of gRPC C#</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
<dependencies>
- <dependency id="Microsoft.Bcl.Immutable" version="1.0.34" />
+ <dependency id="System.Collections.Immutable" version="1.1.36" />
<dependency id="Ix-Async" version="1.2.3" />
- <dependency id="grpc.native.csharp_ext" version="0.9.1" />
+ <dependency id="grpc.native.csharp_ext" version="$GrpcNativeCsharpExtVersion$" />
</dependencies>
</metadata>
<files>
diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs
index 30ff289714..47d1651aab 100644
--- a/src/csharp/Grpc.Core/GrpcEnvironment.cs
+++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs
@@ -33,7 +33,9 @@
using System;
using System.Runtime.InteropServices;
+using System.Threading.Tasks;
using Grpc.Core.Internal;
+using Grpc.Core.Utils;
namespace Grpc.Core
{
@@ -51,20 +53,18 @@ namespace Grpc.Core
static extern void grpcsharp_shutdown();
static object staticLock = new object();
- static volatile GrpcEnvironment instance;
+ static GrpcEnvironment instance;
readonly GrpcThreadPool threadPool;
readonly CompletionRegistry completionRegistry;
+ readonly DebugStats debugStats = new DebugStats();
bool isClosed;
/// <summary>
- /// Makes sure GRPC environment is initialized. Subsequent invocations don't have any
- /// effect unless you call Shutdown first.
- /// Although normal use cases assume you will call this just once in your application's
- /// lifetime (and call Shutdown once you're done), for the sake of easier testing it's
- /// allowed to initialize the environment again after it has been successfully shutdown.
+ /// Returns an instance of initialized gRPC environment.
+ /// Subsequent invocations return the same instance unless Shutdown has been called first.
/// </summary>
- public static void Initialize()
+ internal static GrpcEnvironment GetInstance()
{
lock (staticLock)
{
@@ -72,12 +72,13 @@ namespace Grpc.Core
{
instance = new GrpcEnvironment();
}
+ return instance;
}
}
/// <summary>
- /// Shuts down the GRPC environment if it was initialized before.
- /// Repeated invocations have no effect.
+ /// Shuts down the gRPC environment if it was initialized before.
+ /// Blocks until the environment has been fully shutdown.
/// </summary>
public static void Shutdown()
{
@@ -87,50 +88,55 @@ namespace Grpc.Core
{
instance.Close();
instance = null;
-
- CheckDebugStats();
}
}
}
- internal static GrpcThreadPool ThreadPool
+ /// <summary>
+ /// Creates gRPC environment.
+ /// </summary>
+ private GrpcEnvironment()
+ {
+ GrpcLog.RedirectNativeLogs(Console.Error);
+ grpcsharp_init();
+ completionRegistry = new CompletionRegistry(this);
+ threadPool = new GrpcThreadPool(this, THREAD_POOL_SIZE);
+ threadPool.Start();
+ // TODO: use proper logging here
+ Console.WriteLine("GRPC initialized.");
+ }
+
+ /// <summary>
+ /// Gets the completion registry used by this gRPC environment.
+ /// </summary>
+ internal CompletionRegistry CompletionRegistry
{
get
{
- var inst = instance;
- if (inst == null)
- {
- throw new InvalidOperationException("GRPC environment not initialized");
- }
- return inst.threadPool;
+ return this.completionRegistry;
}
}
- internal static CompletionRegistry CompletionRegistry
+ /// <summary>
+ /// Gets the completion queue used by this gRPC environment.
+ /// </summary>
+ internal CompletionQueueSafeHandle CompletionQueue
{
get
{
- var inst = instance;
- if (inst == null)
- {
- throw new InvalidOperationException("GRPC environment not initialized");
- }
- return inst.completionRegistry;
+ return this.threadPool.CompletionQueue;
}
}
/// <summary>
- /// Creates gRPC environment.
+ /// Gets the completion queue used by this gRPC environment.
/// </summary>
- private GrpcEnvironment()
+ internal DebugStats DebugStats
{
- GrpcLog.RedirectNativeLogs(Console.Error);
- grpcsharp_init();
- completionRegistry = new CompletionRegistry();
- threadPool = new GrpcThreadPool(THREAD_POOL_SIZE);
- threadPool.Start();
- // TODO: use proper logging here
- Console.WriteLine("GRPC initialized.");
+ get
+ {
+ return this.debugStats;
+ }
}
/// <summary>
@@ -146,32 +152,28 @@ namespace Grpc.Core
grpcsharp_shutdown();
isClosed = true;
+ debugStats.CheckOK();
+
// TODO: use proper logging here
Console.WriteLine("GRPC shutdown.");
}
- private static void CheckDebugStats()
+ /// <summary>
+ /// Shuts down this environment asynchronously.
+ /// </summary>
+ private Task CloseAsync()
{
- var remainingClientCalls = DebugStats.ActiveClientCalls.Count;
- if (remainingClientCalls != 0)
- {
- DebugWarning(string.Format("Detected {0} client calls that weren't disposed properly.", remainingClientCalls));
- }
- var remainingServerCalls = DebugStats.ActiveServerCalls.Count;
- if (remainingServerCalls != 0)
- {
- DebugWarning(string.Format("Detected {0} server calls that weren't disposed properly.", remainingServerCalls));
- }
- var pendingBatchCompletions = DebugStats.PendingBatchCompletions.Count;
- if (pendingBatchCompletions != 0)
+ return Task.Run(() =>
{
- DebugWarning(string.Format("Detected {0} pending batch completions.", pendingBatchCompletions));
- }
- }
-
- private static void DebugWarning(string message)
- {
- throw new Exception("Shutdown check: " + message);
+ try
+ {
+ Close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error occured while shutting down GrpcEnvironment: " + e);
+ }
+ });
}
}
}
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index d350f45da6..24b75d1668 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -47,6 +47,8 @@ namespace Grpc.Core.Internal
/// </summary>
internal class AsyncCall<TRequest, TResponse> : AsyncCallBase<TRequest, TResponse>
{
+ Channel channel;
+
// Completion of a pending unary response if not null.
TaskCompletionSource<TResponse> unaryResponseTcs;
@@ -61,8 +63,9 @@ namespace Grpc.Core.Internal
public void Initialize(Channel channel, CompletionQueueSafeHandle cq, string methodName)
{
- var call = CallSafeHandle.Create(channel.Handle, cq, methodName, channel.Target, Timespec.InfFuture);
- DebugStats.ActiveClientCalls.Increment();
+ this.channel = channel;
+ var call = CallSafeHandle.Create(channel.Handle, channel.CompletionRegistry, cq, methodName, channel.Target, Timespec.InfFuture);
+ channel.Environment.DebugStats.ActiveClientCalls.Increment();
InitializeInternal(call);
}
@@ -277,7 +280,7 @@ namespace Grpc.Core.Internal
protected override void OnReleaseResources()
{
- DebugStats.ActiveClientCalls.Decrement();
+ channel.Environment.DebugStats.ActiveClientCalls.Decrement();
}
/// <summary>
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
index 4f510ba40a..309067ea9d 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
@@ -48,14 +48,17 @@ namespace Grpc.Core.Internal
internal class AsyncCallServer<TRequest, TResponse> : AsyncCallBase<TResponse, TRequest>
{
readonly TaskCompletionSource<object> finishedServersideTcs = new TaskCompletionSource<object>();
+ readonly GrpcEnvironment environment;
- public AsyncCallServer(Func<TResponse, byte[]> serializer, Func<byte[], TRequest> deserializer) : base(serializer, deserializer)
+ public AsyncCallServer(Func<TResponse, byte[]> serializer, Func<byte[], TRequest> deserializer, GrpcEnvironment environment) : base(serializer, deserializer)
{
+ this.environment = Preconditions.CheckNotNull(environment);
}
public void Initialize(CallSafeHandle call)
{
- DebugStats.ActiveServerCalls.Increment();
+ call.SetCompletionRegistry(environment.CompletionRegistry);
+ environment.DebugStats.ActiveServerCalls.Increment();
InitializeInternal(call);
}
@@ -114,7 +117,7 @@ namespace Grpc.Core.Internal
protected override void OnReleaseResources()
{
- DebugStats.ActiveServerCalls.Decrement();
+ environment.DebugStats.ActiveServerCalls.Decrement();
}
/// <summary>
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index ef92b44402..3b246ac01b 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -43,6 +43,7 @@ namespace Grpc.Core.Internal
internal class CallSafeHandle : SafeHandleZeroIsInvalid
{
const uint GRPC_WRITE_BUFFER_HINT = 1;
+ CompletionRegistry completionRegistry;
[DllImport("grpc_csharp_ext.dll")]
static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline);
@@ -97,15 +98,22 @@ namespace Grpc.Core.Internal
{
}
- public static CallSafeHandle Create(ChannelSafeHandle channel, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline)
+ public static CallSafeHandle Create(ChannelSafeHandle channel, CompletionRegistry registry, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline)
{
- return grpcsharp_channel_create_call(channel, cq, method, host, deadline);
+ var result = grpcsharp_channel_create_call(channel, cq, method, host, deadline);
+ result.SetCompletionRegistry(registry);
+ return result;
+ }
+
+ public void SetCompletionRegistry(CompletionRegistry completionRegistry)
+ {
+ this.completionRegistry = completionRegistry;
}
public void StartUnary(byte[] payload, BatchCompletionDelegate callback, MetadataArraySafeHandle metadataArray)
{
var ctx = BatchContextSafeHandle.Create();
- GrpcEnvironment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+ completionRegistry.RegisterBatchCompletion(ctx, callback);
grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray)
.CheckOk();
}
@@ -119,56 +127,56 @@ namespace Grpc.Core.Internal
public void StartClientStreaming(BatchCompletionDelegate callback, MetadataArraySafeHandle metadataArray)
{
var ctx = BatchContextSafeHandle.Create();
- GrpcEnvironment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+ completionRegistry.RegisterBatchCompletion(ctx, callback);
grpcsharp_call_start_client_streaming(this, ctx, metadataArray).CheckOk();
}
public void StartServerStreaming(byte[] payload, BatchCompletionDelegate callback, MetadataArraySafeHandle metadataArray)
{
var ctx = BatchContextSafeHandle.Create();
- GrpcEnvironment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+ completionRegistry.RegisterBatchCompletion(ctx, callback);
grpcsharp_call_start_server_streaming(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray).CheckOk();
}
public void StartDuplexStreaming(BatchCompletionDelegate callback, MetadataArraySafeHandle metadataArray)
{
var ctx = BatchContextSafeHandle.Create();
- GrpcEnvironment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+ completionRegistry.RegisterBatchCompletion(ctx, callback);
grpcsharp_call_start_duplex_streaming(this, ctx, metadataArray).CheckOk();
}
public void StartSendMessage(byte[] payload, BatchCompletionDelegate callback)
{
var ctx = BatchContextSafeHandle.Create();
- GrpcEnvironment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+ completionRegistry.RegisterBatchCompletion(ctx, callback);
grpcsharp_call_send_message(this, ctx, payload, new UIntPtr((ulong)payload.Length)).CheckOk();
}
public void StartSendCloseFromClient(BatchCompletionDelegate callback)
{
var ctx = BatchContextSafeHandle.Create();
- GrpcEnvironment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+ completionRegistry.RegisterBatchCompletion(ctx, callback);
grpcsharp_call_send_close_from_client(this, ctx).CheckOk();
}
public void StartSendStatusFromServer(Status status, BatchCompletionDelegate callback)
{
var ctx = BatchContextSafeHandle.Create();
- GrpcEnvironment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+ completionRegistry.RegisterBatchCompletion(ctx, callback);
grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, status.Detail).CheckOk();
}
public void StartReceiveMessage(BatchCompletionDelegate callback)
{
var ctx = BatchContextSafeHandle.Create();
- GrpcEnvironment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+ completionRegistry.RegisterBatchCompletion(ctx, callback);
grpcsharp_call_recv_message(this, ctx).CheckOk();
}
public void StartServerSide(BatchCompletionDelegate callback)
{
var ctx = BatchContextSafeHandle.Create();
- GrpcEnvironment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+ completionRegistry.RegisterBatchCompletion(ctx, callback);
grpcsharp_call_start_serverside(this, ctx).CheckOk();
}
diff --git a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs
index 80f006ae50..f6d8aa0600 100644
--- a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs
+++ b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs
@@ -45,11 +45,17 @@ namespace Grpc.Core.Internal
internal class CompletionRegistry
{
- readonly ConcurrentDictionary<IntPtr, OpCompletionDelegate> dict = new ConcurrentDictionary<IntPtr, OpCompletionDelegate>();
+ readonly GrpcEnvironment environment;
+ readonly ConcurrentDictionary<IntPtr, OpCompletionDelegate> dict = new ConcurrentDictionary<IntPtr, OpCompletionDelegate>();
+
+ public CompletionRegistry(GrpcEnvironment environment)
+ {
+ this.environment = environment;
+ }
public void Register(IntPtr key, OpCompletionDelegate callback)
{
- DebugStats.PendingBatchCompletions.Increment();
+ environment.DebugStats.PendingBatchCompletions.Increment();
Preconditions.CheckState(dict.TryAdd(key, callback));
}
@@ -63,7 +69,7 @@ namespace Grpc.Core.Internal
{
OpCompletionDelegate value;
Preconditions.CheckState(dict.TryRemove(key, out value));
- DebugStats.PendingBatchCompletions.Decrement();
+ environment.DebugStats.PendingBatchCompletions.Decrement();
return value;
}
diff --git a/src/csharp/Grpc.Core/Internal/DebugStats.cs b/src/csharp/Grpc.Core/Internal/DebugStats.cs
index ef9d9afe11..8793450ff3 100644
--- a/src/csharp/Grpc.Core/Internal/DebugStats.cs
+++ b/src/csharp/Grpc.Core/Internal/DebugStats.cs
@@ -36,12 +36,39 @@ using System.Threading;
namespace Grpc.Core.Internal
{
- internal static class DebugStats
+ internal class DebugStats
{
- public static readonly AtomicCounter ActiveClientCalls = new AtomicCounter();
+ public readonly AtomicCounter ActiveClientCalls = new AtomicCounter();
- public static readonly AtomicCounter ActiveServerCalls = new AtomicCounter();
+ public readonly AtomicCounter ActiveServerCalls = new AtomicCounter();
- public static readonly AtomicCounter PendingBatchCompletions = new AtomicCounter();
+ public readonly AtomicCounter PendingBatchCompletions = new AtomicCounter();
+
+ /// <summary>
+ /// Checks the debug stats and take action for any inconsistency found.
+ /// </summary>
+ public void CheckOK()
+ {
+ var remainingClientCalls = ActiveClientCalls.Count;
+ if (remainingClientCalls != 0)
+ {
+ DebugWarning(string.Format("Detected {0} client calls that weren't disposed properly.", remainingClientCalls));
+ }
+ var remainingServerCalls = ActiveServerCalls.Count;
+ if (remainingServerCalls != 0)
+ {
+ DebugWarning(string.Format("Detected {0} server calls that weren't disposed properly.", remainingServerCalls));
+ }
+ var pendingBatchCompletions = PendingBatchCompletions.Count;
+ if (pendingBatchCompletions != 0)
+ {
+ DebugWarning(string.Format("Detected {0} pending batch completions.", pendingBatchCompletions));
+ }
+ }
+
+ private void DebugWarning(string message)
+ {
+ throw new Exception("Shutdown check: " + message);
+ }
}
}
diff --git a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
index 89b44a4e2b..b77e893044 100644
--- a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
+++ b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
@@ -45,14 +45,16 @@ namespace Grpc.Core.Internal
/// </summary>
internal class GrpcThreadPool
{
+ readonly GrpcEnvironment environment;
readonly object myLock = new object();
readonly List<Thread> threads = new List<Thread>();
readonly int poolSize;
CompletionQueueSafeHandle cq;
- public GrpcThreadPool(int poolSize)
+ public GrpcThreadPool(GrpcEnvironment environment, int poolSize)
{
+ this.environment = environment;
this.poolSize = poolSize;
}
@@ -80,7 +82,7 @@ namespace Grpc.Core.Internal
{
cq.Shutdown();
- Console.WriteLine("Waiting for GPRC threads to finish.");
+ Console.WriteLine("Waiting for GRPC threads to finish.");
foreach (var thread in threads)
{
thread.Join();
@@ -122,7 +124,7 @@ namespace Grpc.Core.Internal
IntPtr tag = ev.tag;
try
{
- var callback = GrpcEnvironment.CompletionRegistry.Extract(tag);
+ var callback = environment.CompletionRegistry.Extract(tag);
callback(success);
}
catch (Exception e)
diff --git a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
index c9c4d954c9..80aa7f5603 100644
--- a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
@@ -54,11 +54,11 @@ namespace Grpc.Core.Internal
public static MetadataArraySafeHandle Create(Metadata metadata)
{
- var entries = metadata.Entries;
- var metadataArray = grpcsharp_metadata_array_create(new UIntPtr((ulong)entries.Count));
- for (int i = 0; i < entries.Count; i++)
+ // TODO(jtattermusch): we might wanna check that the metadata is readonly
+ var metadataArray = grpcsharp_metadata_array_create(new UIntPtr((ulong)metadata.Count));
+ for (int i = 0; i < metadata.Count; i++)
{
- grpcsharp_metadata_array_add(metadataArray, entries[i].Key, entries[i].ValueBytes, new UIntPtr((ulong)entries[i].ValueBytes.Length));
+ grpcsharp_metadata_array_add(metadataArray, metadata[i].Key, metadata[i].ValueBytes, new UIntPtr((ulong)metadata[i].ValueBytes.Length));
}
return metadataArray;
}
diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
index c0e5bae13f..594e46b159 100644
--- a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
@@ -42,7 +42,7 @@ namespace Grpc.Core.Internal
{
internal interface IServerCallHandler
{
- Task HandleCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq);
+ Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment);
}
internal class UnaryServerCallHandler<TRequest, TResponse> : IServerCallHandler
@@ -58,11 +58,12 @@ namespace Grpc.Core.Internal
this.handler = handler;
}
- public async Task HandleCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq)
+ public async Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment)
{
var asyncCall = new AsyncCallServer<TRequest, TResponse>(
method.ResponseMarshaller.Serializer,
- method.RequestMarshaller.Deserializer);
+ method.RequestMarshaller.Deserializer,
+ environment);
asyncCall.Initialize(call);
var finishedTask = asyncCall.ServerSideCallAsync();
@@ -110,11 +111,12 @@ namespace Grpc.Core.Internal
this.handler = handler;
}
- public async Task HandleCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq)
+ public async Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment)
{
var asyncCall = new AsyncCallServer<TRequest, TResponse>(
method.ResponseMarshaller.Serializer,
- method.RequestMarshaller.Deserializer);
+ method.RequestMarshaller.Deserializer,
+ environment);
asyncCall.Initialize(call);
var finishedTask = asyncCall.ServerSideCallAsync();
@@ -163,11 +165,12 @@ namespace Grpc.Core.Internal
this.handler = handler;
}
- public async Task HandleCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq)
+ public async Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment)
{
var asyncCall = new AsyncCallServer<TRequest, TResponse>(
method.ResponseMarshaller.Serializer,
- method.RequestMarshaller.Deserializer);
+ method.RequestMarshaller.Deserializer,
+ environment);
asyncCall.Initialize(call);
var finishedTask = asyncCall.ServerSideCallAsync();
@@ -219,11 +222,12 @@ namespace Grpc.Core.Internal
this.handler = handler;
}
- public async Task HandleCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq)
+ public async Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment)
{
var asyncCall = new AsyncCallServer<TRequest, TResponse>(
method.ResponseMarshaller.Serializer,
- method.RequestMarshaller.Deserializer);
+ method.RequestMarshaller.Deserializer,
+ environment);
asyncCall.Initialize(call);
var finishedTask = asyncCall.ServerSideCallAsync();
@@ -255,11 +259,11 @@ namespace Grpc.Core.Internal
internal class NoSuchMethodCallHandler : IServerCallHandler
{
- public async Task HandleCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq)
+ public async Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment)
{
// We don't care about the payload type here.
var asyncCall = new AsyncCallServer<byte[], byte[]>(
- (payload) => payload, (payload) => payload);
+ (payload) => payload, (payload) => payload, environment);
asyncCall.Initialize(call);
var finishedTask = asyncCall.ServerSideCallAsync();
diff --git a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
index 83dbb910aa..9e1170e6dd 100644
--- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
@@ -91,19 +91,19 @@ namespace Grpc.Core.Internal
{
grpcsharp_server_start(this);
}
-
- public void ShutdownAndNotify(CompletionQueueSafeHandle cq, BatchCompletionDelegate callback)
+
+ public void ShutdownAndNotify(BatchCompletionDelegate callback, GrpcEnvironment environment)
{
var ctx = BatchContextSafeHandle.Create();
- GrpcEnvironment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
- grpcsharp_server_shutdown_and_notify_callback(this, cq, ctx);
+ environment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+ grpcsharp_server_shutdown_and_notify_callback(this, environment.CompletionQueue, ctx);
}
- public void RequestCall(CompletionQueueSafeHandle cq, BatchCompletionDelegate callback)
+ public void RequestCall(BatchCompletionDelegate callback, GrpcEnvironment environment)
{
var ctx = BatchContextSafeHandle.Create();
- GrpcEnvironment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
- grpcsharp_server_request_call(this, cq, ctx).CheckOk();
+ environment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+ grpcsharp_server_request_call(this, environment.CompletionQueue, ctx).CheckOk();
}
protected override bool ReleaseHandle()
diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core/Metadata.cs
index eccec26a61..4552d39d88 100644
--- a/src/csharp/Grpc.Core/Metadata.cs
+++ b/src/csharp/Grpc.Core/Metadata.cs
@@ -30,55 +30,163 @@
#endregion
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Collections.Specialized;
using System.Runtime.InteropServices;
using System.Text;
+using Grpc.Core.Utils;
+
namespace Grpc.Core
{
/// <summary>
- /// gRPC call metadata.
+ /// Provides access to read and write metadata values to be exchanged during a call.
/// </summary>
- public class Metadata
+ public sealed class Metadata : IList<Metadata.Entry>
{
- public static readonly Metadata Empty = new Metadata(ImmutableList<MetadataEntry>.Empty);
+ /// <summary>
+ /// An read-only instance of metadata containing no entries.
+ /// </summary>
+ public static readonly Metadata Empty = new Metadata().Freeze();
+
+ readonly List<Entry> entries;
+ bool readOnly;
+
+ public Metadata()
+ {
+ this.entries = new List<Entry>();
+ }
+
+ public Metadata(ICollection<Entry> entries)
+ {
+ this.entries = new List<Entry>(entries);
+ }
+
+ /// <summary>
+ /// Makes this object read-only.
+ /// </summary>
+ /// <returns>this object</returns>
+ public Metadata Freeze()
+ {
+ this.readOnly = true;
+ return this;
+ }
+
+ // TODO: add support for access by key
+
+ #region IList members
+
+ public int IndexOf(Metadata.Entry item)
+ {
+ return entries.IndexOf(item);
+ }
- readonly ImmutableList<MetadataEntry> entries;
+ public void Insert(int index, Metadata.Entry item)
+ {
+ CheckWriteable();
+ entries.Insert(index, item);
+ }
- public Metadata(ImmutableList<MetadataEntry> entries)
+ public void RemoveAt(int index)
{
- this.entries = entries;
+ CheckWriteable();
+ entries.RemoveAt(index);
}
- public ImmutableList<MetadataEntry> Entries
+ public Metadata.Entry this[int index]
{
get
{
- return this.entries;
+ return entries[index];
+ }
+
+ set
+ {
+ CheckWriteable();
+ entries[index] = value;
}
}
- public static Builder CreateBuilder()
+ public void Add(Metadata.Entry item)
+ {
+ CheckWriteable();
+ entries.Add(item);
+ }
+
+ public void Clear()
+ {
+ CheckWriteable();
+ entries.Clear();
+ }
+
+ public bool Contains(Metadata.Entry item)
+ {
+ return entries.Contains(item);
+ }
+
+ public void CopyTo(Metadata.Entry[] array, int arrayIndex)
{
- return new Builder();
+ entries.CopyTo(array, arrayIndex);
}
-
- public struct MetadataEntry
+
+ public int Count
+ {
+ get { return entries.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return readOnly; }
+ }
+
+ public bool Remove(Metadata.Entry item)
+ {
+ CheckWriteable();
+ return entries.Remove(item);
+ }
+
+ public IEnumerator<Metadata.Entry> GetEnumerator()
+ {
+ return entries.GetEnumerator();
+ }
+
+ IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return entries.GetEnumerator();
+ }
+
+ private void CheckWriteable()
+ {
+ Preconditions.CheckState(!readOnly, "Object is read only");
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Metadata entry
+ /// </summary>
+ public struct Entry
{
+ private static readonly Encoding Encoding = Encoding.ASCII;
+
readonly string key;
- readonly byte[] valueBytes;
+ string value;
+ byte[] valueBytes;
- public MetadataEntry(string key, byte[] valueBytes)
+ public Entry(string key, byte[] valueBytes)
{
- this.key = key;
- this.valueBytes = valueBytes;
+ this.key = Preconditions.CheckNotNull(key);
+ this.value = null;
+ this.valueBytes = Preconditions.CheckNotNull(valueBytes);
}
- public MetadataEntry(string key, string value)
+ public Entry(string key, string value)
{
- this.key = key;
- this.valueBytes = Encoding.ASCII.GetBytes(value);
+ this.key = Preconditions.CheckNotNull(key);
+ this.value = Preconditions.CheckNotNull(value);
+ this.valueBytes = null;
}
public string Key
@@ -89,38 +197,29 @@ namespace Grpc.Core
}
}
- // TODO: using ByteString would guarantee immutability.
public byte[] ValueBytes
{
get
{
- return this.valueBytes;
+ if (valueBytes == null)
+ {
+ valueBytes = Encoding.GetBytes(value);
+ }
+ return valueBytes;
}
}
- }
- public class Builder
- {
- readonly List<Metadata.MetadataEntry> entries = new List<Metadata.MetadataEntry>();
-
- public List<MetadataEntry> Entries
+ public string Value
{
get
{
- return entries;
+ if (value == null)
+ {
+ value = Encoding.GetString(valueBytes);
+ }
+ return value;
}
}
-
- public Builder Add(MetadataEntry entry)
- {
- entries.Add(entry);
- return this;
- }
-
- public Metadata Build()
- {
- return new Metadata(entries.ToImmutableList());
- }
}
}
}
diff --git a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
index 03b682181a..2b3d7530f2 100644
--- a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
@@ -9,6 +9,5 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.5.*")]
[assembly: InternalsVisibleTo("Grpc.Core.Tests")]
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index 8e818885d1..cbf77196cf 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -52,6 +52,7 @@ namespace Grpc.Core
/// </summary>
public const int PickUnusedPort = 0;
+ readonly GrpcEnvironment environment;
readonly ServerSafeHandle handle;
readonly object myLock = new object();
@@ -67,9 +68,10 @@ namespace Grpc.Core
/// <param name="options">Channel options.</param>
public Server(IEnumerable<ChannelOption> options = null)
{
+ this.environment = GrpcEnvironment.GetInstance();
using (var channelArgs = ChannelOptions.CreateChannelArgs(options))
{
- this.handle = ServerSafeHandle.NewServer(GetCompletionQueue(), channelArgs);
+ this.handle = ServerSafeHandle.NewServer(environment.CompletionQueue, channelArgs);
}
}
@@ -144,7 +146,7 @@ namespace Grpc.Core
shutdownRequested = true;
}
- handle.ShutdownAndNotify(GetCompletionQueue(), HandleServerShutdown);
+ handle.ShutdownAndNotify(HandleServerShutdown, environment);
await shutdownTcs.Task;
handle.Dispose();
}
@@ -173,7 +175,7 @@ namespace Grpc.Core
shutdownRequested = true;
}
- handle.ShutdownAndNotify(GetCompletionQueue(), HandleServerShutdown);
+ handle.ShutdownAndNotify(HandleServerShutdown, environment);
handle.CancelAllCalls();
await shutdownTcs.Task;
handle.Dispose();
@@ -208,7 +210,7 @@ namespace Grpc.Core
{
if (!shutdownRequested)
{
- handle.RequestCall(GetCompletionQueue(), HandleNewServerRpc);
+ handle.RequestCall(HandleNewServerRpc, environment);
}
}
}
@@ -225,7 +227,7 @@ namespace Grpc.Core
{
callHandler = new NoSuchMethodCallHandler();
}
- await callHandler.HandleCall(method, call, GetCompletionQueue());
+ await callHandler.HandleCall(method, call, environment);
}
catch (Exception e)
{
@@ -259,10 +261,5 @@ namespace Grpc.Core
{
shutdownTcs.SetResult(null);
}
-
- private static CompletionQueueSafeHandle GetCompletionQueue()
- {
- return GrpcEnvironment.ThreadPool.CompletionQueue;
- }
}
}
diff --git a/src/csharp/Grpc.Core/Version.cs b/src/csharp/Grpc.Core/Version.cs
new file mode 100644
index 0000000000..f1db1f6157
--- /dev/null
+++ b/src/csharp/Grpc.Core/Version.cs
@@ -0,0 +1,5 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// The current version of gRPC C#.
+[assembly: AssemblyVersion("0.6.0.*")]
diff --git a/src/csharp/Grpc.Core/packages.config b/src/csharp/Grpc.Core/packages.config
index fb7eaaeeda..6cdcdf2656 100644
--- a/src/csharp/Grpc.Core/packages.config
+++ b/src/csharp/Grpc.Core/packages.config
@@ -3,5 +3,5 @@
<package id="grpc.dependencies.openssl.redist" version="1.0.2.2" targetFramework="net45" />
<package id="grpc.dependencies.zlib.redist" version="1.2.8.9" targetFramework="net45" />
<package id="Ix-Async" version="1.2.3" targetFramework="net45" />
- <package id="Microsoft.Bcl.Immutable" version="1.0.34" targetFramework="net45" />
+ <package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj b/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj
index 19bb4347aa..5d5401593d 100644
--- a/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj
+++ b/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -35,6 +35,9 @@
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MathClient.cs" />
</ItemGroup>
@@ -49,4 +52,4 @@
<Name>Grpc.Examples</Name>
</ProjectReference>
</ItemGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Examples.MathClient/MathClient.cs b/src/csharp/Grpc.Examples.MathClient/MathClient.cs
index 360fe928dd..cfe2a06916 100644
--- a/src/csharp/Grpc.Examples.MathClient/MathClient.cs
+++ b/src/csharp/Grpc.Examples.MathClient/MathClient.cs
@@ -39,22 +39,20 @@ namespace math
{
public static void Main(string[] args)
{
- GrpcEnvironment.Initialize();
-
using (Channel channel = new Channel("127.0.0.1", 23456))
{
- Math.IMathClient stub = new Math.MathClient(channel);
- MathExamples.DivExample(stub);
+ Math.IMathClient client = new Math.MathClient(channel);
+ MathExamples.DivExample(client);
- MathExamples.DivAsyncExample(stub).Wait();
+ MathExamples.DivAsyncExample(client).Wait();
- MathExamples.FibExample(stub).Wait();
+ MathExamples.FibExample(client).Wait();
- MathExamples.SumExample(stub).Wait();
+ MathExamples.SumExample(client).Wait();
- MathExamples.DivManyExample(stub).Wait();
+ MathExamples.DivManyExample(client).Wait();
- MathExamples.DependendRequestsExample(stub).Wait();
+ MathExamples.DependendRequestsExample(client).Wait();
}
GrpcEnvironment.Shutdown();
diff --git a/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs
index 4b77472fbd..0fb0dbd510 100644
--- a/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs
@@ -9,4 +9,3 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.5.*")]
diff --git a/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj b/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj
index ba6586ee5e..677d87da20 100644
--- a/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj
+++ b/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj
@@ -35,6 +35,9 @@
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MathServer.cs" />
</ItemGroup>
diff --git a/src/csharp/Grpc.Examples.MathServer/MathServer.cs b/src/csharp/Grpc.Examples.MathServer/MathServer.cs
index d05e3f2808..f440985112 100644
--- a/src/csharp/Grpc.Examples.MathServer/MathServer.cs
+++ b/src/csharp/Grpc.Examples.MathServer/MathServer.cs
@@ -42,8 +42,6 @@ namespace math
{
string host = "0.0.0.0";
- GrpcEnvironment.Initialize();
-
Server server = new Server();
server.AddServiceDefinition(Math.BindService(new MathServiceImpl()));
int port = server.AddListeningPort(host, 23456);
diff --git a/src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs
index c18fc251d4..63035b6c63 100644
--- a/src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs
@@ -9,4 +9,3 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.5.*")]
diff --git a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
index 6e84add42b..d59d7515d1 100644
--- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
+++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
@@ -43,6 +43,9 @@
</Reference>
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MathClientServerTests.cs" />
</ItemGroup>
diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
index aadd49f795..e7c4b33120 100644
--- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
+++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
@@ -49,33 +49,30 @@ namespace math.Tests
string host = "localhost";
Server server;
Channel channel;
- Math.IMathClient client;
+ Math.MathClient client;
[TestFixtureSetUp]
public void Init()
{
- GrpcEnvironment.Initialize();
-
server = new Server();
server.AddServiceDefinition(Math.BindService(new MathServiceImpl()));
int port = server.AddListeningPort(host, Server.PickUnusedPort);
server.Start();
channel = new Channel(host, port);
+ client = Math.NewClient(channel);
// TODO(jtattermusch): get rid of the custom header here once we have dedicated tests
// for header support.
- var stubConfig = new StubConfiguration((headerBuilder) =>
+ client.HeaderInterceptor = (metadata) =>
{
- headerBuilder.Add(new Metadata.MetadataEntry("customHeader", "abcdef"));
- });
- client = Math.NewStub(channel, stubConfig);
+ metadata.Add(new Metadata.Entry("customHeader", "abcdef"));
+ };
}
[TestFixtureTearDown]
public void Cleanup()
{
channel.Dispose();
-
server.ShutdownAsync().Wait();
GrpcEnvironment.Shutdown();
}
diff --git a/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs
index c1ba396a95..846afb4616 100644
--- a/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs
@@ -9,4 +9,3 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.5.*")]
diff --git a/src/csharp/Grpc.Examples/Grpc.Examples.csproj b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
index 5ce490f403..eaf24a253c 100644
--- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj
+++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
@@ -40,6 +40,9 @@
</Reference>
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Math.cs" />
<Compile Include="MathGrpc.cs" />
diff --git a/src/csharp/Grpc.Examples/MathExamples.cs b/src/csharp/Grpc.Examples/MathExamples.cs
index d2cfbee18f..7deb651689 100644
--- a/src/csharp/Grpc.Examples/MathExamples.cs
+++ b/src/csharp/Grpc.Examples/MathExamples.cs
@@ -38,29 +38,29 @@ namespace math
{
public static class MathExamples
{
- public static void DivExample(Math.IMathClient stub)
+ public static void DivExample(Math.IMathClient client)
{
- DivReply result = stub.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build());
+ DivReply result = client.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build());
Console.WriteLine("Div Result: " + result);
}
- public static async Task DivAsyncExample(Math.IMathClient stub)
+ public static async Task DivAsyncExample(Math.IMathClient client)
{
- Task<DivReply> resultTask = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
+ Task<DivReply> resultTask = client.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
DivReply result = await resultTask;
Console.WriteLine("DivAsync Result: " + result);
}
- public static async Task FibExample(Math.IMathClient stub)
+ public static async Task FibExample(Math.IMathClient client)
{
- using (var call = stub.Fib(new FibArgs.Builder { Limit = 5 }.Build()))
+ using (var call = client.Fib(new FibArgs.Builder { Limit = 5 }.Build()))
{
List<Num> result = await call.ResponseStream.ToList();
Console.WriteLine("Fib Result: " + string.Join("|", result));
}
}
- public static async Task SumExample(Math.IMathClient stub)
+ public static async Task SumExample(Math.IMathClient client)
{
var numbers = new List<Num>
{
@@ -69,14 +69,14 @@ namespace math
new Num.Builder { Num_ = 3 }.Build()
};
- using (var call = stub.Sum())
+ using (var call = client.Sum())
{
await call.RequestStream.WriteAll(numbers);
Console.WriteLine("Sum Result: " + await call.Result);
}
}
- public static async Task DivManyExample(Math.IMathClient stub)
+ public static async Task DivManyExample(Math.IMathClient client)
{
var divArgsList = new List<DivArgs>
{
@@ -84,14 +84,14 @@ namespace math
new DivArgs.Builder { Dividend = 100, Divisor = 21 }.Build(),
new DivArgs.Builder { Dividend = 7, Divisor = 2 }.Build()
};
- using (var call = stub.DivMany())
+ using (var call = client.DivMany())
{
await call.RequestStream.WriteAll(divArgsList);
Console.WriteLine("DivMany Result: " + string.Join("|", await call.ResponseStream.ToList()));
}
}
- public static async Task DependendRequestsExample(Math.IMathClient stub)
+ public static async Task DependendRequestsExample(Math.IMathClient client)
{
var numbers = new List<Num>
{
@@ -101,13 +101,13 @@ namespace math
};
Num sum;
- using (var sumCall = stub.Sum())
+ using (var sumCall = client.Sum())
{
await sumCall.RequestStream.WriteAll(numbers);
sum = await sumCall.Result;
}
- DivReply result = await stub.DivAsync(new DivArgs.Builder { Dividend = sum.Num_, Divisor = numbers.Count }.Build());
+ DivReply result = await client.DivAsync(new DivArgs.Builder { Dividend = sum.Num_, Divisor = numbers.Count }.Build());
Console.WriteLine("Avg Result: " + result);
}
}
diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs
index b9efc44e8c..1805972ce3 100644
--- a/src/csharp/Grpc.Examples/MathGrpc.cs
+++ b/src/csharp/Grpc.Examples/MathGrpc.cs
@@ -41,14 +41,14 @@ namespace math {
__Marshaller_Num,
__Marshaller_Num);
- // client-side stub interface
+ // client interface
public interface IMathClient
{
- global::math.DivReply Div(global::math.DivArgs request, CancellationToken token = default(CancellationToken));
- Task<global::math.DivReply> DivAsync(global::math.DivArgs request, CancellationToken token = default(CancellationToken));
- AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(CancellationToken token = default(CancellationToken));
- AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, CancellationToken token = default(CancellationToken));
- AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(CancellationToken token = default(CancellationToken));
+ global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ Task<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
}
// server-side interface
@@ -61,38 +61,35 @@ namespace math {
}
// client stub
- public class MathClient : AbstractStub<MathClient, StubConfiguration>, IMathClient
+ public class MathClient : ClientBase, IMathClient
{
- public MathClient(Channel channel) : this(channel, StubConfiguration.Default)
+ public MathClient(Channel channel) : base(channel)
{
}
- public MathClient(Channel channel, StubConfiguration config) : base(channel, config)
+ public global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
+ var call = CreateCall(__ServiceName, __Method_Div, headers);
+ return Calls.BlockingUnaryCall(call, request, cancellationToken);
}
- public global::math.DivReply Div(global::math.DivArgs request, CancellationToken token = default(CancellationToken))
+ public Task<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_Div);
- return Calls.BlockingUnaryCall(call, request, token);
+ var call = CreateCall(__ServiceName, __Method_Div, headers);
+ return Calls.AsyncUnaryCall(call, request, cancellationToken);
}
- public Task<global::math.DivReply> DivAsync(global::math.DivArgs request, CancellationToken token = default(CancellationToken))
+ public AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_Div);
- return Calls.AsyncUnaryCall(call, request, token);
+ var call = CreateCall(__ServiceName, __Method_DivMany, headers);
+ return Calls.AsyncDuplexStreamingCall(call, cancellationToken);
}
- public AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(CancellationToken token = default(CancellationToken))
+ public AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_DivMany);
- return Calls.AsyncDuplexStreamingCall(call, token);
+ var call = CreateCall(__ServiceName, __Method_Fib, headers);
+ return Calls.AsyncServerStreamingCall(call, request, cancellationToken);
}
- public AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, CancellationToken token = default(CancellationToken))
+ public AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_Fib);
- return Calls.AsyncServerStreamingCall(call, request, token);
- }
- public AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(CancellationToken token = default(CancellationToken))
- {
- var call = CreateCall(__ServiceName, __Method_Sum);
- return Calls.AsyncClientStreamingCall(call, token);
+ var call = CreateCall(__ServiceName, __Method_Sum, headers);
+ return Calls.AsyncClientStreamingCall(call, cancellationToken);
}
}
@@ -106,17 +103,12 @@ namespace math {
.AddMethod(__Method_Sum, serviceImpl.Sum).Build();
}
- // creates a new client stub
- public static IMathClient NewStub(Channel channel)
+ // creates a new client
+ public static MathClient NewClient(Channel channel)
{
return new MathClient(channel);
}
- // creates a new client stub
- public static IMathClient NewStub(Channel channel, StubConfiguration config)
- {
- return new MathClient(channel, config);
- }
}
}
#endregion
diff --git a/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs
index a63e05d7f6..92111389cb 100644
--- a/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs
@@ -9,4 +9,3 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.5.*")]
diff --git a/src/csharp/Grpc.HealthCheck.Tests/.gitignore b/src/csharp/Grpc.HealthCheck.Tests/.gitignore
new file mode 100644
index 0000000000..1746e3269e
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck.Tests/.gitignore
@@ -0,0 +1,2 @@
+bin
+obj
diff --git a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
new file mode 100644
index 0000000000..72e110302b
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Grpc.HealthCheck.Tests</RootNamespace>
+ <AssemblyName>Grpc.HealthCheck.Tests</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Google.ProtocolBuffers">
+ <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.ProtocolBuffers.Serialization">
+ <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
+ <Compile Include="HealthServiceImplTest.cs" />
+ <Compile Include="HealthClientServerTest.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
+ <Project>{ccc4440e-49f7-4790-b0af-feabb0837ae7}</Project>
+ <Name>Grpc.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Grpc.HealthCheck\Grpc.HealthCheck.csproj">
+ <Project>{aa5e328a-8835-49d7-98ed-c29f2b3049f0}</Project>
+ <Name>Grpc.HealthCheck</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
new file mode 100644
index 0000000000..73ff0e74b5
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
@@ -0,0 +1,97 @@
+#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 System.Text;
+using System.Threading.Tasks;
+
+using Grpc.Core;
+using Grpc.Health.V1Alpha;
+using NUnit.Framework;
+
+namespace Grpc.HealthCheck.Tests
+{
+ /// <summary>
+ /// Health client talks to health server.
+ /// </summary>
+ public class HealthClientServerTest
+ {
+ const string Host = "localhost";
+ Server server;
+ Channel channel;
+ Grpc.Health.V1Alpha.Health.IHealthClient client;
+ Grpc.HealthCheck.HealthServiceImpl serviceImpl;
+
+ [TestFixtureSetUp]
+ public void Init()
+ {
+ serviceImpl = new HealthServiceImpl();
+
+ server = new Server();
+ server.AddServiceDefinition(Grpc.Health.V1Alpha.Health.BindService(serviceImpl));
+ int port = server.AddListeningPort(Host, Server.PickUnusedPort);
+ server.Start();
+ channel = new Channel(Host, port);
+
+ client = Grpc.Health.V1Alpha.Health.NewClient(channel);
+ }
+
+ [TestFixtureTearDown]
+ public void Cleanup()
+ {
+ channel.Dispose();
+
+ server.ShutdownAsync().Wait();
+ GrpcEnvironment.Shutdown();
+ }
+
+ [Test]
+ public void ServiceIsRunning()
+ {
+ serviceImpl.SetStatus("", "", HealthCheckResponse.Types.ServingStatus.SERVING);
+
+ var response = client.Check(HealthCheckRequest.CreateBuilder().SetHost("").SetService("").Build());
+ Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, response.Status);
+ }
+
+ [Test]
+ public void ServiceDoesntExist()
+ {
+ // TODO(jtattermusch): currently, this returns wrong status code, because we don't enable sending arbitrary status code from
+ // server handlers yet.
+ Assert.Throws(typeof(RpcException), () => client.Check(HealthCheckRequest.CreateBuilder().SetHost("").SetService("nonexistent.service").Build()));
+ }
+
+ // TODO(jtattermusch): add test with timeout once timeouts are supported
+ }
+} \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs
new file mode 100644
index 0000000000..9b7c4f2140
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs
@@ -0,0 +1,107 @@
+#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 System.Text;
+using System.Threading.Tasks;
+
+using Grpc.Core;
+using Grpc.Health.V1Alpha;
+using NUnit.Framework;
+
+namespace Grpc.HealthCheck.Tests
+{
+ /// <summary>
+ /// Tests for HealthCheckServiceImpl
+ /// </summary>
+ public class HealthServiceImplTest
+ {
+ [Test]
+ public void SetStatus()
+ {
+ var impl = new HealthServiceImpl();
+ impl.SetStatus("", "", HealthCheckResponse.Types.ServingStatus.SERVING);
+ Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, GetStatusHelper(impl, "", ""));
+
+ impl.SetStatus("", "", HealthCheckResponse.Types.ServingStatus.NOT_SERVING);
+ Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.NOT_SERVING, GetStatusHelper(impl, "", ""));
+
+ impl.SetStatus("virtual-host", "", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
+ Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.UNKNOWN, GetStatusHelper(impl, "virtual-host", ""));
+
+ impl.SetStatus("virtual-host", "grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.SERVING);
+ Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, GetStatusHelper(impl, "virtual-host", "grpc.test.TestService"));
+ }
+
+ [Test]
+ public void ClearStatus()
+ {
+ var impl = new HealthServiceImpl();
+ impl.SetStatus("", "", HealthCheckResponse.Types.ServingStatus.SERVING);
+ impl.SetStatus("virtual-host", "", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
+
+ impl.ClearStatus("", "");
+
+ Assert.Throws(Is.TypeOf(typeof(RpcException)).And.Property("Status").Property("StatusCode").EqualTo(StatusCode.NotFound), () => GetStatusHelper(impl, "", ""));
+ Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.UNKNOWN, GetStatusHelper(impl, "virtual-host", ""));
+ }
+
+ [Test]
+ public void ClearAll()
+ {
+ var impl = new HealthServiceImpl();
+ impl.SetStatus("", "", HealthCheckResponse.Types.ServingStatus.SERVING);
+ impl.SetStatus("virtual-host", "", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
+
+ impl.ClearAll();
+ Assert.Throws(typeof(RpcException), () => GetStatusHelper(impl, "", ""));
+ Assert.Throws(typeof(RpcException), () => GetStatusHelper(impl, "virtual-host", ""));
+ }
+
+ [Test]
+ public void NullsRejected()
+ {
+ var impl = new HealthServiceImpl();
+ Assert.Throws(typeof(NullReferenceException), () => impl.SetStatus(null, "", HealthCheckResponse.Types.ServingStatus.SERVING));
+ Assert.Throws(typeof(NullReferenceException), () => impl.SetStatus("", null, HealthCheckResponse.Types.ServingStatus.SERVING));
+
+ Assert.Throws(typeof(NullReferenceException), () => impl.ClearStatus(null, ""));
+ Assert.Throws(typeof(NullReferenceException), () => impl.ClearStatus("", null));
+ }
+
+ private static HealthCheckResponse.Types.ServingStatus GetStatusHelper(HealthServiceImpl impl, string host, string service)
+ {
+ return impl.Check(null, HealthCheckRequest.CreateBuilder().SetHost(host).SetService(service).Build()).Result.Status;
+ }
+ }
+}
diff --git a/src/csharp/Grpc.HealthCheck.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.HealthCheck.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..d5660305be
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Grpc.HealthCheck.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
diff --git a/src/csharp/Grpc.HealthCheck.Tests/packages.config b/src/csharp/Grpc.HealthCheck.Tests/packages.config
new file mode 100644
index 0000000000..050c4eaed6
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck.Tests/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Google.ProtocolBuffers" version="2.4.1.555" targetFramework="net45" />
+ <package id="NUnit" version="2.6.4" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck/.gitignore b/src/csharp/Grpc.HealthCheck/.gitignore
new file mode 100644
index 0000000000..1746e3269e
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/.gitignore
@@ -0,0 +1,2 @@
+bin
+obj
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
new file mode 100644
index 0000000000..4ebb6446dd
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{AA5E328A-8835-49D7-98ED-C29F2B3049F0}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Grpc.HealthCheck</RootNamespace>
+ <AssemblyName>Grpc.HealthCheck</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <DocumentationFile>bin\$(Configuration)\Grpc.HealthCheck.Xml</DocumentationFile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Google.ProtocolBuffers">
+ <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.ProtocolBuffers.Serialization">
+ <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Interactive.Async">
+ <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
+ <Compile Include="HealthServiceImpl.cs" />
+ <Compile Include="Health.cs" />
+ <Compile Include="HealthGrpc.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Grpc.HealthCheck.nuspec" />
+ <None Include="packages.config" />
+ <None Include="proto\health.proto" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
+ <Project>{ccc4440e-49f7-4790-b0af-feabb0837ae7}</Project>
+ <Name>Grpc.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
new file mode 100644
index 0000000000..ca35b36805
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<package>
+ <metadata>
+ <id>Grpc.HealthCheck</id>
+ <title>gRPC C# Healthchecking</title>
+ <summary>Implementation of gRPC health service</summary>
+ <description>Example implementation of grpc.health.v1alpha service that can be used for health-checking.</description>
+ <version>$version$</version>
+ <authors>Google Inc.</authors>
+ <owners>grpc-packages</owners>
+ <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
+ <projectUrl>https://github.com/grpc/grpc</projectUrl>
+ <requireLicenseAcceptance>false</requireLicenseAcceptance>
+ <copyright>Copyright 2015, Google Inc.</copyright>
+ <tags>gRPC health check</tags>
+ <dependencies>
+ <dependency id="Google.ProtocolBuffers" version="2.4.1.555" />
+ <dependency id="Grpc.Core" version="$version$" />
+ <dependency id="Ix-Async" version="1.2.3" />
+ </dependencies>
+ </metadata>
+ <files>
+ <file src="bin/Release/Grpc.HealthCheck.dll" target="lib/net45" />
+ <file src="bin/Release/Grpc.HealthCheck.pdb" target="lib/net45" />
+ <file src="bin/Release/Grpc.HealthCheck.xml" target="lib/net45" />
+ <file src="**\*.cs" target="src" />
+ </files>
+</package>
diff --git a/src/csharp/Grpc.HealthCheck/Health.cs b/src/csharp/Grpc.HealthCheck/Health.cs
new file mode 100644
index 0000000000..361382d4bd
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/Health.cs
@@ -0,0 +1,687 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: health.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.ProtocolBuffers;
+using pbc = global::Google.ProtocolBuffers.Collections;
+using pbd = global::Google.ProtocolBuffers.Descriptors;
+using scg = global::System.Collections.Generic;
+namespace Grpc.Health.V1Alpha {
+
+ namespace Proto {
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class Health {
+
+ #region Extension registration
+ public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
+ }
+ #endregion
+ #region Static variables
+ internal static pbd::MessageDescriptor internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckRequest.Builder> internal__static_grpc_health_v1alpha_HealthCheckRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckResponse, global::Grpc.Health.V1Alpha.HealthCheckResponse.Builder> internal__static_grpc_health_v1alpha_HealthCheckResponse__FieldAccessorTable;
+ #endregion
+ #region Descriptor
+ public static pbd::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbd::FileDescriptor descriptor;
+
+ static Health() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "CgxoZWFsdGgucHJvdG8SE2dycGMuaGVhbHRoLnYxYWxwaGEiMwoSSGVhbHRo",
+ "Q2hlY2tSZXF1ZXN0EgwKBGhvc3QYASABKAkSDwoHc2VydmljZRgCIAEoCSKZ",
+ "AQoTSGVhbHRoQ2hlY2tSZXNwb25zZRJGCgZzdGF0dXMYASABKA4yNi5ncnBj",
+ "LmhlYWx0aC52MWFscGhhLkhlYWx0aENoZWNrUmVzcG9uc2UuU2VydmluZ1N0",
+ "YXR1cyI6Cg1TZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5H",
+ "EAESDwoLTk9UX1NFUlZJTkcQAjJkCgZIZWFsdGgSWgoFQ2hlY2sSJy5ncnBj",
+ "LmhlYWx0aC52MWFscGhhLkhlYWx0aENoZWNrUmVxdWVzdBooLmdycGMuaGVh",
+ "bHRoLnYxYWxwaGEuSGVhbHRoQ2hlY2tSZXNwb25zZUIWqgITR3JwYy5IZWFs",
+ "dGguVjFBbHBoYQ=="));
+ pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
+ descriptor = root;
+ internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor = Descriptor.MessageTypes[0];
+ internal__static_grpc_health_v1alpha_HealthCheckRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckRequest.Builder>(internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor,
+ new string[] { "Host", "Service", });
+ internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor = Descriptor.MessageTypes[1];
+ internal__static_grpc_health_v1alpha_HealthCheckResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckResponse, global::Grpc.Health.V1Alpha.HealthCheckResponse.Builder>(internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor,
+ new string[] { "Status", });
+ pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
+ RegisterAllExtensions(registry);
+ return registry;
+ };
+ pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+ new pbd::FileDescriptor[] {
+ }, assigner);
+ }
+ #endregion
+
+ }
+ }
+ #region Messages
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class HealthCheckRequest : pb::GeneratedMessage<HealthCheckRequest, HealthCheckRequest.Builder> {
+ private HealthCheckRequest() { }
+ private static readonly HealthCheckRequest defaultInstance = new HealthCheckRequest().MakeReadOnly();
+ private static readonly string[] _healthCheckRequestFieldNames = new string[] { "host", "service" };
+ private static readonly uint[] _healthCheckRequestFieldTags = new uint[] { 10, 18 };
+ public static HealthCheckRequest DefaultInstance {
+ get { return defaultInstance; }
+ }
+
+ public override HealthCheckRequest DefaultInstanceForType {
+ get { return DefaultInstance; }
+ }
+
+ protected override HealthCheckRequest ThisMessage {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor {
+ get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable<HealthCheckRequest, HealthCheckRequest.Builder> InternalFieldAccessors {
+ get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckRequest__FieldAccessorTable; }
+ }
+
+ public const int HostFieldNumber = 1;
+ private bool hasHost;
+ private string host_ = "";
+ public bool HasHost {
+ get { return hasHost; }
+ }
+ public string Host {
+ get { return host_; }
+ }
+
+ public const int ServiceFieldNumber = 2;
+ private bool hasService;
+ private string service_ = "";
+ public bool HasService {
+ get { return hasService; }
+ }
+ public string Service {
+ get { return service_; }
+ }
+
+ public override bool IsInitialized {
+ get {
+ return true;
+ }
+ }
+
+ public override void WriteTo(pb::ICodedOutputStream output) {
+ CalcSerializedSize();
+ string[] field_names = _healthCheckRequestFieldNames;
+ if (hasHost) {
+ output.WriteString(1, field_names[0], Host);
+ }
+ if (hasService) {
+ output.WriteString(2, field_names[1], Service);
+ }
+ UnknownFields.WriteTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public override int SerializedSize {
+ get {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+ return CalcSerializedSize();
+ }
+ }
+
+ private int CalcSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasHost) {
+ size += pb::CodedOutputStream.ComputeStringSize(1, Host);
+ }
+ if (hasService) {
+ size += pb::CodedOutputStream.ComputeStringSize(2, Service);
+ }
+ size += UnknownFields.SerializedSize;
+ memoizedSerializedSize = size;
+ return size;
+ }
+ public static HealthCheckRequest ParseFrom(pb::ByteString data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(byte[] data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(global::System.IO.Stream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseDelimitedFrom(global::System.IO.Stream input) {
+ return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+ }
+ public static HealthCheckRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(pb::ICodedInputStream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ private HealthCheckRequest MakeReadOnly() {
+ return this;
+ }
+
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder ToBuilder() { return CreateBuilder(this); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(HealthCheckRequest prototype) {
+ return new Builder(prototype);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Builder : pb::GeneratedBuilder<HealthCheckRequest, Builder> {
+ protected override Builder ThisBuilder {
+ get { return this; }
+ }
+ public Builder() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ }
+ internal Builder(HealthCheckRequest cloneFrom) {
+ result = cloneFrom;
+ resultIsReadOnly = true;
+ }
+
+ private bool resultIsReadOnly;
+ private HealthCheckRequest result;
+
+ private HealthCheckRequest PrepareBuilder() {
+ if (resultIsReadOnly) {
+ HealthCheckRequest original = result;
+ result = new HealthCheckRequest();
+ resultIsReadOnly = false;
+ MergeFrom(original);
+ }
+ return result;
+ }
+
+ public override bool IsInitialized {
+ get { return result.IsInitialized; }
+ }
+
+ protected override HealthCheckRequest MessageBeingBuilt {
+ get { return PrepareBuilder(); }
+ }
+
+ public override Builder Clear() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ return this;
+ }
+
+ public override Builder Clone() {
+ if (resultIsReadOnly) {
+ return new Builder(result);
+ } else {
+ return new Builder().MergeFrom(result);
+ }
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType {
+ get { return global::Grpc.Health.V1Alpha.HealthCheckRequest.Descriptor; }
+ }
+
+ public override HealthCheckRequest DefaultInstanceForType {
+ get { return global::Grpc.Health.V1Alpha.HealthCheckRequest.DefaultInstance; }
+ }
+
+ public override HealthCheckRequest BuildPartial() {
+ if (resultIsReadOnly) {
+ return result;
+ }
+ resultIsReadOnly = true;
+ return result.MakeReadOnly();
+ }
+
+ public override Builder MergeFrom(pb::IMessage other) {
+ if (other is HealthCheckRequest) {
+ return MergeFrom((HealthCheckRequest) other);
+ } else {
+ base.MergeFrom(other);
+ return this;
+ }
+ }
+
+ public override Builder MergeFrom(HealthCheckRequest other) {
+ if (other == global::Grpc.Health.V1Alpha.HealthCheckRequest.DefaultInstance) return this;
+ PrepareBuilder();
+ if (other.HasHost) {
+ Host = other.Host;
+ }
+ if (other.HasService) {
+ Service = other.Service;
+ }
+ this.MergeUnknownFields(other.UnknownFields);
+ return this;
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input) {
+ return MergeFrom(input, pb::ExtensionRegistry.Empty);
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ PrepareBuilder();
+ pb::UnknownFieldSet.Builder unknownFields = null;
+ uint tag;
+ string field_name;
+ while (input.ReadTag(out tag, out field_name)) {
+ if(tag == 0 && field_name != null) {
+ int field_ordinal = global::System.Array.BinarySearch(_healthCheckRequestFieldNames, field_name, global::System.StringComparer.Ordinal);
+ if(field_ordinal >= 0)
+ tag = _healthCheckRequestFieldTags[field_ordinal];
+ else {
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ continue;
+ }
+ }
+ switch (tag) {
+ case 0: {
+ throw pb::InvalidProtocolBufferException.InvalidTag();
+ }
+ default: {
+ if (pb::WireFormat.IsEndGroupTag(tag)) {
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ break;
+ }
+ case 10: {
+ result.hasHost = input.ReadString(ref result.host_);
+ break;
+ }
+ case 18: {
+ result.hasService = input.ReadString(ref result.service_);
+ break;
+ }
+ }
+ }
+
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+
+
+ public bool HasHost {
+ get { return result.hasHost; }
+ }
+ public string Host {
+ get { return result.Host; }
+ set { SetHost(value); }
+ }
+ public Builder SetHost(string value) {
+ pb::ThrowHelper.ThrowIfNull(value, "value");
+ PrepareBuilder();
+ result.hasHost = true;
+ result.host_ = value;
+ return this;
+ }
+ public Builder ClearHost() {
+ PrepareBuilder();
+ result.hasHost = false;
+ result.host_ = "";
+ return this;
+ }
+
+ public bool HasService {
+ get { return result.hasService; }
+ }
+ public string Service {
+ get { return result.Service; }
+ set { SetService(value); }
+ }
+ public Builder SetService(string value) {
+ pb::ThrowHelper.ThrowIfNull(value, "value");
+ PrepareBuilder();
+ result.hasService = true;
+ result.service_ = value;
+ return this;
+ }
+ public Builder ClearService() {
+ PrepareBuilder();
+ result.hasService = false;
+ result.service_ = "";
+ return this;
+ }
+ }
+ static HealthCheckRequest() {
+ object.ReferenceEquals(global::Grpc.Health.V1Alpha.Proto.Health.Descriptor, null);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class HealthCheckResponse : pb::GeneratedMessage<HealthCheckResponse, HealthCheckResponse.Builder> {
+ private HealthCheckResponse() { }
+ private static readonly HealthCheckResponse defaultInstance = new HealthCheckResponse().MakeReadOnly();
+ private static readonly string[] _healthCheckResponseFieldNames = new string[] { "status" };
+ private static readonly uint[] _healthCheckResponseFieldTags = new uint[] { 8 };
+ public static HealthCheckResponse DefaultInstance {
+ get { return defaultInstance; }
+ }
+
+ public override HealthCheckResponse DefaultInstanceForType {
+ get { return DefaultInstance; }
+ }
+
+ protected override HealthCheckResponse ThisMessage {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor {
+ get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable<HealthCheckResponse, HealthCheckResponse.Builder> InternalFieldAccessors {
+ get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckResponse__FieldAccessorTable; }
+ }
+
+ #region Nested types
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class Types {
+ public enum ServingStatus {
+ UNKNOWN = 0,
+ SERVING = 1,
+ NOT_SERVING = 2,
+ }
+
+ }
+ #endregion
+
+ public const int StatusFieldNumber = 1;
+ private bool hasStatus;
+ private global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus status_ = global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN;
+ public bool HasStatus {
+ get { return hasStatus; }
+ }
+ public global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus Status {
+ get { return status_; }
+ }
+
+ public override bool IsInitialized {
+ get {
+ return true;
+ }
+ }
+
+ public override void WriteTo(pb::ICodedOutputStream output) {
+ CalcSerializedSize();
+ string[] field_names = _healthCheckResponseFieldNames;
+ if (hasStatus) {
+ output.WriteEnum(1, field_names[0], (int) Status, Status);
+ }
+ UnknownFields.WriteTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public override int SerializedSize {
+ get {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+ return CalcSerializedSize();
+ }
+ }
+
+ private int CalcSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasStatus) {
+ size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Status);
+ }
+ size += UnknownFields.SerializedSize;
+ memoizedSerializedSize = size;
+ return size;
+ }
+ public static HealthCheckResponse ParseFrom(pb::ByteString data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(byte[] data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(global::System.IO.Stream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseDelimitedFrom(global::System.IO.Stream input) {
+ return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+ }
+ public static HealthCheckResponse ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(pb::ICodedInputStream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ private HealthCheckResponse MakeReadOnly() {
+ return this;
+ }
+
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder ToBuilder() { return CreateBuilder(this); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(HealthCheckResponse prototype) {
+ return new Builder(prototype);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Builder : pb::GeneratedBuilder<HealthCheckResponse, Builder> {
+ protected override Builder ThisBuilder {
+ get { return this; }
+ }
+ public Builder() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ }
+ internal Builder(HealthCheckResponse cloneFrom) {
+ result = cloneFrom;
+ resultIsReadOnly = true;
+ }
+
+ private bool resultIsReadOnly;
+ private HealthCheckResponse result;
+
+ private HealthCheckResponse PrepareBuilder() {
+ if (resultIsReadOnly) {
+ HealthCheckResponse original = result;
+ result = new HealthCheckResponse();
+ resultIsReadOnly = false;
+ MergeFrom(original);
+ }
+ return result;
+ }
+
+ public override bool IsInitialized {
+ get { return result.IsInitialized; }
+ }
+
+ protected override HealthCheckResponse MessageBeingBuilt {
+ get { return PrepareBuilder(); }
+ }
+
+ public override Builder Clear() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ return this;
+ }
+
+ public override Builder Clone() {
+ if (resultIsReadOnly) {
+ return new Builder(result);
+ } else {
+ return new Builder().MergeFrom(result);
+ }
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType {
+ get { return global::Grpc.Health.V1Alpha.HealthCheckResponse.Descriptor; }
+ }
+
+ public override HealthCheckResponse DefaultInstanceForType {
+ get { return global::Grpc.Health.V1Alpha.HealthCheckResponse.DefaultInstance; }
+ }
+
+ public override HealthCheckResponse BuildPartial() {
+ if (resultIsReadOnly) {
+ return result;
+ }
+ resultIsReadOnly = true;
+ return result.MakeReadOnly();
+ }
+
+ public override Builder MergeFrom(pb::IMessage other) {
+ if (other is HealthCheckResponse) {
+ return MergeFrom((HealthCheckResponse) other);
+ } else {
+ base.MergeFrom(other);
+ return this;
+ }
+ }
+
+ public override Builder MergeFrom(HealthCheckResponse other) {
+ if (other == global::Grpc.Health.V1Alpha.HealthCheckResponse.DefaultInstance) return this;
+ PrepareBuilder();
+ if (other.HasStatus) {
+ Status = other.Status;
+ }
+ this.MergeUnknownFields(other.UnknownFields);
+ return this;
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input) {
+ return MergeFrom(input, pb::ExtensionRegistry.Empty);
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ PrepareBuilder();
+ pb::UnknownFieldSet.Builder unknownFields = null;
+ uint tag;
+ string field_name;
+ while (input.ReadTag(out tag, out field_name)) {
+ if(tag == 0 && field_name != null) {
+ int field_ordinal = global::System.Array.BinarySearch(_healthCheckResponseFieldNames, field_name, global::System.StringComparer.Ordinal);
+ if(field_ordinal >= 0)
+ tag = _healthCheckResponseFieldTags[field_ordinal];
+ else {
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ continue;
+ }
+ }
+ switch (tag) {
+ case 0: {
+ throw pb::InvalidProtocolBufferException.InvalidTag();
+ }
+ default: {
+ if (pb::WireFormat.IsEndGroupTag(tag)) {
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ break;
+ }
+ case 8: {
+ object unknown;
+ if(input.ReadEnum(ref result.status_, out unknown)) {
+ result.hasStatus = true;
+ } else if(unknown is int) {
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ unknownFields.MergeVarintField(1, (ulong)(int)unknown);
+ }
+ break;
+ }
+ }
+ }
+
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+
+
+ public bool HasStatus {
+ get { return result.hasStatus; }
+ }
+ public global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus Status {
+ get { return result.Status; }
+ set { SetStatus(value); }
+ }
+ public Builder SetStatus(global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus value) {
+ PrepareBuilder();
+ result.hasStatus = true;
+ result.status_ = value;
+ return this;
+ }
+ public Builder ClearStatus() {
+ PrepareBuilder();
+ result.hasStatus = false;
+ result.status_ = global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN;
+ return this;
+ }
+ }
+ static HealthCheckResponse() {
+ object.ReferenceEquals(global::Grpc.Health.V1Alpha.Proto.Health.Descriptor, null);
+ }
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
new file mode 100644
index 0000000000..3aebdcb557
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
@@ -0,0 +1,70 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: health.proto
+#region Designer generated code
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+
+namespace Grpc.Health.V1Alpha {
+ public static class Health
+ {
+ static readonly string __ServiceName = "grpc.health.v1alpha.Health";
+
+ static readonly Marshaller<global::Grpc.Health.V1Alpha.HealthCheckRequest> __Marshaller_HealthCheckRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Health.V1Alpha.HealthCheckRequest.ParseFrom);
+ static readonly Marshaller<global::Grpc.Health.V1Alpha.HealthCheckResponse> __Marshaller_HealthCheckResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Health.V1Alpha.HealthCheckResponse.ParseFrom);
+
+ static readonly Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse> __Method_Check = new Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse>(
+ MethodType.Unary,
+ "Check",
+ __Marshaller_HealthCheckRequest,
+ __Marshaller_HealthCheckResponse);
+
+ // client interface
+ public interface IHealthClient
+ {
+ global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ Task<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ }
+
+ // server-side interface
+ public interface IHealth
+ {
+ Task<global::Grpc.Health.V1Alpha.HealthCheckResponse> Check(ServerCallContext context, global::Grpc.Health.V1Alpha.HealthCheckRequest request);
+ }
+
+ // client stub
+ public class HealthClient : ClientBase, IHealthClient
+ {
+ public HealthClient(Channel channel) : base(channel)
+ {
+ }
+ public global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var call = CreateCall(__ServiceName, __Method_Check, headers);
+ return Calls.BlockingUnaryCall(call, request, cancellationToken);
+ }
+ public Task<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var call = CreateCall(__ServiceName, __Method_Check, headers);
+ return Calls.AsyncUnaryCall(call, request, cancellationToken);
+ }
+ }
+
+ // creates service definition that can be registered with a server
+ public static ServerServiceDefinition BindService(IHealth serviceImpl)
+ {
+ return ServerServiceDefinition.CreateBuilder(__ServiceName)
+ .AddMethod(__Method_Check, serviceImpl.Check).Build();
+ }
+
+ // creates a new client
+ public static HealthClient NewClient(Channel channel)
+ {
+ return new HealthClient(channel);
+ }
+
+ }
+}
+#endregion
diff --git a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
new file mode 100644
index 0000000000..db3a2a0942
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
@@ -0,0 +1,132 @@
+#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 System.Text;
+using System.Threading.Tasks;
+
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Health.V1Alpha;
+
+namespace Grpc.HealthCheck
+{
+ /// <summary>
+ /// Implementation of a simple Health service. Useful for health checking.
+ ///
+ /// Registering service with a server:
+ /// <code>
+ /// var serviceImpl = new HealthServiceImpl();
+ /// server = new Server();
+ /// server.AddServiceDefinition(Grpc.Health.V1Alpha.Health.BindService(serviceImpl));
+ /// </code>
+ /// </summary>
+ public class HealthServiceImpl : Grpc.Health.V1Alpha.Health.IHealth
+ {
+ private readonly object myLock = new object();
+ private readonly Dictionary<Key, HealthCheckResponse.Types.ServingStatus> statusMap =
+ new Dictionary<Key, HealthCheckResponse.Types.ServingStatus>();
+
+ /// <summary>
+ /// Sets the health status for given host and service.
+ /// </summary>
+ /// <param name="host">The host. Cannot be null.</param>
+ /// <param name="service">The service. Cannot be null.</param>
+ /// <param name="status">the health status</param>
+ public void SetStatus(string host, string service, HealthCheckResponse.Types.ServingStatus status)
+ {
+ lock (myLock)
+ {
+ statusMap[CreateKey(host, service)] = status;
+ }
+ }
+
+ /// <summary>
+ /// Clears health status for given host and service.
+ /// </summary>
+ /// <param name="host">The host. Cannot be null.</param>
+ /// <param name="service">The service. Cannot be null.</param>
+ public void ClearStatus(string host, string service)
+ {
+ lock (myLock)
+ {
+ statusMap.Remove(CreateKey(host, service));
+ }
+ }
+
+ /// <summary>
+ /// Clears statuses for all hosts and services.
+ /// </summary>
+ public void ClearAll()
+ {
+ lock (myLock)
+ {
+ statusMap.Clear();
+ }
+ }
+
+ public Task<HealthCheckResponse> Check(ServerCallContext context, HealthCheckRequest request)
+ {
+ lock (myLock)
+ {
+ var host = request.HasHost ? request.Host : "";
+ var service = request.HasService ? request.Service : "";
+
+ HealthCheckResponse.Types.ServingStatus status;
+ if (!statusMap.TryGetValue(CreateKey(host, service), out status))
+ {
+ // TODO(jtattermusch): returning specific status from server handler is not supported yet.
+ throw new RpcException(new Status(StatusCode.NotFound, ""));
+ }
+ return Task.FromResult(HealthCheckResponse.CreateBuilder().SetStatus(status).Build());
+ }
+ }
+
+ private static Key CreateKey(string host, string service)
+ {
+ return new Key(host, service);
+ }
+
+ private struct Key
+ {
+ public Key(string host, string service)
+ {
+ this.Host = Preconditions.CheckNotNull(host);
+ this.Service = Preconditions.CheckNotNull(service);
+ }
+
+ readonly string Host;
+ readonly string Service;
+ }
+ }
+}
diff --git a/src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs b/src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..41a54a98bc
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Grpc.HealthCheck")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")] \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck/packages.config b/src/csharp/Grpc.HealthCheck/packages.config
new file mode 100644
index 0000000000..094a30981e
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Google.ProtocolBuffers" version="2.4.1.555" targetFramework="net45" />
+ <package id="Ix-Async" version="1.2.3" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/Stub/StubConfiguration.cs b/src/csharp/Grpc.HealthCheck/proto/health.proto
index 5bcb5b40d2..08df7e104e 100644
--- a/src/csharp/Grpc.Core/Stub/StubConfiguration.cs
+++ b/src/csharp/Grpc.HealthCheck/proto/health.proto
@@ -1,5 +1,3 @@
-#region Copyright notice and license
-
// Copyright 2015, Google Inc.
// All rights reserved.
//
@@ -29,36 +27,26 @@
// (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 Grpc.Core.Internal;
-using Grpc.Core.Utils;
-
-namespace Grpc.Core
-{
- public delegate void HeaderInterceptorDelegate(Metadata.Builder headerBuilder);
+// TODO(jtattermusch): switch to proto3 once C# supports that.
+syntax = "proto2";
- public class StubConfiguration
- {
- /// <summary>
- /// The default stub configuration.
- /// </summary>
- public static readonly StubConfiguration Default = new StubConfiguration((headerBuilder) => { });
+package grpc.health.v1alpha;
+option csharp_namespace = "Grpc.Health.V1Alpha";
- readonly HeaderInterceptorDelegate headerInterceptor;
-
- public StubConfiguration(HeaderInterceptorDelegate headerInterceptor)
- {
- this.headerInterceptor = Preconditions.CheckNotNull(headerInterceptor);
- }
+message HealthCheckRequest {
+ optional string host = 1;
+ optional string service = 2;
+}
- public HeaderInterceptorDelegate HeaderInterceptor
- {
- get
- {
- return headerInterceptor;
- }
- }
- }
+message HealthCheckResponse {
+ enum ServingStatus {
+ UNKNOWN = 0;
+ SERVING = 1;
+ NOT_SERVING = 2;
+ }
+ optional ServingStatus status = 1;
}
+
+service Health {
+ rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
+} \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
index df05c535e2..328acb5b47 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
@@ -36,6 +36,9 @@
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs
index 26c0dcc3b9..f51f2796c4 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs
@@ -9,4 +9,3 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.5.*")]
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
index 235897c888..ae184c1dc7 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
@@ -36,6 +36,9 @@
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs
index 2d518d7b72..f68d9a3ddc 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs
@@ -9,4 +9,3 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.5.*")]
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index b3a0a2917b..af4a75a034 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -54,6 +54,10 @@
<Reference Include="Google.ProtocolBuffers">
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath>
</Reference>
+ <Reference Include="System.Collections.Immutable, Version=1.1.36.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
+ </Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
@@ -69,11 +73,11 @@
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
- <Reference Include="System.Collections.Immutable">
- <HintPath>..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
- </Reference>
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Empty.cs" />
<Compile Include="Messages.cs" />
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index f0be522bc6..05e732dbd4 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -102,8 +102,6 @@ namespace Grpc.IntegrationTesting
private void Run()
{
- GrpcEnvironment.Initialize();
-
Credentials credentials = null;
if (options.useTls)
{
@@ -121,7 +119,7 @@ namespace Grpc.IntegrationTesting
using (Channel channel = new Channel(options.serverHost, options.serverPort.Value, credentials, channelOptions))
{
- var stubConfig = StubConfiguration.Default;
+ TestService.TestServiceClient client = new TestService.TestServiceClient(channel);
if (options.testCase == "service_account_creds" || options.testCase == "compute_engine_creds")
{
var credential = GoogleCredential.GetApplicationDefault();
@@ -129,13 +127,11 @@ namespace Grpc.IntegrationTesting
{
credential = credential.CreateScoped(new[] { AuthScope });
}
- stubConfig = new StubConfiguration(OAuth2InterceptorFactory.Create(credential));
+ client.HeaderInterceptor = OAuth2InterceptorFactory.Create(credential);
}
- TestService.ITestServiceClient client = new TestService.TestServiceClient(channel, stubConfig);
RunTestCase(options.testCase, client);
}
-
GrpcEnvironment.Shutdown();
}
@@ -366,7 +362,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("running cancel_after_begin");
var cts = new CancellationTokenSource();
- using (var call = client.StreamingInputCall(cts.Token))
+ using (var call = client.StreamingInputCall(cancellationToken: cts.Token))
{
// TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it.
await Task.Delay(1000);
@@ -393,7 +389,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("running cancel_after_first_response");
var cts = new CancellationTokenSource();
- using (var call = client.FullDuplexCall(cts.Token))
+ using (var call = client.FullDuplexCall(cancellationToken: cts.Token))
{
await call.RequestStream.WriteAsync(StreamingOutputCallRequest.CreateBuilder()
.SetResponseType(PayloadType.COMPRESSABLE)
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
index 1a733450c1..f306289cfb 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
@@ -55,8 +55,6 @@ namespace Grpc.IntegrationTesting
[TestFixtureSetUp]
public void Init()
{
- GrpcEnvironment.Initialize();
-
server = new Server();
server.AddServiceDefinition(TestService.BindService(new TestServiceImpl()));
int port = server.AddListeningPort(host, Server.PickUnusedPort, TestCredentials.CreateTestServerCredentials());
@@ -67,14 +65,13 @@ namespace Grpc.IntegrationTesting
new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride)
};
channel = new Channel(host, port, TestCredentials.CreateTestClientCredentials(true), options);
- client = TestService.NewStub(channel);
+ client = TestService.NewClient(channel);
}
[TestFixtureTearDown]
public void Cleanup()
{
channel.Dispose();
-
server.ShutdownAsync().Wait();
GrpcEnvironment.Shutdown();
}
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
index 87c3cbe1d4..9475e66c40 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
@@ -88,8 +88,6 @@ namespace Grpc.IntegrationTesting
private void Run()
{
- GrpcEnvironment.Initialize();
-
var server = new Server();
server.AddServiceDefinition(TestService.BindService(new TestServiceImpl()));
diff --git a/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs
index f73575e8bd..1beb0bbb41 100644
--- a/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs
@@ -9,4 +9,3 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.5.*")]
diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
index ee077f9f56..96d9b23717 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
@@ -56,17 +56,17 @@ namespace grpc.testing {
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
- // client-side stub interface
+ // client interface
public interface ITestServiceClient
{
- global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, CancellationToken token = default(CancellationToken));
- Task<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, CancellationToken token = default(CancellationToken));
- global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, CancellationToken token = default(CancellationToken));
- Task<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, CancellationToken token = default(CancellationToken));
- AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, CancellationToken token = default(CancellationToken));
- AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken));
- AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(CancellationToken token = default(CancellationToken));
- AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(CancellationToken token = default(CancellationToken));
+ global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ Task<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ Task<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
}
// server-side interface
@@ -81,53 +81,50 @@ namespace grpc.testing {
}
// client stub
- public class TestServiceClient : AbstractStub<TestServiceClient, StubConfiguration>, ITestServiceClient
+ public class TestServiceClient : ClientBase, ITestServiceClient
{
- public TestServiceClient(Channel channel) : this(channel, StubConfiguration.Default)
+ public TestServiceClient(Channel channel) : base(channel)
{
}
- public TestServiceClient(Channel channel, StubConfiguration config) : base(channel, config)
+ public global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
+ var call = CreateCall(__ServiceName, __Method_EmptyCall, headers);
+ return Calls.BlockingUnaryCall(call, request, cancellationToken);
}
- public global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, CancellationToken token = default(CancellationToken))
+ public Task<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_EmptyCall);
- return Calls.BlockingUnaryCall(call, request, token);
+ var call = CreateCall(__ServiceName, __Method_EmptyCall, headers);
+ return Calls.AsyncUnaryCall(call, request, cancellationToken);
}
- public Task<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, CancellationToken token = default(CancellationToken))
+ public global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_EmptyCall);
- return Calls.AsyncUnaryCall(call, request, token);
+ var call = CreateCall(__ServiceName, __Method_UnaryCall, headers);
+ return Calls.BlockingUnaryCall(call, request, cancellationToken);
}
- public global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, CancellationToken token = default(CancellationToken))
+ public Task<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_UnaryCall);
- return Calls.BlockingUnaryCall(call, request, token);
+ var call = CreateCall(__ServiceName, __Method_UnaryCall, headers);
+ return Calls.AsyncUnaryCall(call, request, cancellationToken);
}
- public Task<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, CancellationToken token = default(CancellationToken))
+ public AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_UnaryCall);
- return Calls.AsyncUnaryCall(call, request, token);
+ var call = CreateCall(__ServiceName, __Method_StreamingOutputCall, headers);
+ return Calls.AsyncServerStreamingCall(call, request, cancellationToken);
}
- public AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, CancellationToken token = default(CancellationToken))
+ public AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_StreamingOutputCall);
- return Calls.AsyncServerStreamingCall(call, request, token);
+ var call = CreateCall(__ServiceName, __Method_StreamingInputCall, headers);
+ return Calls.AsyncClientStreamingCall(call, cancellationToken);
}
- public AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken))
+ public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_StreamingInputCall);
- return Calls.AsyncClientStreamingCall(call, token);
+ var call = CreateCall(__ServiceName, __Method_FullDuplexCall, headers);
+ return Calls.AsyncDuplexStreamingCall(call, cancellationToken);
}
- public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(CancellationToken token = default(CancellationToken))
+ public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_FullDuplexCall);
- return Calls.AsyncDuplexStreamingCall(call, token);
- }
- public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(CancellationToken token = default(CancellationToken))
- {
- var call = CreateCall(__ServiceName, __Method_HalfDuplexCall);
- return Calls.AsyncDuplexStreamingCall(call, token);
+ var call = CreateCall(__ServiceName, __Method_HalfDuplexCall, headers);
+ return Calls.AsyncDuplexStreamingCall(call, cancellationToken);
}
}
@@ -143,17 +140,12 @@ namespace grpc.testing {
.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
}
- // creates a new client stub
- public static ITestServiceClient NewStub(Channel channel)
+ // creates a new client
+ public static TestServiceClient NewClient(Channel channel)
{
return new TestServiceClient(channel);
}
- // creates a new client stub
- public static ITestServiceClient NewStub(Channel channel, StubConfiguration config)
- {
- return new TestServiceClient(channel, config);
- }
}
}
#endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index 291b7b8599..c74ac75d79 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -7,8 +7,8 @@
<package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
- <package id="Microsoft.Bcl.Immutable" version="1.0.34" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.28" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net45" />
<package id="NUnit" version="2.6.4" targetFramework="net45" />
+ <package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Tools.nuspec b/src/csharp/Grpc.Tools.nuspec
index 913d4c8f4b..eabf5dc7db 100644
--- a/src/csharp/Grpc.Tools.nuspec
+++ b/src/csharp/Grpc.Tools.nuspec
@@ -5,13 +5,13 @@
<title>gRPC C# Tools</title>
<summary>Tools for C# implementation of gRPC - an RPC library and framework</summary>
<description>Precompiled Windows binaries for generating protocol buffer messages and gRPC client/server code</description>
- <version>0.5.1</version>
+ <version>$version$</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
- <releaseNotes>protoc.exe - protocol buffer compiler v3.0.0-alpha-3; grpc_csharp_plugin.exe - gRPC C# protoc plugin version 0.5.1</releaseNotes>
+ <releaseNotes>protoc.exe - protocol buffer compiler v3.0.0-alpha-3; grpc_csharp_plugin.exe - gRPC C# protoc plugin version $version$</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
</metadata>
diff --git a/src/csharp/Grpc.nuspec b/src/csharp/Grpc.nuspec
index cf4c74fa2d..7fbd861923 100644
--- a/src/csharp/Grpc.nuspec
+++ b/src/csharp/Grpc.nuspec
@@ -5,17 +5,17 @@
<title>gRPC C#</title>
<summary>C# implementation of gRPC - an RPC library and framework</summary>
<description>C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
- <version>0.5.1</version>
+ <version>$version$</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
- <releaseNotes>Release 0.5.1 of gRPC C#</releaseNotes>
+ <releaseNotes>Release $version$ of gRPC C#</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
<dependencies>
- <dependency id="Grpc.Core" version="0.5.1" />
+ <dependency id="Grpc.Core" version="$version$" />
</dependencies>
</metadata>
<files/>
diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln
index 978739f23a..705e4fb1c2 100644
--- a/src/csharp/Grpc.sln
+++ b/src/csharp/Grpc.sln
@@ -28,57 +28,68 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{B5B871
.nuget\packages.config = .nuget\packages.config
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.HealthCheck", "Grpc.HealthCheck\Grpc.HealthCheck.csproj", "{AA5E328A-8835-49D7-98ED-C29F2B3049F0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.HealthCheck.Tests", "Grpc.HealthCheck.Tests\Grpc.HealthCheck.Tests.csproj", "{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|x86.ActiveCfg = Debug|Any CPU
- {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|x86.Build.0 = Debug|Any CPU
- {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|x86.ActiveCfg = Release|Any CPU
- {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|x86.Build.0 = Release|Any CPU
- {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.ActiveCfg = Debug|Any CPU
- {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.Build.0 = Debug|Any CPU
- {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.ActiveCfg = Release|Any CPU
- {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.Build.0 = Release|Any CPU
- {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|x86.ActiveCfg = Debug|Any CPU
- {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|x86.Build.0 = Debug|Any CPU
- {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|x86.ActiveCfg = Release|Any CPU
- {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|x86.Build.0 = Release|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|x86.ActiveCfg = Debug|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|x86.Build.0 = Debug|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|x86.ActiveCfg = Release|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|x86.Build.0 = Release|Any CPU
- {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.ActiveCfg = Debug|x86
- {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.Build.0 = Debug|x86
- {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.ActiveCfg = Release|x86
- {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.Build.0 = Release|x86
- {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.ActiveCfg = Debug|x86
- {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.Build.0 = Debug|x86
- {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.ActiveCfg = Release|x86
- {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.Build.0 = Release|x86
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|x86.ActiveCfg = Debug|x86
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|x86.Build.0 = Debug|x86
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|x86.ActiveCfg = Release|x86
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|x86.Build.0 = Release|x86
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.ActiveCfg = Debug|x86
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.Build.0 = Debug|x86
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.ActiveCfg = Release|x86
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.Build.0 = Release|x86
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|x86.Build.0 = Debug|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|x86.ActiveCfg = Release|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|x86.Build.0 = Release|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|x86.Build.0 = Debug|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|x86.ActiveCfg = Release|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|x86.Build.0 = Release|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|x86.ActiveCfg = Debug|x86
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|x86.Build.0 = Debug|x86
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.ActiveCfg = Release|x86
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.Build.0 = Release|x86
- {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.ActiveCfg = Debug|x86
- {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.Build.0 = Debug|x86
- {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.ActiveCfg = Release|x86
- {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.Build.0 = Release|x86
+ {AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Debug|x86.Build.0 = Debug|Any CPU
+ {AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|x86.ActiveCfg = Release|Any CPU
+ {AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|x86.Build.0 = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.ActiveCfg = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.Build.0 = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.ActiveCfg = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.Build.0 = Release|Any CPU
+ {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.ActiveCfg = Debug|x86
+ {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.Build.0 = Debug|x86
+ {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.ActiveCfg = Release|x86
+ {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.Build.0 = Release|x86
+ {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.ActiveCfg = Debug|x86
+ {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.Build.0 = Debug|x86
+ {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.ActiveCfg = Release|x86
+ {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.Build.0 = Release|x86
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.Build.0 = Debug|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.ActiveCfg = Release|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.Build.0 = Release|Any CPU
+ {F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|x86.Build.0 = Debug|Any CPU
+ {F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Release|x86.ActiveCfg = Release|Any CPU
+ {F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
- GlobalSection(MonoDevelopProperties) = preSolution
- StartupItem = Grpc.Examples\Grpc.Examples.csproj
- EndGlobalSection
EndGlobal
diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat
index 3412129fb2..c3e5fe8817 100644
--- a/src/csharp/build_packages.bat
+++ b/src/csharp/build_packages.bat
@@ -1,5 +1,9 @@
@rem Builds gRPC NuGet packages
+@rem Current package versions
+set VERSION=0.6.0
+set CORE_VERSION=0.10.0
+
@rem Adjust the location of nuget.exe
set NUGET=C:\nuget\nuget.exe
@@ -10,11 +14,12 @@ endlocal
@call buildall.bat || goto :error
-%NUGET% pack ..\..\vsprojects\nuget_package\grpc.native.csharp_ext.nuspec || goto :error
-%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols || goto :error
-%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols || goto :error
-%NUGET% pack Grpc.Tools.nuspec || goto :error
-%NUGET% pack Grpc.nuspec || goto :error
+%NUGET% pack ..\..\vsprojects\nuget_package\grpc.native.csharp_ext.nuspec -Version %CORE_VERSION% || goto :error
+%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error
+%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% -Properties GrpcNativeCsharpExtVersion=%CORE_VERSION% || goto :error
+%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION% || goto :error
+%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% || goto :error
+%NUGET% pack Grpc.nuspec -Version %VERSION% || goto :error
goto :EOF
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index ec125db78b..a55cc9e247 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -379,7 +379,7 @@ grpcsharp_channel_args_destroy(grpc_channel_args *args) {
/* Timespec */
-GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(void) { return gpr_now(); }
+GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(void) { return gpr_now(GPR_CLOCK_REALTIME); }
GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_inf_future(void) {
return gpr_inf_future;
diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh
index f980787bb7..7c3ba70922 100755
--- a/src/csharp/generate_proto_csharp.sh
+++ b/src/csharp/generate_proto_csharp.sh
@@ -32,12 +32,17 @@
set +e
cd $(dirname $0)
+PROTOC=../../bins/opt/protobuf/protoc
PLUGIN=protoc-gen-grpc=../../bins/opt/grpc_csharp_plugin
EXAMPLES_DIR=Grpc.Examples
INTEROP_DIR=Grpc.IntegrationTesting
+HEALTHCHECK_DIR=Grpc.HealthCheck
-protoc --plugin=$PLUGIN --grpc_out=$EXAMPLES_DIR \
+$PROTOC --plugin=$PLUGIN --grpc_out=$EXAMPLES_DIR \
-I $EXAMPLES_DIR/proto $EXAMPLES_DIR/proto/math.proto
-protoc --plugin=$PLUGIN --grpc_out=$INTEROP_DIR \
+$PROTOC --plugin=$PLUGIN --grpc_out=$INTEROP_DIR \
-I $INTEROP_DIR/proto $INTEROP_DIR/proto/test.proto
+
+$PROTOC --plugin=$PLUGIN --grpc_out=$HEALTHCHECK_DIR \
+ -I $HEALTHCHECK_DIR/proto $HEALTHCHECK_DIR/proto/health.proto
diff --git a/src/node/binding.gyp b/src/node/binding.gyp
index 83f72fabca..6ba233388a 100644
--- a/src/node/binding.gyp
+++ b/src/node/binding.gyp
@@ -10,20 +10,54 @@
'-pthread',
'-pedantic',
'-g',
- '-zdefs'
+ '-zdefs',
'-Werror'
],
'ldflags': [
'-g'
],
- 'link_settings': {
- 'libraries': [
- '-lpthread',
- '-lgrpc',
- '-lgpr'
- ]
- },
"conditions": [
+ ['OS != "win"', {
+ 'variables': {
+ 'pkg_config_grpc': '<!(pkg-config --exists grpc >/dev/null 2>&1 && echo true || echo false)'
+ },
+ 'conditions': [
+ ['pkg_config_grpc == "true"', {
+ 'link_settings': {
+ 'libraries': [
+ '<!@(pkg-config --libs-only-l --static grpc)'
+ ]
+ },
+ 'cflags': [
+ '<!@(pkg-config --cflags grpc)'
+ ],
+ 'libraries': [
+ '<!@(pkg-config --libs-only-L --static grpc)'
+ ],
+ 'ldflags': [
+ '<!@(pkg-config --libs-only-other --static grpc)'
+ ]
+ }, {
+ 'link_settings': {
+ 'libraries': [
+ '-lpthread',
+ '-lgrpc',
+ '-lgpr'
+ ],
+ },
+ 'conditions':[
+ ['OS != "mac"', {
+ 'link_settings': {
+ 'libraries': [
+ '-lrt'
+ ]
+ }
+ }]
+ ]
+ }
+ ]
+ ]
+ }],
['OS == "mac"', {
'xcode_settings': {
'MACOSX_DEPLOYMENT_TARGET': '10.9',
@@ -32,13 +66,6 @@
'-stdlib=libc++'
]
}
- }],
- ['OS != "mac"', {
- 'link_settings': {
- 'libraries': [
- '-lrt'
- ]
- }
}]
],
"target_name": "grpc",
diff --git a/src/node/health_check/health.js b/src/node/health_check/health.js
new file mode 100644
index 0000000000..87e00197fe
--- /dev/null
+++ b/src/node/health_check/health.js
@@ -0,0 +1,70 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+'use strict';
+
+var grpc = require('../');
+
+var _ = require('lodash');
+
+var health_proto = grpc.load(__dirname + '/health.proto');
+
+var HealthClient = health_proto.grpc.health.v1alpha.Health;
+
+function HealthImplementation(statusMap) {
+ this.statusMap = _.clone(statusMap);
+}
+
+HealthImplementation.prototype.setStatus = function(host, service, status) {
+ if (!this.statusMap[host]) {
+ this.statusMap[host] = {};
+ }
+ this.statusMap[host][service] = status;
+};
+
+HealthImplementation.prototype.check = function(call, callback){
+ var host = call.request.host;
+ var service = call.request.service;
+ var status = _.get(this.statusMap, [host, service], null);
+ if (status === null) {
+ callback({code:grpc.status.NOT_FOUND});
+ } else {
+ callback(null, {status: status});
+ }
+};
+
+module.exports = {
+ Client: HealthClient,
+ service: HealthClient.service,
+ Implementation: HealthImplementation
+};
diff --git a/src/node/health_check/health.proto b/src/node/health_check/health.proto
new file mode 100644
index 0000000000..d31df1e0a7
--- /dev/null
+++ b/src/node/health_check/health.proto
@@ -0,0 +1,50 @@
+// 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.
+
+syntax = "proto3";
+
+package grpc.health.v1alpha;
+
+message HealthCheckRequest {
+ string host = 1;
+ string service = 2;
+}
+
+message HealthCheckResponse {
+ enum ServingStatus {
+ UNKNOWN = 0;
+ SERVING = 1;
+ NOT_SERVING = 2;
+ }
+ ServingStatus status = 1;
+}
+
+service Health {
+ rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
+} \ No newline at end of file
diff --git a/src/node/package.json b/src/node/package.json
index 7d4a493af4..1caf158792 100644
--- a/src/node/package.json
+++ b/src/node/package.json
@@ -1,6 +1,6 @@
{
"name": "grpc",
- "version": "0.9.1",
+ "version": "0.10.0",
"author": "Google Inc.",
"description": "gRPC Library for Node",
"homepage": "http://www.grpc.io/",
@@ -27,7 +27,7 @@
"bindings": "^1.2.0",
"lodash": "^3.9.3",
"nan": "^1.5.0",
- "protobufjs": "dcodeIO/ProtoBuf.js"
+ "protobufjs": "^4.0.0"
},
"devDependencies": {
"async": "^0.9.0",
diff --git a/src/node/src/server.js b/src/node/src/server.js
index c6cf9e7eb8..00be400e61 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -55,7 +55,7 @@ var EventEmitter = require('events').EventEmitter;
*/
function handleError(call, error) {
var status = {
- code: grpc.status.INTERNAL,
+ code: grpc.status.UNKNOWN,
details: 'Unknown Error',
metadata: {}
};
@@ -142,12 +142,12 @@ function setUpWritable(stream, serialize) {
stream.on('finish', sendStatus);
/**
* Set the pending status to a given error status. If the error does not have
- * code or details properties, the code will be set to grpc.status.INTERNAL
+ * code or details properties, the code will be set to grpc.status.UNKNOWN
* and the details will be set to 'Unknown Error'.
* @param {Error} err The error object
*/
function setStatus(err) {
- var code = grpc.status.INTERNAL;
+ var code = grpc.status.UNKNOWN;
var details = 'Unknown Error';
var metadata = {};
if (err.hasOwnProperty('message')) {
@@ -634,7 +634,8 @@ function makeServerConstructor(service_attr_map) {
}
var serialize = attrs.responseSerialize;
var deserialize = attrs.requestDeserialize;
- server.register(attrs.path, service_handlers[service_name][name],
+ server.register(attrs.path, _.bind(service_handlers[service_name][name],
+ service_handlers[service_name]),
serialize, deserialize, method_type);
});
}, this);
diff --git a/src/node/test/health_test.js b/src/node/test/health_test.js
new file mode 100644
index 0000000000..4d1a5082e0
--- /dev/null
+++ b/src/node/test/health_test.js
@@ -0,0 +1,103 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+'use strict';
+
+var assert = require('assert');
+
+var health = require('../health_check/health.js');
+
+var grpc = require('../');
+
+describe('Health Checking', function() {
+ var statusMap = {
+ '': {
+ '': 'SERVING',
+ 'grpc.test.TestService': 'NOT_SERVING',
+ },
+ virtual_host: {
+ 'grpc.test.TestService': 'SERVING'
+ }
+ };
+ var HealthServer = grpc.buildServer([health.service]);
+ var healthServer = new HealthServer({
+ 'grpc.health.v1alpha.Health': new health.Implementation(statusMap)
+ });
+ var healthClient;
+ before(function() {
+ var port_num = healthServer.bind('0.0.0.0:0');
+ healthServer.listen();
+ healthClient = new health.Client('localhost:' + port_num);
+ });
+ after(function() {
+ healthServer.shutdown();
+ });
+ it('should say an enabled service is SERVING', function(done) {
+ healthClient.check({service: ''}, function(err, response) {
+ assert.ifError(err);
+ assert.strictEqual(response.status, 'SERVING');
+ done();
+ });
+ });
+ it('should say that a disabled service is NOT_SERVING', function(done) {
+ healthClient.check({service: 'grpc.test.TestService'},
+ function(err, response) {
+ assert.ifError(err);
+ assert.strictEqual(response.status, 'NOT_SERVING');
+ done();
+ });
+ });
+ it('should say that a service on another host is SERVING', function(done) {
+ healthClient.check({host: 'virtual_host', service: 'grpc.test.TestService'},
+ function(err, response) {
+ assert.ifError(err);
+ assert.strictEqual(response.status, 'SERVING');
+ done();
+ });
+ });
+ it('should get NOT_FOUND if the service is not registered', function(done) {
+ healthClient.check({service: 'not_registered'}, function(err, response) {
+ assert(err);
+ assert.strictEqual(err.code, grpc.status.NOT_FOUND);
+ done();
+ });
+ });
+ it('should get NOT_FOUND if the host is not registered', function(done) {
+ healthClient.check({host: 'wrong_host', service: 'grpc.test.TestService'},
+ function(err, response) {
+ assert(err);
+ assert.strictEqual(err.code, grpc.status.NOT_FOUND);
+ done();
+ });
+ });
+});
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index 8d1f99aaee..125957277f 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -418,6 +418,48 @@ describe('Other conditions', function() {
});
});
});
+ describe('Error object should contain the status', function() {
+ it('for a unary call', function(done) {
+ client.unary({error: true}, function(err, data) {
+ assert(err);
+ assert.strictEqual(err.code, grpc.status.UNKNOWN);
+ assert.strictEqual(err.message, 'Requested error');
+ done();
+ });
+ });
+ it('for a client stream call', function(done) {
+ var call = client.clientStream(function(err, data) {
+ assert(err);
+ assert.strictEqual(err.code, grpc.status.UNKNOWN);
+ assert.strictEqual(err.message, 'Requested error');
+ done();
+ });
+ call.write({error: false});
+ call.write({error: true});
+ call.end();
+ });
+ it('for a server stream call', function(done) {
+ var call = client.serverStream({error: true});
+ call.on('data', function(){});
+ call.on('error', function(error) {
+ assert.strictEqual(error.code, grpc.status.UNKNOWN);
+ assert.strictEqual(error.message, 'Requested error');
+ done();
+ });
+ });
+ it('for a bidi stream call', function(done) {
+ var call = client.bidiStream();
+ call.write({error: false});
+ call.write({error: true});
+ call.end();
+ call.on('data', function(){});
+ call.on('error', function(error) {
+ assert.strictEqual(error.code, grpc.status.UNKNOWN);
+ assert.strictEqual(error.message, 'Requested error');
+ done();
+ });
+ });
+ });
});
describe('Cancelling surface client', function() {
var client;
diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h
index cba53fa2f6..4a8b7fff48 100644
--- a/src/objective-c/GRPCClient/GRPCCall.h
+++ b/src/objective-c/GRPCClient/GRPCCall.h
@@ -52,7 +52,7 @@
extern id const kGRPCStatusMetadataKey;
// Represents a single gRPC remote call.
-@interface GRPCCall : NSObject<GRXWriter>
+@interface GRPCCall : GRXWriter
// These HTTP headers will be passed to the server as part of this call. Each HTTP header is a
// name-value pair with string names and either string or binary values.
@@ -89,7 +89,7 @@ extern id const kGRPCStatusMetadataKey;
// To finish a call right away, invoke cancel.
- (instancetype)initWithHost:(NSString *)host
path:(NSString *)path
- requestsWriter:(id<GRXWriter>)requestsWriter NS_DESIGNATED_INITIALIZER;
+ requestsWriter:(GRXWriter *)requestsWriter NS_DESIGNATED_INITIALIZER;
// Finishes the request side of this call, notifies the server that the RPC
// should be cancelled, and finishes the response side of the call with an error
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m
index 4ac4e4d37f..53e5abe177 100644
--- a/src/objective-c/GRPCClient/GRPCCall.m
+++ b/src/objective-c/GRPCClient/GRPCCall.m
@@ -79,7 +79,7 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
// all. This wrapper over our actual writeable ensures thread-safety and
// correct ordering.
GRPCDelegateWrapper *_responseWriteable;
- id<GRXWriter> _requestWriter;
+ GRXWriter *_requestWriter;
NSMutableDictionary *_requestMetadata;
NSMutableDictionary *_responseMetadata;
@@ -94,7 +94,7 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
// Designated initializer
- (instancetype)initWithHost:(NSString *)host
path:(NSString *)path
- requestsWriter:(id<GRXWriter>)requestWriter {
+ requestsWriter:(GRXWriter *)requestWriter {
if (!host || !path) {
[NSException raise:NSInvalidArgumentException format:@"Neither host nor method can be nil."];
}
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m
index 36f4c0aa5e..af4326332f 100644
--- a/src/objective-c/GRPCClient/private/GRPCChannel.m
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.m
@@ -60,7 +60,7 @@
}
- (instancetype)initWithHost:(NSString *)host {
- if (![host containsString:@"://"]) {
+ if (![host rangeOfString:@"://"].length) {
// No scheme provided; assume https.
host = [@"https://" stringByAppendingString:host];
}
diff --git a/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.h b/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.h
index 1ef245fe37..9a30a2f966 100644
--- a/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.h
+++ b/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.h
@@ -33,8 +33,9 @@
#import <Foundation/Foundation.h>
+#import <RxLibrary/GRXWriter.h>
+
@protocol GRXWriteable;
-@protocol GRXWriter;
// This is a thread-safe wrapper over a GRXWriteable instance. It lets one
// enqueue calls to a GRXWriteable instance for the main thread, guaranteeing
@@ -54,7 +55,7 @@
// writesFinishedWithError: is sent to the writeable, and released after that.
// This is used to create a retain cycle that keeps both objects alive until the
// writing is explicitly finished.
-- (instancetype)initWithWriteable:(id<GRXWriteable>)writeable writer:(id<GRXWriter>)writer
+- (instancetype)initWithWriteable:(id<GRXWriteable>)writeable writer:(GRXWriter *)writer
NS_DESIGNATED_INITIALIZER;
// Enqueues writeValue: to be sent to the writeable in the main thread.
diff --git a/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m b/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m
index 59c0565494..294cfb7e23 100644
--- a/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m
+++ b/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m
@@ -38,7 +38,7 @@
@interface GRPCDelegateWrapper ()
// These are atomic so that cancellation can nillify them from any thread.
@property(atomic, strong) id<GRXWriteable> writeable;
-@property(atomic, strong) id<GRXWriter> writer;
+@property(atomic, strong) GRXWriter *writer;
@end
@implementation GRPCDelegateWrapper {
@@ -52,7 +52,7 @@
}
// Designated initializer
-- (instancetype)initWithWriteable:(id<GRXWriteable>)writeable writer:(id<GRXWriter>)writer {
+- (instancetype)initWithWriteable:(id<GRXWriteable>)writeable writer:(GRXWriter *)writer {
if (self = [super init]) {
_writeableQueue = dispatch_get_main_queue();
_writeable = writeable;
diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h
index fcc0a507fe..bd926b7328 100644
--- a/src/objective-c/ProtoRPC/ProtoRPC.h
+++ b/src/objective-c/ProtoRPC/ProtoRPC.h
@@ -40,7 +40,7 @@
- (instancetype)initWithHost:(NSString *)host
method:(ProtoMethod *)method
- requestsWriter:(id<GRXWriter>)requestsWriter
+ requestsWriter:(GRXWriter *)requestsWriter
responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable NS_DESIGNATED_INITIALIZER;
diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m
index fe3ccf0541..889d71a308 100644
--- a/src/objective-c/ProtoRPC/ProtoRPC.m
+++ b/src/objective-c/ProtoRPC/ProtoRPC.m
@@ -35,7 +35,6 @@
#import <GPBProtocolBuffers.h>
#import <RxLibrary/GRXWriteable.h>
-#import <RxLibrary/GRXWriter.h>
#import <RxLibrary/GRXWriter+Transformations.h>
@implementation ProtoRPC {
@@ -46,7 +45,7 @@
#pragma clang diagnostic ignored "-Wobjc-designated-initializers"
- (instancetype)initWithHost:(NSString *)host
path:(NSString *)path
- requestsWriter:(id<GRXWriter>)requestsWriter {
+ requestsWriter:(GRXWriter *)requestsWriter {
[NSException raise:NSInvalidArgumentException
format:@"Please use ProtoRPC's designated initializer instead."];
return nil;
@@ -56,7 +55,7 @@
// Designated initializer
- (instancetype)initWithHost:(NSString *)host
method:(ProtoMethod *)method
- requestsWriter:(id<GRXWriter>)requestsWriter
+ requestsWriter:(GRXWriter *)requestsWriter
responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable {
// Because we can't tell the type system to constrain the class, we need to check at runtime:
@@ -65,12 +64,11 @@
format:@"A protobuf class to parse the responses must be provided."];
}
// A writer that serializes the proto messages to send.
- id<GRXWriter> bytesWriter =
- [[[GRXWriter alloc] initWithWriter:requestsWriter] map:^id(GPBMessage *proto) {
- // TODO(jcanizales): Fail with an understandable error message if the requestsWriter isn't
- // sending GPBMessages.
- return [proto data];
- }];
+ GRXWriter *bytesWriter = [requestsWriter map:^id(GPBMessage *proto) {
+ // TODO(jcanizales): Fail with an understandable error message if the requestsWriter isn't
+ // sending GPBMessages.
+ return [proto data];
+ }];
if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter])) {
// A writeable that parses the proto messages received.
_responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h
index c5ef820f48..2e8cb33696 100644
--- a/src/objective-c/ProtoRPC/ProtoService.h
+++ b/src/objective-c/ProtoRPC/ProtoService.h
@@ -35,7 +35,7 @@
@class ProtoRPC;
@protocol GRXWriteable;
-@protocol GRXWriter;
+@class GRXWriter;
@interface ProtoService : NSObject
- (instancetype)initWithHost:(NSString *)host
@@ -43,7 +43,7 @@
serviceName:(NSString *)serviceName NS_DESIGNATED_INITIALIZER;
- (ProtoRPC *)RPCToMethod:(NSString *)method
- requestsWriter:(id<GRXWriter>)requestsWriter
+ requestsWriter:(GRXWriter *)requestsWriter
responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable;
@end
diff --git a/src/objective-c/ProtoRPC/ProtoService.m b/src/objective-c/ProtoRPC/ProtoService.m
index d7c5b6a850..fccc6aadc9 100644
--- a/src/objective-c/ProtoRPC/ProtoService.m
+++ b/src/objective-c/ProtoRPC/ProtoService.m
@@ -66,7 +66,7 @@
}
- (ProtoRPC *)RPCToMethod:(NSString *)method
- requestsWriter:(id<GRXWriter>)requestsWriter
+ requestsWriter:(GRXWriter *)requestsWriter
responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable {
ProtoMethod *methodName = [[ProtoMethod alloc] initWithPackage:_packageName
diff --git a/src/objective-c/RxLibrary/GRXBufferedPipe.h b/src/objective-c/RxLibrary/GRXBufferedPipe.h
index 5e876a73bf..b6296e1ed7 100644
--- a/src/objective-c/RxLibrary/GRXBufferedPipe.h
+++ b/src/objective-c/RxLibrary/GRXBufferedPipe.h
@@ -51,7 +51,7 @@
// pipe will keep buffering all data written to it, your application could run out of memory and
// crash. If you want to react to flow control signals to prevent that, instead of using this class
// you can implement an object that conforms to GRXWriter.
-@interface GRXBufferedPipe : NSObject<GRXWriteable, GRXWriter>
+@interface GRXBufferedPipe : GRXWriter<GRXWriteable>
// Convenience constructor.
+ (instancetype)pipe;
diff --git a/src/objective-c/RxLibrary/GRXForwardingWriter.h b/src/objective-c/RxLibrary/GRXForwardingWriter.h
new file mode 100644
index 0000000000..d004333d2b
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXForwardingWriter.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#import "GRXWriter.h"
+
+// A "proxy" class that simply forwards values, completion, and errors from its
+// input writer to its writeable.
+// It is useful as a superclass for pipes that act as a transformation of their
+// input writer, and for classes that represent objects with input and
+// output sequences of values, like an RPC.
+@interface GRXForwardingWriter : GRXWriter
+- (instancetype)initWithWriter:(GRXWriter *)writer NS_DESIGNATED_INITIALIZER;
+@end
diff --git a/src/objective-c/RxLibrary/GRXForwardingWriter.m b/src/objective-c/RxLibrary/GRXForwardingWriter.m
new file mode 100644
index 0000000000..2342f51ab3
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXForwardingWriter.m
@@ -0,0 +1,112 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#import "GRXForwardingWriter.h"
+
+@interface GRXForwardingWriter () <GRXWriteable>
+@end
+
+@implementation GRXForwardingWriter {
+ GRXWriter *_writer;
+ id<GRXWriteable> _writeable;
+}
+
+- (instancetype)init {
+ return [self initWithWriter:nil];
+}
+
+// Designated initializer
+- (instancetype)initWithWriter:(GRXWriter *)writer {
+ if (!writer) {
+ [NSException raise:NSInvalidArgumentException format:@"writer can't be nil."];
+ }
+ if ((self = [super init])) {
+ _writer = writer;
+ }
+ return self;
+}
+
+// This is used to send a completion or an error to the writeable. It nillifies
+// our reference to it in order to guarantee no more messages are sent to it,
+// and to release it.
+- (void)finishOutputWithError:(NSError *)errorOrNil {
+ id<GRXWriteable> writeable = _writeable;
+ _writeable = nil;
+ [writeable writesFinishedWithError:errorOrNil];
+}
+
+// This is used to stop the input writer. It nillifies our reference to it
+// to release it.
+- (void)finishInput {
+ GRXWriter *writer = _writer;
+ _writer = nil;
+ writer.state = GRXWriterStateFinished;
+}
+
+#pragma mark GRXWriteable implementation
+
+- (void)writeValue:(id)value {
+ [_writeable writeValue:value];
+}
+
+- (void)writesFinishedWithError:(NSError *)errorOrNil {
+ _writer = nil;
+ [self finishOutputWithError:errorOrNil];
+}
+
+#pragma mark GRXWriter implementation
+
+- (GRXWriterState)state {
+ return _writer ? _writer.state : GRXWriterStateFinished;
+}
+
+- (void)setState:(GRXWriterState)state {
+ if (state == GRXWriterStateFinished) {
+ _writeable = nil;
+ [self finishInput];
+ } else {
+ _writer.state = state;
+ }
+}
+
+- (void)startWithWriteable:(id<GRXWriteable>)writeable {
+ _writeable = writeable;
+ [_writer startWithWriteable:self];
+}
+
+- (void)finishWithError:(NSError *)errorOrNil {
+ [self finishOutputWithError:errorOrNil];
+ [self finishInput];
+}
+
+@end
diff --git a/src/objective-c/RxLibrary/GRXImmediateWriter.h b/src/objective-c/RxLibrary/GRXImmediateWriter.h
index f86d38dcd8..b171f0c760 100644
--- a/src/objective-c/RxLibrary/GRXImmediateWriter.h
+++ b/src/objective-c/RxLibrary/GRXImmediateWriter.h
@@ -40,15 +40,15 @@
//
// Unless the writeable callback pauses them or stops them early, these writers will do all their
// interactions with the writeable before the start method returns.
-@interface GRXImmediateWriter : NSObject<GRXWriter>
+@interface GRXImmediateWriter : GRXWriter
// Returns a writer that pulls values from the passed NSEnumerator instance and pushes them to
// its writeable. The NSEnumerator is released when it finishes.
-+ (id<GRXWriter>)writerWithEnumerator:(NSEnumerator *)enumerator;
++ (GRXWriter *)writerWithEnumerator:(NSEnumerator *)enumerator;
// Returns a writer that pushes to its writeable the successive values returned by the passed
// block. When the block first returns nil, it is released.
-+ (id<GRXWriter>)writerWithValueSupplier:(id (^)())block;
++ (GRXWriter *)writerWithValueSupplier:(id (^)())block;
// Returns a writer that iterates over the values of the passed container and pushes them to
// its writeable. The container is released when the iteration is over.
@@ -56,18 +56,18 @@
// Note that the usual speed gain of NSFastEnumeration over NSEnumerator results from not having to
// call one method per element. Because GRXWriteable instances accept values one by one, that speed
// gain doesn't happen here.
-+ (id<GRXWriter>)writerWithContainer:(id<NSFastEnumeration>)container;
++ (GRXWriter *)writerWithContainer:(id<NSFastEnumeration>)container;
// Returns a writer that sends the passed value to its writeable and then finishes (releasing the
// value).
-+ (id<GRXWriter>)writerWithValue:(id)value;
++ (GRXWriter *)writerWithValue:(id)value;
// Returns a writer that, as part of its start method, sends the passed error to the writeable
// (then releasing the error).
-+ (id<GRXWriter>)writerWithError:(NSError *)error;
++ (GRXWriter *)writerWithError:(NSError *)error;
// Returns a writer that, as part of its start method, finishes immediately without sending any
// values to its writeable.
-+ (id<GRXWriter>)emptyWriter;
++ (GRXWriter *)emptyWriter;
@end
diff --git a/src/objective-c/RxLibrary/GRXImmediateWriter.m b/src/objective-c/RxLibrary/GRXImmediateWriter.m
index 0b4979872e..b6d2b2cac0 100644
--- a/src/objective-c/RxLibrary/GRXImmediateWriter.m
+++ b/src/objective-c/RxLibrary/GRXImmediateWriter.m
@@ -63,19 +63,19 @@
return [[self alloc] initWithEnumerator:enumerator error:errorOrNil];
}
-+ (id<GRXWriter>)writerWithEnumerator:(NSEnumerator *)enumerator {
++ (GRXWriter *)writerWithEnumerator:(NSEnumerator *)enumerator {
return [self writerWithEnumerator:enumerator error:nil];
}
-+ (id<GRXWriter>)writerWithValueSupplier:(id (^)())block {
++ (GRXWriter *)writerWithValueSupplier:(id (^)())block {
return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithValueSupplier:block]];
}
-+ (id<GRXWriter>)writerWithContainer:(id<NSFastEnumeration>)container {
++ (GRXWriter *)writerWithContainer:(id<NSFastEnumeration>)container {
return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithContainer:container]];;
}
-+ (id<GRXWriter>)writerWithValue:(id)value {
++ (GRXWriter *)writerWithValue:(id)value {
if (value) {
return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithSingleValue:value]];
} else {
@@ -83,7 +83,7 @@
}
}
-+ (id<GRXWriter>)writerWithError:(NSError *)error {
++ (GRXWriter *)writerWithError:(NSError *)error {
if (error) {
return [self writerWithEnumerator:nil error:error];
} else {
@@ -91,7 +91,7 @@
}
}
-+ (id<GRXWriter>)emptyWriter {
++ (GRXWriter *)emptyWriter {
static GRXImmediateWriter *emptyWriter;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
diff --git a/src/objective-c/RxLibrary/GRXWriter+Immediate.m b/src/objective-c/RxLibrary/GRXWriter+Immediate.m
index 39c54f86ec..1d55eb3529 100644
--- a/src/objective-c/RxLibrary/GRXWriter+Immediate.m
+++ b/src/objective-c/RxLibrary/GRXWriter+Immediate.m
@@ -38,27 +38,27 @@
@implementation GRXWriter (Immediate)
+ (instancetype)writerWithEnumerator:(NSEnumerator *)enumerator {
- return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithEnumerator:enumerator]];
+ return [GRXImmediateWriter writerWithEnumerator:enumerator];
}
+ (instancetype)writerWithValueSupplier:(id (^)())block {
- return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithValueSupplier:block]];
+ return [GRXImmediateWriter writerWithValueSupplier:block];
}
+ (instancetype)writerWithContainer:(id<NSFastEnumeration>)container {
- return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithContainer:container]];
+ return [GRXImmediateWriter writerWithContainer:container];
}
+ (instancetype)writerWithValue:(id)value {
- return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithValue:value]];
+ return [GRXImmediateWriter writerWithValue:value];
}
+ (instancetype)writerWithError:(NSError *)error {
- return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithError:error]];
+ return [GRXImmediateWriter writerWithError:error];
}
+ (instancetype)emptyWriter {
- return [[self alloc] initWithWriter:[GRXImmediateWriter emptyWriter]];
+ return [GRXImmediateWriter emptyWriter];
}
@end
diff --git a/src/objective-c/RxLibrary/GRXWriter.h b/src/objective-c/RxLibrary/GRXWriter.h
index dcf44e3143..5d6e1a472a 100644
--- a/src/objective-c/RxLibrary/GRXWriter.h
+++ b/src/objective-c/RxLibrary/GRXWriter.h
@@ -85,7 +85,7 @@ typedef NS_ENUM(NSInteger, GRXWriterState) {
// Unless otherwise indicated by a conforming class, no messages should be sent
// concurrently to a GRXWriter. I.e., conforming classes aren't required to
// be thread-safe.
-@protocol GRXWriter <NSObject>
+@interface GRXWriter : NSObject
// This property can be used to query the current state of the writer, which
// determines how it might currently use its writeable. Some state transitions can
@@ -116,12 +116,3 @@ typedef NS_ENUM(NSInteger, GRXWriterState) {
// can't remember the details in the presence of concurrency.
- (void)finishWithError:(NSError *)errorOrNil;
@end
-
-// A "proxy" class that simply forwards values, completion, and errors from its
-// input writer to its writeable.
-// It is useful as a superclass for pipes that act as a transformation of their
-// input writer, and for classes that represent objects with input and
-// output sequences of values, like an RPC.
-@interface GRXWriter : NSObject<GRXWriter>
-- (instancetype)initWithWriter:(id<GRXWriter>)writer NS_DESIGNATED_INITIALIZER;
-@end
diff --git a/src/objective-c/RxLibrary/GRXWriter.m b/src/objective-c/RxLibrary/GRXWriter.m
index cc14383560..019fcbd785 100644
--- a/src/objective-c/RxLibrary/GRXWriter.m
+++ b/src/objective-c/RxLibrary/GRXWriter.m
@@ -33,80 +33,6 @@
#import "GRXWriter.h"
-@interface GRXWriter () <GRXWriteable>
-@end
-
-@implementation GRXWriter {
- id<GRXWriter> _writer;
- id<GRXWriteable> _writeable;
-}
-
-- (instancetype)init {
- return [self initWithWriter:nil];
-}
-
-// Designated initializer
-- (instancetype)initWithWriter:(id<GRXWriter>)writer {
- if (!writer) {
- [NSException raise:NSInvalidArgumentException format:@"writer can't be nil."];
- }
- if ((self = [super init])) {
- _writer = writer;
- }
- return self;
-}
-
-// This is used to send a completion or an error to the writeable. It nillifies
-// our reference to it in order to guarantee no more messages are sent to it,
-// and to release it.
-- (void)finishOutputWithError:(NSError *)errorOrNil {
- id<GRXWriteable> writeable = _writeable;
- _writeable = nil;
- [writeable writesFinishedWithError:errorOrNil];
-}
-
-// This is used to stop the input writer. It nillifies our reference to it
-// to release it.
-- (void)finishInput {
- id<GRXWriter> writer = _writer;
- _writer = nil;
- writer.state = GRXWriterStateFinished;
-}
-
-#pragma mark GRXWriteable implementation
-
-- (void)writeValue:(id)value {
- [_writeable writeValue:value];
-}
-
-- (void)writesFinishedWithError:(NSError *)errorOrNil {
- _writer = nil;
- [self finishOutputWithError:errorOrNil];
-}
-
-#pragma mark GRXWriter implementation
-
-- (GRXWriterState)state {
- return _writer ? _writer.state : GRXWriterStateFinished;
-}
-
-- (void)setState:(GRXWriterState)state {
- if (state == GRXWriterStateFinished) {
- _writeable = nil;
- [self finishInput];
- } else {
- _writer.state = state;
- }
-}
-
-- (void)startWithWriteable:(id<GRXWriteable>)writeable {
- _writeable = writeable;
- [_writer startWithWriteable:self];
-}
-
-- (void)finishWithError:(NSError *)errorOrNil {
- [self finishOutputWithError:errorOrNil];
- [self finishInput];
-}
+@implementation GRXWriter
@end
diff --git a/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h
index 55f6f82f20..43b8706864 100644
--- a/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h
+++ b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h
@@ -31,10 +31,10 @@
*
*/
-#import "RxLibrary/GRXWriter.h"
+#import "RxLibrary/GRXForwardingWriter.h"
// A "proxy" writer that transforms all the values of its input writer by using a mapping function.
-@interface GRXMappingWriter : GRXWriter
-- (instancetype)initWithWriter:(id<GRXWriter>)writer map:(id (^)(id value))map
+@interface GRXMappingWriter : GRXForwardingWriter
+- (instancetype)initWithWriter:(GRXWriter *)writer map:(id (^)(id value))map
NS_DESIGNATED_INITIALIZER;
@end
diff --git a/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m
index 2cdfea1b67..f3242e4fa9 100644
--- a/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m
+++ b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m
@@ -37,19 +37,19 @@ static id (^kIdentity)(id value) = ^id(id value) {
return value;
};
-@interface GRXWriter () <GRXWriteable>
+@interface GRXForwardingWriter () <GRXWriteable>
@end
@implementation GRXMappingWriter {
id (^_map)(id value);
}
-- (instancetype)initWithWriter:(id<GRXWriter>)writer {
+- (instancetype)initWithWriter:(GRXWriter *)writer {
return [self initWithWriter:writer map:nil];
}
// Designated initializer
-- (instancetype)initWithWriter:(id<GRXWriter>)writer map:(id (^)(id value))map {
+- (instancetype)initWithWriter:(GRXWriter *)writer map:(id (^)(id value))map {
if ((self = [super initWithWriter:writer])) {
_map = map ?: kIdentity;
}
diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m
index f9c2d5d8d6..3210ad7050 100644
--- a/src/objective-c/tests/GRPCClientTests.m
+++ b/src/objective-c/tests/GRPCClientTests.m
@@ -87,7 +87,7 @@ static ProtoMethod *kUnaryCallMethod;
[call startWithWriteable:responsesWriteable];
- [self waitForExpectationsWithTimeout:2. handler:nil];
+ [self waitForExpectationsWithTimeout:4 handler:nil];
}
- (void)testEmptyRPC {
@@ -109,7 +109,7 @@ static ProtoMethod *kUnaryCallMethod;
[call startWithWriteable:responsesWriteable];
- [self waitForExpectationsWithTimeout:2. handler:nil];
+ [self waitForExpectationsWithTimeout:4 handler:nil];
}
- (void)testSimpleProtoRPC {
@@ -120,7 +120,7 @@ static ProtoMethod *kUnaryCallMethod;
request.responseSize = 100;
request.fillUsername = YES;
request.fillOauthScope = YES;
- id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[request data]];
+ GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
path:kUnaryCallMethod.HTTPPath
@@ -141,7 +141,7 @@ static ProtoMethod *kUnaryCallMethod;
[call startWithWriteable:responsesWriteable];
- [self waitForExpectationsWithTimeout:2. handler:nil];
+ [self waitForExpectationsWithTimeout:4 handler:nil];
}
- (void)testMetadata {
@@ -150,7 +150,7 @@ static ProtoMethod *kUnaryCallMethod;
RMTSimpleRequest *request = [RMTSimpleRequest message];
request.fillUsername = YES;
request.fillOauthScope = YES;
- id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[request data]];
+ GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
path:kUnaryCallMethod.HTTPPath
@@ -173,7 +173,7 @@ static ProtoMethod *kUnaryCallMethod;
[call startWithWriteable:responsesWriteable];
- [self waitForExpectationsWithTimeout:2. handler:nil];
+ [self waitForExpectationsWithTimeout:4 handler:nil];
}
@end
diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m
index 74f6b231cf..501f33317a 100644
--- a/src/objective-c/tests/InteropTests.m
+++ b/src/objective-c/tests/InteropTests.m
@@ -103,7 +103,7 @@
[expectation fulfill];
}];
- [self waitForExpectationsWithTimeout:2 handler:nil];
+ [self waitForExpectationsWithTimeout:4 handler:nil];
}
- (void)testLargeUnaryRPC {
@@ -125,7 +125,7 @@
[expectation fulfill];
}];
- [self waitForExpectationsWithTimeout:4 handler:nil];
+ [self waitForExpectationsWithTimeout:8 handler:nil];
}
- (void)testClientStreamingRPC {
@@ -143,7 +143,7 @@
RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message];
request4.payload.body = [NSMutableData dataWithLength:45904];
- id<GRXWriter> writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]];
+ GRXWriter *writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]];
[_service streamingInputCallWithRequestsWriter:writer
handler:^(RMTStreamingInputCallResponse *response,
@@ -157,7 +157,7 @@
[expectation fulfill];
}];
- [self waitForExpectationsWithTimeout:4 handler:nil];
+ [self waitForExpectationsWithTimeout:8 handler:nil];
}
- (void)testServerStreamingRPC {
@@ -193,7 +193,7 @@
}
}];
- [self waitForExpectationsWithTimeout:4 handler:nil];
+ [self waitForExpectationsWithTimeout:8 handler:nil];
}
- (void)testPingPongRPC {
@@ -236,7 +236,7 @@
[expectation fulfill];
}
}];
- [self waitForExpectationsWithTimeout:2 handler:nil];
+ [self waitForExpectationsWithTimeout:4 handler:nil];
}
- (void)testEmptyStreamRPC {
@@ -282,10 +282,11 @@
[requestsBuffer writeValue:request];
- __block ProtoRPC *call = [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer
- eventHandler:^(BOOL done,
- RMTStreamingOutputCallResponse *response,
- NSError *error) {
+ __block ProtoRPC *call =
+ [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer
+ eventHandler:^(BOOL done,
+ RMTStreamingOutputCallResponse *response,
+ NSError *error) {
if (receivedResponse) {
XCTAssert(done, @"Unexpected extra response %@", response);
XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
@@ -299,7 +300,7 @@
}
}];
[call start];
- [self waitForExpectationsWithTimeout:4 handler:nil];
+ [self waitForExpectationsWithTimeout:8 handler:nil];
}
@end
diff --git a/src/objective-c/tests/LocalClearTextTests.m b/src/objective-c/tests/LocalClearTextTests.m
index 10c9f13ea3..4317614dd9 100644
--- a/src/objective-c/tests/LocalClearTextTests.m
+++ b/src/objective-c/tests/LocalClearTextTests.m
@@ -64,7 +64,7 @@ static NSString * const kService = @"RouteGuide";
// interface:kService
// method:@"EmptyCall"];
//
-// id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[NSData data]];
+// GRXWriter *requestsWriter = [GRXWriter writerWithValue:[NSData data]];
//
// GRPCCall *call = [[GRPCCall alloc] initWithHost:kRouteGuideHost
// method:method
@@ -91,7 +91,7 @@ static NSString * const kService = @"RouteGuide";
service:kService
method:@"RecordRoute"];
- id<GRXWriter> requestsWriter = [GRXWriter emptyWriter];
+ GRXWriter *requestsWriter = [GRXWriter emptyWriter];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kRouteGuideHost
path:method.HTTPPath
@@ -122,7 +122,7 @@ static NSString * const kService = @"RouteGuide";
RGDPoint *point = [RGDPoint message];
point.latitude = 28E7;
point.longitude = -15E7;
- id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[point data]];
+ GRXWriter *requestsWriter = [GRXWriter writerWithValue:[point data]];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kRouteGuideHost
path:method.HTTPPath
diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile
index 026868db12..2aa837f764 100644
--- a/src/objective-c/tests/Podfile
+++ b/src/objective-c/tests/Podfile
@@ -1,6 +1,7 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
+pod 'Protobuf', :path => "../../../third_party/protobuf"
pod 'gRPC', :path => "../../.."
pod 'RemoteTest', :path => "../generated_libraries/RemoteTestClient"
pod 'RouteGuide', :path => "../generated_libraries/RouteGuideClient"
diff --git a/src/php/bin/determine_extension_dir.sh b/src/php/bin/determine_extension_dir.sh
index 6bbd934bf1..b4342ac89f 100755
--- a/src/php/bin/determine_extension_dir.sh
+++ b/src/php/bin/determine_extension_dir.sh
@@ -27,12 +27,12 @@
# 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.
-
set -e
default_extension_dir=$(php-config --extension-dir)
-if command -v brew >/dev/null && [ -d $(brew --prefix)/opt/grpc-php ]; then
- # homebrew and the grpc-php formula are installed
- extension_dir="-d extension_dir="$(brew --prefix)/opt/grpc-php
+if command -v brew > /dev/null && \
+ brew ls --versions | grep php5[56]-grpc > /dev/null; then
+ # the grpc php extension was installed by homebrew
+ :
elif [ ! -e $default_extension_dir/grpc.so ]; then
# the grpc extension is not found in the default PHP extension dir
# try the source modules directory
@@ -45,5 +45,7 @@ elif [ ! -e $default_extension_dir/grpc.so ]; then
for f in $default_extension_dir/*.so; do
ln -s $f $module_dir/$(basename $f) &> /dev/null || true
done
- extension_dir="-d extension_dir="$module_dir
+ extension_dir="-d extension_dir=${module_dir} -d extension=grpc.so"
+else
+ extension_dir="-d extension=grpc.so"
fi
diff --git a/src/php/bin/interop_client.sh b/src/php/bin/interop_client.sh
index 42e075cbe8..17b888dd4e 100755
--- a/src/php/bin/interop_client.sh
+++ b/src/php/bin/interop_client.sh
@@ -31,5 +31,5 @@
set -e
cd $(dirname $0)
source ./determine_extension_dir.sh
-php $extension_dir -d extension=grpc.so \
+php $extension_dir \
../tests/interop/interop_client.php $@ 1>&2
diff --git a/src/php/bin/run_gen_code_test.sh b/src/php/bin/run_gen_code_test.sh
index 03a9101a45..6e56c7207c 100755
--- a/src/php/bin/run_gen_code_test.sh
+++ b/src/php/bin/run_gen_code_test.sh
@@ -31,8 +31,8 @@
set -e
cd $(dirname $0)
source ./determine_extension_dir.sh
-export GRPC_TEST_HOST=localhost:7071
-php $extension_dir -d extension=grpc.so $(which phpunit) -v --debug --strict \
+export GRPC_TEST_HOST=localhost:50051
+php $extension_dir $(which phpunit) -v --debug --strict \
../tests/generated_code/GeneratedCodeTest.php
-php $extension_dir -d extension=grpc.so $(which phpunit) -v --debug --strict \
+php $extension_dir $(which phpunit) -v --debug --strict \
../tests/generated_code/GeneratedCodeWithCallbackTest.php
diff --git a/src/php/bin/run_tests.sh b/src/php/bin/run_tests.sh
index 4c37285455..953f408ea8 100755
--- a/src/php/bin/run_tests.sh
+++ b/src/php/bin/run_tests.sh
@@ -33,5 +33,5 @@
set -e
cd $(dirname $0)
source ./determine_extension_dir.sh
-php $extension_dir -d extension=grpc.so $(which phpunit) -v --debug --strict \
+php $extension_dir $(which phpunit) -v --debug --strict \
../tests/unit_tests
diff --git a/src/php/ext/grpc/README.md b/src/php/ext/grpc/README.md
index 0ac09e1835..88d2c481ec 100644
--- a/src/php/ext/grpc/README.md
+++ b/src/php/ext/grpc/README.md
@@ -4,7 +4,7 @@ gRPC PHP Extension
# Requirements
* PHP 5.5+
- * [gRPC core library](https://github.com/grpc/grpc) 0.9.1
+ * [gRPC core library](https://github.com/grpc/grpc) 0.10.0
# Installation
@@ -55,7 +55,7 @@ $ sudo pecl install grpc
Note: before a stable release, you may need to do
```sh
-$ sudo pecl install grpc-0.5.0
+$ sudo pecl install grpc-0.5.1
```
OR
diff --git a/src/php/ext/grpc/package.xml b/src/php/ext/grpc/package.xml
index 2c89829d51..bc2a05923b 100644
--- a/src/php/ext/grpc/package.xml
+++ b/src/php/ext/grpc/package.xml
@@ -10,11 +10,11 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
- <date>2015-06-16</date>
- <time>20:12:55</time>
+ <date>2015-07-09</date>
+ <time>21:47:27</time>
<version>
- <release>0.5.0</release>
- <api>0.5.0</api>
+ <release>0.5.1</release>
+ <api>0.5.1</api>
</version>
<stability>
<release>alpha</release>
@@ -22,7 +22,7 @@
</stability>
<license>BSD</license>
<notes>
-First alpha release
+Update to wrap gRPC C Core version 0.10.0
</notes>
<contents>
<dir baseinstalldir="/" name="/">
@@ -34,15 +34,15 @@ First alpha release
<file baseinstalldir="/" md5sum="f1b66029daeced20b47cf00cc6523fc8" name="channel.h" role="src" />
<file baseinstalldir="/" md5sum="81a1193e93d8b6602add8ac360de565b" name="completion_queue.c" role="src" />
<file baseinstalldir="/" md5sum="f10b5bb232d74a6878e829e2e76cdaa2" name="completion_queue.h" role="src" />
- <file baseinstalldir="/" md5sum="a9181ed994a072ac5f41e7c9705c170f" name="config.m4" role="src" />
+ <file baseinstalldir="/" md5sum="a22f8eac0164761058cc4d9eb2ceb069" name="config.m4" role="src" />
<file baseinstalldir="/" md5sum="8c3f1e11dac623001378bfd53b554f08" name="credentials.c" role="src" />
<file baseinstalldir="/" md5sum="6988d6e97c19c8f8e3eb92371cf8246b" name="credentials.h" role="src" />
<file baseinstalldir="/" md5sum="38a1bc979d810c36ebc2a52d4b7b5319" name="CREDITS" role="doc" />
<file baseinstalldir="/" md5sum="3f35b472bbdef5a788cd90617d7d0847" name="LICENSE" role="doc" />
<file baseinstalldir="/" md5sum="6aaa7a290122d230f2d8c4e4e05da4a9" name="php_grpc.c" role="src" />
<file baseinstalldir="/" md5sum="673b07859d9f69232f8a754c56780686" name="php_grpc.h" role="src" />
- <file baseinstalldir="/" md5sum="4d4d3382f8d10cae2e4378468e5516b9" name="README.md" role="doc" />
- <file baseinstalldir="/" md5sum="53fda0ee6937f6ddc8e271886018d441" name="server.c" role="src" />
+ <file baseinstalldir="/" md5sum="c1d0b42fd77b7d6740bf7744bee90af5" name="README.md" role="doc" />
+ <file baseinstalldir="/" md5sum="30997dd423403e1f8ad09dcee598e5c4" name="server.c" role="src" />
<file baseinstalldir="/" md5sum="4b730f06d14cbbb0642bdbd194749595" name="server.h" role="src" />
<file baseinstalldir="/" md5sum="f6930beafb6c0e061899262f2f077e98" name="server_credentials.c" role="src" />
<file baseinstalldir="/" md5sum="9c4b4cc06356a8a39a16a085a9b85996" name="server_credentials.h" role="src" />
@@ -78,5 +78,20 @@ First alpha release
First alpha release
</notes>
</release>
+ <release>
+ <version>
+ <release>0.5.1</release>
+ <api>0.5.1</api>
+ </version>
+ <stability>
+ <release>alpha</release>
+ <api>alpha</api>
+ </stability>
+ <date>2015-07-09</date>
+ <license>BSD</license>
+ <notes>
+Update to wrap gRPC C Core version 0.10.0
+ </notes>
+ </release>
</changelog>
</package>
diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c
index 8a278d6760..ccf7f0f81a 100644
--- a/src/php/ext/grpc/timeval.c
+++ b/src/php/ext/grpc/timeval.c
@@ -208,7 +208,7 @@ PHP_METHOD(Timeval, similar) {
* @return Timeval The current time
*/
PHP_METHOD(Timeval, now) {
- zval *now = grpc_php_wrap_timeval(gpr_now());
+ zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME));
RETURN_DESTROY_ZVAL(now);
}
diff --git a/src/python/interop/setup.py b/src/python/interop/setup.py
index 502fcbedd8..75012b0d8f 100644
--- a/src/python/interop/setup.py
+++ b/src/python/interop/setup.py
@@ -45,7 +45,7 @@ _PACKAGE_DATA = {
'credentials/server1.pem',]
}
-_INSTALL_REQUIRES = ['oauth2client>=1.4.7', 'grpcio>=0.4.0a4']
+_INSTALL_REQUIRES = ['oauth2client>=1.4.7', 'grpcio>=0.10.0a0']
setuptools.setup(
name='interop',
diff --git a/src/python/src/.gitignore b/src/python/src/.gitignore
index bc15a52cf1..144e501237 100644
--- a/src/python/src/.gitignore
+++ b/src/python/src/.gitignore
@@ -1,3 +1,4 @@
MANIFEST
grpcio.egg-info/
+build/
dist/
diff --git a/src/python/src/grpc/_adapter/.gitignore b/src/python/src/grpc/_adapter/.gitignore
new file mode 100644
index 0000000000..a6f96cd6db
--- /dev/null
+++ b/src/python/src/grpc/_adapter/.gitignore
@@ -0,0 +1,5 @@
+*.a
+*.so
+*.dll
+*.pyc
+*.pyd
diff --git a/src/python/src/grpc/_cython/.gitignore b/src/python/src/grpc/_cython/.gitignore
new file mode 100644
index 0000000000..c315029288
--- /dev/null
+++ b/src/python/src/grpc/_cython/.gitignore
@@ -0,0 +1,7 @@
+*.h
+*.c
+*.a
+*.so
+*.dll
+*.pyc
+*.pyd
diff --git a/src/python/src/grpc/_cython/README.rst b/src/python/src/grpc/_cython/README.rst
new file mode 100644
index 0000000000..c0e66734e8
--- /dev/null
+++ b/src/python/src/grpc/_cython/README.rst
@@ -0,0 +1,52 @@
+GRPC Python Cython layer
+========================
+
+Package for the GRPC Python Cython layer.
+
+What is Cython?
+---------------
+
+Cython is both a superset of the Python language with extensions for dealing
+with C types and a tool that transpiles this superset into C code. It provides
+convenient means of statically typing expressions and of converting Python
+strings to pointers (among other niceties), thus dramatically smoothing the
+Python/C interop by allowing fluid use of APIs in both from the same source.
+See the wonderful `Cython website`_.
+
+Why Cython?
+-----------
+
+- **Python 2 and 3 support**
+ Cython generated C code has precompiler macros to target both Python 2 and
+ Python 3 C APIs, even while acting as a superset of just the Python 2
+ language (e.g. using ``basestring``).
+- **Significantly less semantic noise**
+ A lot of CPython code is just glue, especially human-error-prone
+ ``Py_INCREF``-ing and ``Py_DECREF``-ing around error handlers and such.
+ Cython takes care of that automagically.
+- **Possible PyPy support**
+ One of the major developments in Cython over the past few years was the
+ addition of support for PyPy. We might soon be able to provide such support
+ ourselves through our use of Cython.
+- **Less Python glue code**
+ There existed several adapter layers in and around the original CPython code
+ to smooth the surface exposed to Python due to how much trouble it was to
+ make such a smooth surface via the CPython API alone. Cython makes writing
+ such a surface incredibly easy, so these adapter layers may be removed.
+
+Implications for Users
+----------------------
+
+Nothing additional will be required for users. PyPI packages will contain
+Cython generated C code and thus not necessitate a Cython installation.
+
+Implications for GRPC Developers
+--------------------------------
+
+A typical edit-compile-debug cycle now requires Cython. We install Cython in
+the ``virtualenv`` generated for the Python tests in this repository, so
+initial test runs may take an extra 2+ minutes to complete. Subsequent test
+runs won't reinstall ``Cython`` (unless required versions change and the
+``virtualenv`` doesn't have installed versions that satisfy the change).
+
+.. _`Cython website`: http://cython.org/
diff --git a/src/python/src/grpc/_cython/__init__.py b/src/python/src/grpc/_cython/__init__.py
new file mode 100644
index 0000000000..b89398809f
--- /dev/null
+++ b/src/python/src/grpc/_cython/__init__.py
@@ -0,0 +1,28 @@
+# 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.
diff --git a/src/python/src/grpc/_cython/_cygrpc/__init__.py b/src/python/src/grpc/_cython/_cygrpc/__init__.py
new file mode 100644
index 0000000000..b89398809f
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/__init__.py
@@ -0,0 +1,28 @@
+# 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.
diff --git a/src/python/src/grpc/_cython/_cygrpc/call.pxd b/src/python/src/grpc/_cython/_cygrpc/call.pxd
new file mode 100644
index 0000000000..fe9b81e3d3
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/call.pxd
@@ -0,0 +1,37 @@
+# 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.
+
+from grpc._cython._cygrpc cimport grpc
+
+
+cdef class Call:
+
+ cdef grpc.grpc_call *c_call
+ cdef list references
+
diff --git a/src/python/src/grpc/_cython/_cygrpc/call.pyx b/src/python/src/grpc/_cython/_cygrpc/call.pyx
new file mode 100644
index 0000000000..4349786b3a
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/call.pyx
@@ -0,0 +1,82 @@
+# 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.
+
+cimport cpython
+
+from grpc._cython._cygrpc cimport records
+
+
+cdef class Call:
+
+ def __cinit__(self):
+ # Create an *empty* call
+ self.c_call = NULL
+ self.references = []
+
+ def start_batch(self, operations, tag):
+ if not self.is_valid:
+ raise ValueError("invalid call object cannot be used from Python")
+ cdef records.Operations cy_operations = records.Operations(operations)
+ cdef records.OperationTag operation_tag = records.OperationTag(tag)
+ operation_tag.operation_call = self
+ operation_tag.batch_operations = cy_operations
+ cpython.Py_INCREF(operation_tag)
+ return grpc.grpc_call_start_batch(
+ self.c_call, cy_operations.c_ops, cy_operations.c_nops,
+ <cpython.PyObject *>operation_tag)
+
+ def cancel(self,
+ grpc.grpc_status_code error_code=grpc.GRPC_STATUS__DO_NOT_USE,
+ details=None):
+ if not self.is_valid:
+ raise ValueError("invalid call object cannot be used from Python")
+ if (details is None) != (error_code == grpc.GRPC_STATUS__DO_NOT_USE):
+ raise ValueError("if error_code is specified, so must details "
+ "(and vice-versa)")
+ if isinstance(details, bytes):
+ pass
+ elif isinstance(details, basestring):
+ details = details.encode()
+ else:
+ raise TypeError("expected details to be str or bytes")
+ if error_code != grpc.GRPC_STATUS__DO_NOT_USE:
+ self.references.append(details)
+ return grpc.grpc_call_cancel_with_status(self.c_call, error_code, details)
+ else:
+ return grpc.grpc_call_cancel(self.c_call)
+
+ def __dealloc__(self):
+ if self.c_call != NULL:
+ grpc.grpc_call_destroy(self.c_call)
+
+ # The object *should* always be valid from Python. Used for debugging.
+ @property
+ def is_valid(self):
+ return self.c_call != NULL
+
diff --git a/src/python/src/grpc/_cython/_cygrpc/channel.pxd b/src/python/src/grpc/_cython/_cygrpc/channel.pxd
new file mode 100644
index 0000000000..3e341bf222
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/channel.pxd
@@ -0,0 +1,36 @@
+# 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.
+
+from grpc._cython._cygrpc cimport grpc
+
+
+cdef class Channel:
+
+ cdef grpc.grpc_channel *c_channel
+ cdef list references
diff --git a/src/python/src/grpc/_cython/_cygrpc/channel.pyx b/src/python/src/grpc/_cython/_cygrpc/channel.pyx
new file mode 100644
index 0000000000..b20313818d
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/channel.pyx
@@ -0,0 +1,84 @@
+# 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.
+
+from grpc._cython._cygrpc cimport call
+from grpc._cython._cygrpc cimport completion_queue
+from grpc._cython._cygrpc cimport credentials
+from grpc._cython._cygrpc cimport records
+
+
+cdef class Channel:
+
+ def __cinit__(self, target, records.ChannelArgs arguments=None,
+ credentials.ClientCredentials client_credentials=None):
+ cdef grpc.grpc_channel_args *c_arguments = NULL
+ self.c_channel = NULL
+ self.references = []
+ if arguments is not None:
+ c_arguments = &arguments.c_args
+ if isinstance(target, bytes):
+ pass
+ elif isinstance(target, basestring):
+ target = target.encode()
+ else:
+ raise TypeError("expected target to be str or bytes")
+ if client_credentials is None:
+ self.c_channel = grpc.grpc_channel_create(target, c_arguments)
+ else:
+ self.c_channel = grpc.grpc_secure_channel_create(
+ client_credentials.c_credentials, target, c_arguments)
+ self.references.append(client_credentials)
+ self.references.append(target)
+ self.references.append(arguments)
+
+ def create_call(self, completion_queue.CompletionQueue queue not None,
+ method, host, records.Timespec deadline not None):
+ if queue.is_shutting_down:
+ raise ValueError("queue must not be shutting down or shutdown")
+ if isinstance(method, bytes):
+ pass
+ elif isinstance(method, basestring):
+ method = method.encode()
+ else:
+ raise TypeError("expected method to be str or bytes")
+ if isinstance(host, bytes):
+ pass
+ elif isinstance(host, basestring):
+ host = host.encode()
+ else:
+ raise TypeError("expected host to be str or bytes")
+ cdef call.Call operation_call = call.Call()
+ operation_call.references = [self, method, host, queue]
+ operation_call.c_call = grpc.grpc_channel_create_call(
+ self.c_channel, queue.c_completion_queue, method, host, deadline.c_time)
+ return operation_call
+
+ def __dealloc__(self):
+ if self.c_channel != NULL:
+ grpc.grpc_channel_destroy(self.c_channel)
diff --git a/src/python/src/grpc/_cython/_cygrpc/completion_queue.pxd b/src/python/src/grpc/_cython/_cygrpc/completion_queue.pxd
new file mode 100644
index 0000000000..fd562ad75b
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/completion_queue.pxd
@@ -0,0 +1,39 @@
+# 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.
+
+from grpc._cython._cygrpc cimport grpc
+
+
+cdef class CompletionQueue:
+
+ cdef grpc.grpc_completion_queue *c_completion_queue
+ cdef object poll_condition
+ cdef bint is_polling
+ cdef bint is_shutting_down
+ cdef bint is_shutdown
diff --git a/src/python/src/grpc/_cython/_cygrpc/completion_queue.pyx b/src/python/src/grpc/_cython/_cygrpc/completion_queue.pyx
new file mode 100644
index 0000000000..886d85360a
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/completion_queue.pyx
@@ -0,0 +1,117 @@
+# 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.
+
+cimport cpython
+
+from grpc._cython._cygrpc cimport call
+from grpc._cython._cygrpc cimport records
+
+import threading
+import time
+
+
+cdef class CompletionQueue:
+
+ def __cinit__(self):
+ self.c_completion_queue = grpc.grpc_completion_queue_create()
+ self.is_shutting_down = False
+ self.is_shutdown = False
+ self.poll_condition = threading.Condition()
+ self.is_polling = False
+
+ def poll(self, records.Timespec deadline=None):
+ # We name this 'poll' to avoid problems with CPython's expectations for
+ # 'special' methods (like next and __next__).
+ cdef grpc.gpr_timespec c_deadline = grpc.gpr_inf_future
+ cdef records.OperationTag tag = None
+ cdef object user_tag = None
+ cdef call.Call operation_call = None
+ cdef records.CallDetails request_call_details = None
+ cdef records.Metadata request_metadata = None
+ cdef records.Operations batch_operations = None
+ if deadline is not None:
+ c_deadline = deadline.c_time
+ cdef grpc.grpc_event event
+
+ # Poll within a critical section
+ with self.poll_condition:
+ while self.is_polling:
+ self.poll_condition.wait(float(deadline) - time.time())
+ self.is_polling = True
+ with nogil:
+ event = grpc.grpc_completion_queue_next(
+ self.c_completion_queue, c_deadline)
+ with self.poll_condition:
+ self.is_polling = False
+ self.poll_condition.notify()
+
+ if event.type == grpc.GRPC_QUEUE_TIMEOUT:
+ return records.Event(event.type, False, None, None, None, None, None)
+ elif event.type == grpc.GRPC_QUEUE_SHUTDOWN:
+ self.is_shutdown = True
+ return records.Event(event.type, True, None, None, None, None, None)
+ else:
+ if event.tag != NULL:
+ tag = <records.OperationTag>event.tag
+ # We receive event tags only after they've been inc-ref'd elsewhere in
+ # the code.
+ cpython.Py_DECREF(tag)
+ if tag.shutting_down_server is not None:
+ tag.shutting_down_server.notify_shutdown_complete()
+ user_tag = tag.user_tag
+ operation_call = tag.operation_call
+ request_call_details = tag.request_call_details
+ request_metadata = tag.request_metadata
+ batch_operations = tag.batch_operations
+ if tag.is_new_request:
+ # Stuff in the tag not explicitly handled by us needs to live through
+ # the life of the call
+ operation_call.references.extend(tag.references)
+ return records.Event(
+ event.type, event.success, user_tag, operation_call,
+ request_call_details, request_metadata, batch_operations)
+
+ def shutdown(self):
+ grpc.grpc_completion_queue_shutdown(self.c_completion_queue)
+ self.is_shutting_down = True
+
+ def clear(self):
+ if not self.is_shutting_down:
+ raise ValueError('queue must be shutting down to be cleared')
+ while self.poll().type != grpc.GRPC_QUEUE_SHUTDOWN:
+ pass
+
+ def __dealloc__(self):
+ if self.c_completion_queue != NULL:
+ # Ensure shutdown, pump the queue
+ if not self.is_shutting_down:
+ self.shutdown()
+ while not self.is_shutdown:
+ self.poll()
+ grpc.grpc_completion_queue_destroy(self.c_completion_queue)
diff --git a/src/python/src/grpc/_cython/_cygrpc/credentials.pxd b/src/python/src/grpc/_cython/_cygrpc/credentials.pxd
new file mode 100644
index 0000000000..6b74a267e0
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/credentials.pxd
@@ -0,0 +1,45 @@
+# 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.
+
+from grpc._cython._cygrpc cimport grpc
+
+
+cdef class ClientCredentials:
+
+ cdef grpc.grpc_credentials *c_credentials
+ cdef grpc.grpc_ssl_pem_key_cert_pair c_ssl_pem_key_cert_pair
+ cdef list references
+
+
+cdef class ServerCredentials:
+
+ cdef grpc.grpc_server_credentials *c_credentials
+ cdef grpc.grpc_ssl_pem_key_cert_pair *c_ssl_pem_key_cert_pairs
+ cdef size_t c_ssl_pem_key_cert_pairs_count
+ cdef list references
diff --git a/src/python/src/grpc/_cython/_cygrpc/credentials.pyx b/src/python/src/grpc/_cython/_cygrpc/credentials.pyx
new file mode 100644
index 0000000000..c14d8844dd
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/credentials.pyx
@@ -0,0 +1,217 @@
+# 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.
+
+from grpc._cython._cygrpc cimport records
+
+
+cdef class ClientCredentials:
+
+ def __cinit__(self):
+ self.c_credentials = NULL
+ self.c_ssl_pem_key_cert_pair.private_key = NULL
+ self.c_ssl_pem_key_cert_pair.certificate_chain = NULL
+ self.references = []
+
+ # The object *can* be invalid in Python if we fail to make the credentials
+ # (and the core thus returns NULL credentials). Used primarily for debugging.
+ @property
+ def is_valid(self):
+ return self.c_credentials != NULL
+
+ def __dealloc__(self):
+ if self.c_credentials != NULL:
+ grpc.grpc_credentials_release(self.c_credentials)
+
+
+cdef class ServerCredentials:
+
+ def __cinit__(self):
+ self.c_credentials = NULL
+
+ def __dealloc__(self):
+ if self.c_credentials != NULL:
+ grpc.grpc_server_credentials_release(self.c_credentials)
+
+
+def client_credentials_google_default():
+ cdef ClientCredentials credentials = ClientCredentials();
+ credentials.c_credentials = grpc.grpc_google_default_credentials_create()
+ return credentials
+
+def client_credentials_ssl(pem_root_certificates,
+ records.SslPemKeyCertPair ssl_pem_key_cert_pair):
+ if pem_root_certificates is None:
+ pass
+ elif isinstance(pem_root_certificates, bytes):
+ pass
+ elif isinstance(pem_root_certificates, basestring):
+ pem_root_certificates = pem_root_certificates.encode()
+ else:
+ raise TypeError("expected str or bytes for pem_root_certificates")
+ cdef ClientCredentials credentials = ClientCredentials()
+ cdef const char *c_pem_root_certificates = NULL
+ if pem_root_certificates is not None:
+ c_pem_root_certificates = pem_root_certificates
+ credentials.references.append(pem_root_certificates)
+ if ssl_pem_key_cert_pair is not None:
+ credentials.c_credentials = grpc.grpc_ssl_credentials_create(
+ c_pem_root_certificates, &ssl_pem_key_cert_pair.c_pair
+ )
+ credentials.references.append(ssl_pem_key_cert_pair)
+ else:
+ credentials.c_credentials = grpc.grpc_ssl_credentials_create(
+ c_pem_root_certificates, NULL
+ )
+
+def client_credentials_composite_credentials(
+ ClientCredentials credentials_1 not None,
+ ClientCredentials credentials_2 not None):
+ if not credentials_1.is_valid or not credentials_2.is_valid:
+ raise ValueError("passed credentials must both be valid")
+ cdef ClientCredentials credentials = ClientCredentials()
+ credentials.c_credentials = grpc.grpc_composite_credentials_create(
+ credentials_1.c_credentials, credentials_2.c_credentials)
+ credentials.references.append(credentials_1)
+ credentials.references.append(credentials_2)
+ return credentials
+
+def client_credentials_compute_engine():
+ cdef ClientCredentials credentials = ClientCredentials()
+ credentials.c_credentials = grpc.grpc_compute_engine_credentials_create()
+ return credentials
+
+def client_credentials_service_account(
+ json_key, scope, records.Timespec token_lifetime not None):
+ if isinstance(json_key, bytes):
+ pass
+ elif isinstance(json_key, basestring):
+ json_key = json_key.encode()
+ else:
+ raise TypeError("expected json_key to be str or bytes")
+ if isinstance(scope, bytes):
+ pass
+ elif isinstance(scope, basestring):
+ scope = scope.encode()
+ else:
+ raise TypeError("expected scope to be str or bytes")
+ cdef ClientCredentials credentials = ClientCredentials()
+ credentials.c_credentials = grpc.grpc_service_account_credentials_create(
+ json_key, scope, token_lifetime.c_time)
+ credentials.references.extend([json_key, scope])
+ return credentials
+
+def client_credentials_jwt(json_key, records.Timespec token_lifetime not None):
+ if isinstance(json_key, bytes):
+ pass
+ elif isinstance(json_key, basestring):
+ json_key = json_key.encode()
+ else:
+ raise TypeError("expected json_key to be str or bytes")
+ cdef ClientCredentials credentials = ClientCredentials()
+ credentials.c_credentials = grpc.grpc_jwt_credentials_create(
+ json_key, token_lifetime.c_time)
+ credentials.references.append(json_key)
+ return credentials
+
+def client_credentials_refresh_token(json_refresh_token):
+ if isinstance(json_refresh_token, bytes):
+ pass
+ elif isinstance(json_refresh_token, basestring):
+ json_refresh_token = json_refresh_token.encode()
+ else:
+ raise TypeError("expected json_refresh_token to be str or bytes")
+ cdef ClientCredentials credentials = ClientCredentials()
+ credentials.c_credentials = grpc.grpc_refresh_token_credentials_create(
+ json_refresh_token)
+ credentials.references.append(json_refresh_token)
+ return credentials
+
+def client_credentials_fake_transport_security():
+ cdef ClientCredentials credentials = ClientCredentials()
+ credentials.c_credentials = (
+ grpc.grpc_fake_transport_security_credentials_create())
+ return credentials
+
+def client_credentials_iam(authorization_token, authority_selector):
+ if isinstance(authorization_token, bytes):
+ pass
+ elif isinstance(authorization_token, basestring):
+ authorization_token = authorization_token.encode()
+ else:
+ raise TypeError("expected authorization_token to be str or bytes")
+ if isinstance(authority_selector, bytes):
+ pass
+ elif isinstance(authority_selector, basestring):
+ authority_selector = authority_selector.encode()
+ else:
+ raise TypeError("expected authority_selector to be str or bytes")
+ cdef ClientCredentials credentials = ClientCredentials()
+ credentials.c_credentials = grpc.grpc_iam_credentials_create(
+ authorization_token, authority_selector)
+ credentials.references.append(authorization_token)
+ credentials.references.append(authority_selector)
+ return credentials
+
+def server_credentials_ssl(pem_root_certs, pem_key_cert_pairs):
+ if pem_root_certs is None:
+ pass
+ elif isinstance(pem_root_certs, bytes):
+ pass
+ elif isinstance(pem_root_certs, basestring):
+ pem_root_certs = pem_root_certs.encode()
+ else:
+ raise TypeError("expected pem_root_certs to be str or bytes")
+ pem_key_cert_pairs = list(pem_key_cert_pairs)
+ for pair in pem_key_cert_pairs:
+ if not isinstance(pair, records.SslPemKeyCertPair):
+ raise TypeError("expected pem_key_cert_pairs to be sequence of "
+ "records.SslPemKeyCertPair")
+ cdef ServerCredentials credentials = ServerCredentials()
+ credentials.references.append(pem_key_cert_pairs)
+ credentials.references.append(pem_root_certs)
+ credentials.c_ssl_pem_key_cert_pairs_count = len(pem_key_cert_pairs)
+ credentials.c_ssl_pem_key_cert_pairs = (
+ <grpc.grpc_ssl_pem_key_cert_pair *>grpc.gpr_malloc(
+ sizeof(grpc.grpc_ssl_pem_key_cert_pair) *
+ credentials.c_ssl_pem_key_cert_pairs_count
+ ))
+ for i in range(credentials.c_ssl_pem_key_cert_pairs_count):
+ credentials.c_ssl_pem_key_cert_pairs[i] = (
+ (<records.SslPemKeyCertPair>pem_key_cert_pairs[i]).c_pair)
+ credentials.c_credentials = grpc.grpc_ssl_server_credentials_create(
+ pem_root_certs, credentials.c_ssl_pem_key_cert_pairs,
+ credentials.c_ssl_pem_key_cert_pairs_count
+ )
+ return credentials
+
+def server_credentials_fake_transport_security():
+ cdef ServerCredentials credentials = ServerCredentials()
+ credentials.c_credentials = (
+ grpc.grpc_fake_transport_security_server_credentials_create())
+ return credentials
diff --git a/src/python/src/grpc/_cython/_cygrpc/grpc.pxd b/src/python/src/grpc/_cython/_cygrpc/grpc.pxd
new file mode 100644
index 0000000000..7db8fbe31c
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/grpc.pxd
@@ -0,0 +1,344 @@
+# 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.
+
+cimport libc.time
+
+
+cdef extern from "grpc/support/alloc.h":
+ void *gpr_malloc(size_t size)
+ void gpr_free(void *ptr)
+ void *gpr_realloc(void *p, size_t size)
+
+cdef extern from "grpc/support/slice.h":
+ ctypedef struct gpr_slice:
+ # don't worry about writing out the members of gpr_slice; we never access
+ # them directly.
+ pass
+
+ gpr_slice gpr_slice_ref(gpr_slice s)
+ void gpr_slice_unref(gpr_slice s)
+ gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *))
+ gpr_slice gpr_slice_new_with_len(
+ void *p, size_t len, void (*destroy)(void *, size_t))
+ gpr_slice gpr_slice_malloc(size_t length)
+ gpr_slice gpr_slice_from_copied_string(const char *source)
+ gpr_slice gpr_slice_from_copied_buffer(const char *source, size_t len)
+
+ # Declare functions for function-like macros (because Cython)...
+ void *gpr_slice_start_ptr "GPR_SLICE_START_PTR" (gpr_slice s)
+ size_t gpr_slice_length "GPR_SLICE_LENGTH" (gpr_slice s)
+
+
+cdef extern from "grpc/support/port_platform.h":
+ # As long as the header file gets this type right, we don't need to get this
+ # type exactly; just close enough that the operations will be supported in the
+ # underlying C layers.
+ ctypedef unsigned int gpr_uint32
+
+
+cdef extern from "grpc/support/time.h":
+
+ ctypedef struct gpr_timespec:
+ libc.time.time_t seconds "tv_sec"
+ int nanoseconds "tv_nsec"
+
+ cdef gpr_timespec gpr_time_0
+ cdef gpr_timespec gpr_inf_future
+ cdef gpr_timespec gpr_inf_past
+
+ gpr_timespec gpr_now()
+
+
+cdef extern from "grpc/status.h":
+ ctypedef enum grpc_status_code:
+ GRPC_STATUS_OK
+ GRPC_STATUS_CANCELLED
+ GRPC_STATUS_UNKNOWN
+ GRPC_STATUS_INVALID_ARGUMENT
+ GRPC_STATUS_DEADLINE_EXCEEDED
+ GRPC_STATUS_NOT_FOUND
+ GRPC_STATUS_ALREADY_EXISTS
+ GRPC_STATUS_PERMISSION_DENIED
+ GRPC_STATUS_UNAUTHENTICATED
+ GRPC_STATUS_RESOURCE_EXHAUSTED
+ GRPC_STATUS_FAILED_PRECONDITION
+ GRPC_STATUS_ABORTED
+ GRPC_STATUS_OUT_OF_RANGE
+ GRPC_STATUS_UNIMPLEMENTED
+ GRPC_STATUS_INTERNAL
+ GRPC_STATUS_UNAVAILABLE
+ GRPC_STATUS_DATA_LOSS
+ GRPC_STATUS__DO_NOT_USE
+
+
+cdef extern from "grpc/byte_buffer_reader.h":
+ struct grpc_byte_buffer_reader:
+ # We don't care about the internals
+ pass
+
+
+cdef extern from "grpc/byte_buffer.h":
+ ctypedef struct grpc_byte_buffer:
+ # We don't care about the internals.
+ pass
+
+ grpc_byte_buffer *grpc_raw_byte_buffer_create(gpr_slice *slices,
+ size_t nslices)
+ size_t grpc_byte_buffer_length(grpc_byte_buffer *bb)
+ void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer)
+
+ void grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
+ grpc_byte_buffer *buffer)
+ int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader,
+ gpr_slice *slice)
+ void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader)
+
+
+cdef extern from "grpc/grpc.h":
+
+ ctypedef struct grpc_completion_queue:
+ # We don't care about the internals (and in fact don't know them)
+ pass
+
+ ctypedef struct grpc_channel:
+ # We don't care about the internals (and in fact don't know them)
+ pass
+
+ ctypedef struct grpc_server:
+ # We don't care about the internals (and in fact don't know them)
+ pass
+
+ ctypedef struct grpc_call:
+ # We don't care about the internals (and in fact don't know them)
+ pass
+
+ ctypedef enum grpc_arg_type:
+ grpc_arg_string "GRPC_ARG_STRING"
+ grpc_arg_integer "GRPC_ARG_INTEGER"
+ grpc_arg_pointer "GRPC_ARG_POINTER"
+
+ ctypedef struct grpc_arg_value_pointer:
+ void *address "p"
+ void *(*copy)(void *)
+ void (*destroy)(void *)
+
+ union grpc_arg_value:
+ char *string
+ int integer
+ grpc_arg_value_pointer pointer
+
+ ctypedef struct grpc_arg:
+ grpc_arg_type type
+ char *key
+ grpc_arg_value value
+
+ ctypedef struct grpc_channel_args:
+ size_t arguments_length "num_args"
+ grpc_arg *arguments "args"
+
+ ctypedef enum grpc_call_error:
+ GRPC_CALL_OK
+ GRPC_CALL_ERROR
+ GRPC_CALL_ERROR_NOT_ON_SERVER
+ GRPC_CALL_ERROR_NOT_ON_CLIENT
+ GRPC_CALL_ERROR_ALREADY_ACCEPTED
+ GRPC_CALL_ERROR_ALREADY_INVOKED
+ GRPC_CALL_ERROR_NOT_INVOKED
+ GRPC_CALL_ERROR_ALREADY_FINISHED
+ GRPC_CALL_ERROR_TOO_MANY_OPERATIONS
+ GRPC_CALL_ERROR_INVALID_FLAGS
+ GRPC_CALL_ERROR_INVALID_METADATA
+
+ ctypedef struct grpc_metadata:
+ const char *key
+ const char *value
+ size_t value_length
+ # ignore the 'internal_data.obfuscated' fields.
+
+ ctypedef enum grpc_completion_type:
+ GRPC_QUEUE_SHUTDOWN
+ GRPC_QUEUE_TIMEOUT
+ GRPC_OP_COMPLETE
+
+ ctypedef struct grpc_event:
+ grpc_completion_type type
+ int success
+ void *tag
+
+ ctypedef struct grpc_metadata_array:
+ size_t count
+ size_t capacity
+ grpc_metadata *metadata
+
+ void grpc_metadata_array_init(grpc_metadata_array *array)
+ void grpc_metadata_array_destroy(grpc_metadata_array *array)
+
+ ctypedef struct grpc_call_details:
+ char *method
+ size_t method_capacity
+ char *host
+ size_t host_capacity
+ gpr_timespec deadline
+
+ void grpc_call_details_init(grpc_call_details *details)
+ void grpc_call_details_destroy(grpc_call_details *details)
+
+ ctypedef enum grpc_op_type:
+ GRPC_OP_SEND_INITIAL_METADATA
+ GRPC_OP_SEND_MESSAGE
+ GRPC_OP_SEND_CLOSE_FROM_CLIENT
+ GRPC_OP_SEND_STATUS_FROM_SERVER
+ GRPC_OP_RECV_INITIAL_METADATA
+ GRPC_OP_RECV_MESSAGE
+ GRPC_OP_RECV_STATUS_ON_CLIENT
+ GRPC_OP_RECV_CLOSE_ON_SERVER
+
+ ctypedef struct grpc_op_data_send_initial_metadata:
+ size_t count
+ grpc_metadata *metadata
+
+ ctypedef struct grpc_op_data_send_status_from_server:
+ size_t trailing_metadata_count
+ grpc_metadata *trailing_metadata
+ grpc_status_code status
+ const char *status_details
+
+ ctypedef struct grpc_op_data_recv_status_on_client:
+ grpc_metadata_array *trailing_metadata
+ grpc_status_code *status
+ char **status_details
+ size_t *status_details_capacity
+
+ ctypedef struct grpc_op_data_recv_close_on_server:
+ int *cancelled
+
+ union grpc_op_data:
+ grpc_op_data_send_initial_metadata send_initial_metadata
+ grpc_byte_buffer *send_message
+ grpc_op_data_send_status_from_server send_status_from_server
+ grpc_metadata_array *receive_initial_metadata "recv_initial_metadata"
+ grpc_byte_buffer **receive_message "recv_message"
+ grpc_op_data_recv_status_on_client receive_status_on_client "recv_status_on_client"
+ grpc_op_data_recv_close_on_server receive_close_on_server "recv_close_on_server"
+
+ ctypedef struct grpc_op:
+ grpc_op_type type "op"
+ gpr_uint32 flags
+ grpc_op_data data
+
+ void grpc_init()
+ void grpc_shutdown()
+
+ grpc_completion_queue *grpc_completion_queue_create()
+ grpc_event grpc_completion_queue_next(grpc_completion_queue *cq,
+ gpr_timespec deadline) nogil
+ void grpc_completion_queue_shutdown(grpc_completion_queue *cq)
+ void grpc_completion_queue_destroy(grpc_completion_queue *cq)
+
+ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
+ size_t nops, void *tag)
+ grpc_call_error grpc_call_cancel(grpc_call *call)
+ grpc_call_error grpc_call_cancel_with_status(grpc_call *call,
+ grpc_status_code status,
+ const char *description)
+ void grpc_call_destroy(grpc_call *call)
+
+
+ grpc_channel *grpc_channel_create(const char *target,
+ const grpc_channel_args *args)
+ grpc_call *grpc_channel_create_call(grpc_channel *channel,
+ grpc_completion_queue *completion_queue,
+ const char *method, const char *host,
+ gpr_timespec deadline)
+ void grpc_channel_destroy(grpc_channel *channel)
+
+ grpc_server *grpc_server_create(const grpc_channel_args *args)
+ grpc_call_error grpc_server_request_call(
+ grpc_server *server, grpc_call **call, grpc_call_details *details,
+ grpc_metadata_array *request_metadata, grpc_completion_queue
+ *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void
+ *tag_new)
+ void grpc_server_register_completion_queue(grpc_server *server,
+ grpc_completion_queue *cq)
+ int grpc_server_add_http2_port(grpc_server *server, const char *addr)
+ void grpc_server_start(grpc_server *server)
+ void grpc_server_shutdown_and_notify(
+ grpc_server *server, grpc_completion_queue *cq, void *tag)
+ void grpc_server_cancel_all_calls(grpc_server *server)
+ void grpc_server_destroy(grpc_server *server)
+
+
+cdef extern from "grpc/grpc_security.h":
+
+ ctypedef struct grpc_ssl_pem_key_cert_pair:
+ const char *private_key
+ const char *certificate_chain "cert_chain"
+
+ ctypedef struct grpc_credentials:
+ # We don't care about the internals (and in fact don't know them)
+ pass
+
+ grpc_credentials *grpc_google_default_credentials_create()
+ grpc_credentials *grpc_ssl_credentials_create(
+ const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair)
+
+ grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
+ grpc_credentials *creds2)
+ grpc_credentials *grpc_compute_engine_credentials_create()
+ grpc_credentials *grpc_service_account_credentials_create(
+ const char *json_key, const char *scope, gpr_timespec token_lifetime)
+ grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
+ gpr_timespec token_lifetime)
+ grpc_credentials *grpc_refresh_token_credentials_create(
+ const char *json_refresh_token)
+ grpc_credentials *grpc_fake_transport_security_credentials_create()
+ grpc_credentials *grpc_iam_credentials_create(const char *authorization_token,
+ const char *authority_selector)
+ void grpc_credentials_release(grpc_credentials *creds)
+
+ grpc_channel *grpc_secure_channel_create(
+ grpc_credentials *creds, const char *target,
+ const grpc_channel_args *args)
+
+ ctypedef struct grpc_server_credentials:
+ # We don't care about the internals (and in fact don't know them)
+ pass
+
+ grpc_server_credentials *grpc_ssl_server_credentials_create(
+ const char *pem_root_certs,
+ grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
+ size_t num_key_cert_pairs);
+ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create()
+ void grpc_server_credentials_release(grpc_server_credentials *creds)
+
+ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
+ grpc_server_credentials *creds)
+
+ grpc_call_error grpc_call_set_credentials(grpc_call *call,
+ grpc_credentials *creds)
diff --git a/src/python/src/grpc/_cython/_cygrpc/records.pxd b/src/python/src/grpc/_cython/_cygrpc/records.pxd
new file mode 100644
index 0000000000..9ee487882a
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/records.pxd
@@ -0,0 +1,129 @@
+# 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.
+
+from grpc._cython._cygrpc cimport grpc
+from grpc._cython._cygrpc cimport call
+from grpc._cython._cygrpc cimport server
+
+
+cdef class Timespec:
+
+ cdef grpc.gpr_timespec c_time
+
+
+cdef class CallDetails:
+
+ cdef grpc.grpc_call_details c_details
+
+
+cdef class OperationTag:
+
+ cdef object user_tag
+ cdef list references
+ # This allows CompletionQueue to notify the Python Server object that the
+ # underlying GRPC core server has shutdown
+ cdef server.Server shutting_down_server
+ cdef call.Call operation_call
+ cdef CallDetails request_call_details
+ cdef Metadata request_metadata
+ cdef Operations batch_operations
+ cdef bint is_new_request
+
+
+cdef class Event:
+
+ cdef readonly grpc.grpc_completion_type type
+ cdef readonly bint success
+ cdef readonly object tag
+
+ # For operations with calls
+ cdef readonly call.Call operation_call
+
+ # For Server.request_call
+ cdef readonly CallDetails request_call_details
+ cdef readonly Metadata request_metadata
+
+ # For Call.start_batch
+ cdef readonly Operations batch_operations
+
+
+cdef class ByteBuffer:
+
+ cdef grpc.grpc_byte_buffer *c_byte_buffer
+
+
+cdef class SslPemKeyCertPair:
+
+ cdef grpc.grpc_ssl_pem_key_cert_pair c_pair
+ cdef readonly object private_key, certificate_chain
+
+
+cdef class ChannelArg:
+
+ cdef grpc.grpc_arg c_arg
+ cdef readonly object key, value
+
+
+cdef class ChannelArgs:
+
+ cdef grpc.grpc_channel_args c_args
+ cdef list args
+
+
+cdef class Metadatum:
+
+ cdef grpc.grpc_metadata c_metadata
+ cdef object _key, _value
+
+
+cdef class Metadata:
+
+ cdef grpc.grpc_metadata_array c_metadata_array
+ cdef object metadata
+
+
+cdef class Operation:
+
+ cdef grpc.grpc_op c_op
+ cdef ByteBuffer _received_message
+ cdef Metadata _received_metadata
+ cdef grpc.grpc_status_code _received_status_code
+ cdef char *_received_status_details
+ cdef size_t _received_status_details_capacity
+ cdef int _received_cancelled
+ cdef readonly bint is_valid
+ cdef object references
+
+
+cdef class Operations:
+
+ cdef grpc.grpc_op *c_ops
+ cdef size_t c_nops
+ cdef list operations
+
diff --git a/src/python/src/grpc/_cython/_cygrpc/records.pyx b/src/python/src/grpc/_cython/_cygrpc/records.pyx
new file mode 100644
index 0000000000..4814769fd2
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/records.pyx
@@ -0,0 +1,575 @@
+# 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.
+
+from grpc._cython._cygrpc cimport grpc
+from grpc._cython._cygrpc cimport call
+from grpc._cython._cygrpc cimport server
+
+
+class StatusCode:
+ ok = grpc.GRPC_STATUS_OK
+ cancelled = grpc.GRPC_STATUS_CANCELLED
+ unknown = grpc.GRPC_STATUS_UNKNOWN
+ invalid_argument = grpc.GRPC_STATUS_INVALID_ARGUMENT
+ deadline_exceeded = grpc.GRPC_STATUS_DEADLINE_EXCEEDED
+ not_found = grpc.GRPC_STATUS_NOT_FOUND
+ already_exists = grpc.GRPC_STATUS_ALREADY_EXISTS
+ permission_denied = grpc.GRPC_STATUS_PERMISSION_DENIED
+ unauthenticated = grpc.GRPC_STATUS_UNAUTHENTICATED
+ resource_exhausted = grpc.GRPC_STATUS_RESOURCE_EXHAUSTED
+ failed_precondition = grpc.GRPC_STATUS_FAILED_PRECONDITION
+ aborted = grpc.GRPC_STATUS_ABORTED
+ out_of_range = grpc.GRPC_STATUS_OUT_OF_RANGE
+ unimplemented = grpc.GRPC_STATUS_UNIMPLEMENTED
+ internal = grpc.GRPC_STATUS_INTERNAL
+ unavailable = grpc.GRPC_STATUS_UNAVAILABLE
+ data_loss = grpc.GRPC_STATUS_DATA_LOSS
+
+
+class CallError:
+ ok = grpc.GRPC_CALL_OK
+ error = grpc.GRPC_CALL_ERROR
+ not_on_server = grpc.GRPC_CALL_ERROR_NOT_ON_SERVER
+ not_on_client = grpc.GRPC_CALL_ERROR_NOT_ON_CLIENT
+ already_accepted = grpc.GRPC_CALL_ERROR_ALREADY_ACCEPTED
+ already_invoked = grpc.GRPC_CALL_ERROR_ALREADY_INVOKED
+ not_invoked = grpc.GRPC_CALL_ERROR_NOT_INVOKED
+ already_finished = grpc.GRPC_CALL_ERROR_ALREADY_FINISHED
+ too_many_operations = grpc.GRPC_CALL_ERROR_TOO_MANY_OPERATIONS
+ invalid_flags = grpc.GRPC_CALL_ERROR_INVALID_FLAGS
+ invalid_metadata = grpc.GRPC_CALL_ERROR_INVALID_METADATA
+
+
+class CompletionType:
+ queue_shutdown = grpc.GRPC_QUEUE_SHUTDOWN
+ queue_timeout = grpc.GRPC_QUEUE_TIMEOUT
+ operation_complete = grpc.GRPC_OP_COMPLETE
+
+
+class OperationType:
+ send_initial_metadata = grpc.GRPC_OP_SEND_INITIAL_METADATA
+ send_message = grpc.GRPC_OP_SEND_MESSAGE
+ send_close_from_client = grpc.GRPC_OP_SEND_CLOSE_FROM_CLIENT
+ send_status_from_server = grpc.GRPC_OP_SEND_STATUS_FROM_SERVER
+ receive_initial_metadata = grpc.GRPC_OP_RECV_INITIAL_METADATA
+ receive_message = grpc.GRPC_OP_RECV_MESSAGE
+ receive_status_on_client = grpc.GRPC_OP_RECV_STATUS_ON_CLIENT
+ receive_close_on_server = grpc.GRPC_OP_RECV_CLOSE_ON_SERVER
+
+
+cdef class Timespec:
+
+ def __cinit__(self, time):
+ if time is None:
+ self.c_time = grpc.gpr_now()
+ elif isinstance(time, float):
+ if time == float("+inf"):
+ self.c_time = grpc.gpr_inf_future
+ elif time == float("-inf"):
+ self.c_time = grpc.gpr_inf_past
+ else:
+ self.c_time.seconds = time
+ self.c_time.nanoseconds = (time - float(self.c_time.seconds)) * 1e9
+ else:
+ raise TypeError("expected time to be float")
+
+ @property
+ def seconds(self):
+ return self.c_time.seconds
+
+ @property
+ def nanoseconds(self):
+ return self.c_time.nanoseconds
+
+ def __float__(self):
+ return <double>self.c_time.seconds + <double>self.c_time.nanoseconds / 1e9
+
+ infinite_future = Timespec(float("+inf"))
+ infinite_past = Timespec(float("-inf"))
+
+
+cdef class CallDetails:
+
+ def __cinit__(self):
+ grpc.grpc_call_details_init(&self.c_details)
+
+ def __dealloc__(self):
+ grpc.grpc_call_details_destroy(&self.c_details)
+
+ @property
+ def method(self):
+ if self.c_details.method != NULL:
+ return <bytes>self.c_details.method
+ else:
+ return None
+
+ @property
+ def host(self):
+ if self.c_details.host != NULL:
+ return <bytes>self.c_details.host
+ else:
+ return None
+
+ @property
+ def deadline(self):
+ timespec = Timespec(float("-inf"))
+ timespec.c_time = self.c_details.deadline
+ return timespec
+
+
+cdef class OperationTag:
+
+ def __cinit__(self, user_tag):
+ self.user_tag = user_tag
+ self.references = []
+
+
+cdef class Event:
+
+ def __cinit__(self, grpc.grpc_completion_type type, bint success,
+ object tag, call.Call operation_call,
+ CallDetails request_call_details,
+ Metadata request_metadata,
+ Operations batch_operations):
+ self.type = type
+ self.success = success
+ self.tag = tag
+ self.operation_call = operation_call
+ self.request_call_details = request_call_details
+ self.request_metadata = request_metadata
+ self.batch_operations = batch_operations
+
+
+cdef class ByteBuffer:
+
+ def __cinit__(self, data):
+ if data is None:
+ self.c_byte_buffer = NULL
+ return
+ if isinstance(data, bytes):
+ pass
+ elif isinstance(data, basestring):
+ data = data.encode()
+ else:
+ raise TypeError("expected value to be of type str or bytes")
+
+ cdef char *c_data = data
+ data_slice = grpc.gpr_slice_from_copied_buffer(c_data, len(data))
+ self.c_byte_buffer = grpc.grpc_raw_byte_buffer_create(
+ &data_slice, 1)
+ grpc.gpr_slice_unref(data_slice)
+
+ def bytes(self):
+ cdef grpc.grpc_byte_buffer_reader reader
+ cdef grpc.gpr_slice data_slice
+ cdef size_t data_slice_length
+ cdef void *data_slice_pointer
+ if self.c_byte_buffer != NULL:
+ grpc.grpc_byte_buffer_reader_init(&reader, self.c_byte_buffer)
+ result = b""
+ while grpc.grpc_byte_buffer_reader_next(&reader, &data_slice):
+ data_slice_pointer = grpc.gpr_slice_start_ptr(data_slice)
+ data_slice_length = grpc.gpr_slice_length(data_slice)
+ result += (<char *>data_slice_pointer)[:data_slice_length]
+ grpc.grpc_byte_buffer_reader_destroy(&reader)
+ return result
+ else:
+ return None
+
+ def __len__(self):
+ if self.c_byte_buffer != NULL:
+ return grpc.grpc_byte_buffer_length(self.c_byte_buffer)
+ else:
+ return 0
+
+ def __str__(self):
+ return self.bytes()
+
+ def __dealloc__(self):
+ if self.c_byte_buffer != NULL:
+ grpc.grpc_byte_buffer_destroy(self.c_byte_buffer)
+
+
+cdef class SslPemKeyCertPair:
+
+ def __cinit__(self, private_key, certificate_chain):
+ if isinstance(private_key, bytes):
+ self.private_key = private_key
+ elif isinstance(private_key, basestring):
+ self.private_key = private_key.encode()
+ else:
+ raise TypeError("expected private_key to be of type str or bytes")
+ if isinstance(certificate_chain, bytes):
+ self.certificate_chain = certificate_chain
+ elif isinstance(certificate_chain, basestring):
+ self.certificate_chain = certificate_chain.encode()
+ else:
+ raise TypeError("expected certificate_chain to be of type str or bytes "
+ "or int")
+ self.c_pair.private_key = self.private_key
+ self.c_pair.certificate_chain = self.certificate_chain
+
+
+cdef class ChannelArg:
+
+ def __cinit__(self, key, value):
+ if isinstance(key, bytes):
+ self.key = key
+ elif isinstance(key, basestring):
+ self.key = key.encode()
+ else:
+ raise TypeError("expected key to be of type str or bytes")
+ if isinstance(value, bytes):
+ self.value = value
+ self.c_arg.type = grpc.GRPC_ARG_STRING
+ self.c_arg.value.string = self.value
+ elif isinstance(value, basestring):
+ self.value = value.encode()
+ self.c_arg.type = grpc.GRPC_ARG_STRING
+ self.c_arg.value.string = self.value
+ elif isinstance(value, int):
+ self.value = int(value)
+ self.c_arg.type = grpc.GRPC_ARG_INTEGER
+ self.c_arg.value.integer = self.value
+ else:
+ raise TypeError("expected value to be of type str or bytes or int")
+ self.c_arg.key = self.key
+
+
+cdef class ChannelArgs:
+
+ def __cinit__(self, args):
+ self.args = list(args)
+ for arg in self.args:
+ if not isinstance(arg, ChannelArg):
+ raise TypeError("expected list of ChannelArg")
+ self.c_args.arguments_length = len(self.args)
+ self.c_args.arguments = <grpc.grpc_arg *>grpc.gpr_malloc(
+ self.c_args.arguments_length*sizeof(grpc.grpc_arg)
+ )
+ for i in range(self.c_args.arguments_length):
+ self.c_args.arguments[i] = (<ChannelArg>self.args[i]).c_arg
+
+ def __dealloc__(self):
+ grpc.gpr_free(self.c_args.arguments)
+
+ def __len__(self):
+ # self.args is never stale; it's only updated from this file
+ return len(self.args)
+
+ def __getitem__(self, size_t i):
+ # self.args is never stale; it's only updated from this file
+ return self.args[i]
+
+
+cdef class Metadatum:
+
+ def __cinit__(self, key, value):
+ if isinstance(key, bytes):
+ self._key = key
+ elif isinstance(key, basestring):
+ self._key = key.encode()
+ else:
+ raise TypeError("expected key to be of type str or bytes")
+ if isinstance(value, bytes):
+ self._value = value
+ elif isinstance(value, basestring):
+ self._value = value.encode()
+ else:
+ raise TypeError("expected value to be of type str or bytes")
+ self.c_metadata.key = self._key
+ self.c_metadata.value = self._value
+ self.c_metadata.value_length = len(self._value)
+
+ @property
+ def key(self):
+ return <bytes>self.c_metadata.key
+
+ @property
+ def value(self):
+ return <bytes>self.c_metadata.value[:self.c_metadata.value_length]
+
+ def __len__(self):
+ return 2
+
+ def __getitem__(self, size_t i):
+ if i == 0:
+ return self.key
+ elif i == 1:
+ return self.value
+ else:
+ raise IndexError("index must be 0 (key) or 1 (value)")
+
+ def __iter__(self):
+ return iter((self.key, self.value))
+
+
+cdef class _MetadataIterator:
+
+ cdef size_t i
+ cdef Metadata metadata
+
+ def __cinit__(self, Metadata metadata not None):
+ self.i = 0
+ self.metadata = metadata
+
+ def __next__(self):
+ if self.i < len(self.metadata):
+ result = self.metadata[self.i]
+ self.i = self.i + 1
+ return result
+ else:
+ raise StopIteration()
+
+
+cdef class Metadata:
+
+ def __cinit__(self, metadata):
+ self.metadata = list(metadata)
+ for metadatum in metadata:
+ if not isinstance(metadatum, Metadatum):
+ raise TypeError("expected list of Metadatum")
+ grpc.grpc_metadata_array_init(&self.c_metadata_array)
+ self.c_metadata_array.count = len(self.metadata)
+ self.c_metadata_array.capacity = len(self.metadata)
+ self.c_metadata_array.metadata = <grpc.grpc_metadata *>grpc.gpr_malloc(
+ self.c_metadata_array.count*sizeof(grpc.grpc_metadata)
+ )
+ for i in range(self.c_metadata_array.count):
+ self.c_metadata_array.metadata[i] = (
+ (<Metadatum>self.metadata[i]).c_metadata)
+
+ def __dealloc__(self):
+ # this frees the allocated memory for the grpc_metadata_array (although
+ # it'd be nice if that were documented somewhere...) TODO(atash): document
+ # this in the C core
+ grpc.grpc_metadata_array_destroy(&self.c_metadata_array)
+
+ def __len__(self):
+ return self.c_metadata_array.count
+
+ def __getitem__(self, size_t i):
+ return Metadatum(
+ key=<bytes>self.c_metadata_array.metadata[i].key,
+ value=<bytes>self.c_metadata_array.metadata[i].value[
+ :self.c_metadata_array.metadata[i].value_length])
+
+ def __iter__(self):
+ return _MetadataIterator(self)
+
+
+cdef class Operation:
+
+ def __cinit__(self):
+ self.references = []
+ self._received_status_details = NULL
+ self._received_status_details_capacity = 0
+ self.is_valid = False
+
+ @property
+ def type(self):
+ return self.c_op.type
+
+ @property
+ def received_message(self):
+ if self.c_op.type != grpc.GRPC_OP_RECV_MESSAGE:
+ raise TypeError("self must be an operation receiving a message")
+ return self._received_message
+
+ @property
+ def received_metadata(self):
+ if (self.c_op.type != grpc.GRPC_OP_RECV_INITIAL_METADATA and
+ self.c_op.type != grpc.GRPC_OP_RECV_STATUS_ON_CLIENT):
+ raise TypeError("self must be an operation receiving metadata")
+ return self._received_metadata
+
+ @property
+ def received_status_code(self):
+ if self.c_op.type != grpc.GRPC_OP_RECV_STATUS_ON_CLIENT:
+ raise TypeError("self must be an operation receiving a status code")
+ return self._received_status_code
+
+ @property
+ def received_status_details(self):
+ if self.c_op.type != grpc.GRPC_OP_RECV_STATUS_ON_CLIENT:
+ raise TypeError("self must be an operation receiving status details")
+ if self._received_status_details:
+ return self._received_status_details
+ else:
+ return None
+
+ @property
+ def received_cancelled(self):
+ if self.c_op.type != grpc.GRPC_OP_RECV_CLOSE_ON_SERVER:
+ raise TypeError("self must be an operation receiving cancellation "
+ "information")
+ return False if self._received_cancelled == 0 else True
+
+ def __dealloc__(self):
+ # We *almost* don't need to do anything; most of the objects are handled by
+ # Python. The remaining one(s) are primitive fields filled in by GRPC core.
+ # This means that we need to clean up after receive_status_on_client.
+ if self.c_op.type == grpc.GRPC_OP_RECV_STATUS_ON_CLIENT:
+ grpc.gpr_free(self._received_status_details)
+
+def operation_send_initial_metadata(Metadata metadata):
+ cdef Operation op = Operation()
+ op.c_op.type = grpc.GRPC_OP_SEND_INITIAL_METADATA
+ op.c_op.data.send_initial_metadata.count = metadata.c_metadata_array.count
+ op.c_op.data.send_initial_metadata.metadata = (
+ metadata.c_metadata_array.metadata)
+ op.references.append(metadata)
+ op.is_valid = True
+ return op
+
+def operation_send_message(data):
+ cdef Operation op = Operation()
+ op.c_op.type = grpc.GRPC_OP_SEND_MESSAGE
+ byte_buffer = ByteBuffer(data)
+ op.c_op.data.send_message = byte_buffer.c_byte_buffer
+ op.references.append(byte_buffer)
+ op.is_valid = True
+ return op
+
+def operation_send_close_from_client():
+ cdef Operation op = Operation()
+ op.c_op.type = grpc.GRPC_OP_SEND_CLOSE_FROM_CLIENT
+ op.is_valid = True
+ return op
+
+def operation_send_status_from_server(
+ Metadata metadata, grpc.grpc_status_code code, details):
+ if isinstance(details, bytes):
+ pass
+ elif isinstance(details, basestring):
+ details = details.encode()
+ else:
+ raise TypeError("expected a str or bytes object for details")
+ cdef Operation op = Operation()
+ op.c_op.type = grpc.GRPC_OP_SEND_STATUS_FROM_SERVER
+ op.c_op.data.send_status_from_server.trailing_metadata_count = (
+ metadata.c_metadata_array.count)
+ op.c_op.data.send_status_from_server.trailing_metadata = (
+ metadata.c_metadata_array.metadata)
+ op.c_op.data.send_status_from_server.status = code
+ op.c_op.data.send_status_from_server.status_details = details
+ op.references.append(metadata)
+ op.references.append(details)
+ op.is_valid = True
+ return op
+
+def operation_receive_initial_metadata():
+ cdef Operation op = Operation()
+ op.c_op.type = grpc.GRPC_OP_RECV_INITIAL_METADATA
+ op._received_metadata = Metadata([])
+ op.c_op.data.receive_initial_metadata = (
+ &op._received_metadata.c_metadata_array)
+ op.is_valid = True
+ return op
+
+def operation_receive_message():
+ cdef Operation op = Operation()
+ op.c_op.type = grpc.GRPC_OP_RECV_MESSAGE
+ op._received_message = ByteBuffer(None)
+ # n.b. the c_op.data.receive_message field needs to be deleted by us,
+ # anyway, so we just let that be handled by the ByteBuffer() we allocated
+ # the line before.
+ op.c_op.data.receive_message = &op._received_message.c_byte_buffer
+ op.is_valid = True
+ return op
+
+def operation_receive_status_on_client():
+ cdef Operation op = Operation()
+ op.c_op.type = grpc.GRPC_OP_RECV_STATUS_ON_CLIENT
+ op._received_metadata = Metadata([])
+ op.c_op.data.receive_status_on_client.trailing_metadata = (
+ &op._received_metadata.c_metadata_array)
+ op.c_op.data.receive_status_on_client.status = (
+ &op._received_status_code)
+ op.c_op.data.receive_status_on_client.status_details = (
+ &op._received_status_details)
+ op.c_op.data.receive_status_on_client.status_details_capacity = (
+ &op._received_status_details_capacity)
+ op.is_valid = True
+ return op
+
+def operation_receive_close_on_server():
+ cdef Operation op = Operation()
+ op.c_op.type = grpc.GRPC_OP_RECV_CLOSE_ON_SERVER
+ op.c_op.data.receive_close_on_server.cancelled = &op._received_cancelled
+ op.is_valid = True
+ return op
+
+
+cdef class _OperationsIterator:
+
+ cdef size_t i
+ cdef Operations operations
+
+ def __cinit__(self, Operations operations not None):
+ self.i = 0
+ self.operations = operations
+
+ def __next__(self):
+ if self.i < len(self.operations):
+ result = self.operations[self.i]
+ self.i = self.i + 1
+ return result
+ else:
+ raise StopIteration()
+
+
+cdef class Operations:
+
+ def __cinit__(self, operations):
+ self.operations = list(operations) # normalize iterable
+ self.c_ops = NULL
+ self.c_nops = 0
+ for operation in self.operations:
+ if not isinstance(operation, Operation):
+ raise TypeError("expected operations to be iterable of Operation")
+ self.c_nops = len(self.operations)
+ self.c_ops = <grpc.grpc_op *>grpc.gpr_malloc(
+ sizeof(grpc.grpc_op)*self.c_nops)
+ for i in range(self.c_nops):
+ self.c_ops[i] = (<Operation>(self.operations[i])).c_op
+
+ def __len__(self):
+ return self.c_nops
+
+ def __getitem__(self, size_t i):
+ # self.operations is never stale; it's only updated from this file
+ return self.operations[i]
+
+ def __dealloc__(self):
+ grpc.gpr_free(self.c_ops)
+
+ def __iter__(self):
+ return _OperationsIterator(self)
+
diff --git a/src/python/src/grpc/_cython/_cygrpc/server.pxd b/src/python/src/grpc/_cython/_cygrpc/server.pxd
new file mode 100644
index 0000000000..0257542a03
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/server.pxd
@@ -0,0 +1,45 @@
+# 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.
+
+from grpc._cython._cygrpc cimport grpc
+from grpc._cython._cygrpc cimport completion_queue
+
+
+cdef class Server:
+
+ cdef grpc.grpc_server *c_server
+ cdef bint is_started # start has been called
+ cdef bint is_shutting_down # shutdown has been called
+ cdef bint is_shutdown # notification of complete shutdown received
+ # used at dealloc when user forgets to shutdown
+ cdef completion_queue.CompletionQueue backup_shutdown_queue
+ cdef list references
+ cdef list registered_completion_queues
+
+ cdef notify_shutdown_complete(self)
diff --git a/src/python/src/grpc/_cython/_cygrpc/server.pyx b/src/python/src/grpc/_cython/_cygrpc/server.pyx
new file mode 100644
index 0000000000..dcf9d38337
--- /dev/null
+++ b/src/python/src/grpc/_cython/_cygrpc/server.pyx
@@ -0,0 +1,158 @@
+# 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.
+
+cimport cpython
+
+from grpc._cython._cygrpc cimport call
+from grpc._cython._cygrpc cimport completion_queue
+from grpc._cython._cygrpc cimport credentials
+from grpc._cython._cygrpc cimport records
+
+import time
+
+
+cdef class Server:
+
+ def __cinit__(self, records.ChannelArgs arguments=None):
+ cdef grpc.grpc_channel_args *c_arguments = NULL
+ self.references = []
+ self.registered_completion_queues = []
+ if arguments is not None:
+ c_arguments = &arguments.c_args
+ self.references.append(arguments)
+ self.c_server = grpc.grpc_server_create(c_arguments)
+ self.is_started = False
+ self.is_shutting_down = False
+ self.is_shutdown = False
+
+ def request_call(
+ self, completion_queue.CompletionQueue call_queue not None,
+ completion_queue.CompletionQueue server_queue not None, tag):
+ if not self.is_started or self.is_shutting_down:
+ raise ValueError("server must be started and not shutting down")
+ if server_queue not in self.registered_completion_queues:
+ raise ValueError("server_queue must be a registered completion queue")
+ cdef records.OperationTag operation_tag = records.OperationTag(tag)
+ operation_tag.operation_call = call.Call()
+ operation_tag.request_call_details = records.CallDetails()
+ operation_tag.request_metadata = records.Metadata([])
+ operation_tag.references.extend([self, call_queue, server_queue])
+ operation_tag.is_new_request = True
+ operation_tag.batch_operations = records.Operations([])
+ cpython.Py_INCREF(operation_tag)
+ return grpc.grpc_server_request_call(
+ self.c_server, &operation_tag.operation_call.c_call,
+ &operation_tag.request_call_details.c_details,
+ &operation_tag.request_metadata.c_metadata_array,
+ call_queue.c_completion_queue, server_queue.c_completion_queue,
+ <cpython.PyObject *>operation_tag)
+
+ def register_completion_queue(
+ self, completion_queue.CompletionQueue queue not None):
+ if self.is_started:
+ raise ValueError("cannot register completion queues after start")
+ grpc.grpc_server_register_completion_queue(
+ self.c_server, queue.c_completion_queue)
+ self.registered_completion_queues.append(queue)
+
+ def start(self):
+ if self.is_started:
+ raise ValueError("the server has already started")
+ self.backup_shutdown_queue = completion_queue.CompletionQueue()
+ self.register_completion_queue(self.backup_shutdown_queue)
+ self.is_started = True
+ grpc.grpc_server_start(self.c_server)
+
+ def add_http2_port(self, address,
+ credentials.ServerCredentials server_credentials=None):
+ if isinstance(address, bytes):
+ pass
+ elif isinstance(address, basestring):
+ address = address.encode()
+ else:
+ raise TypeError("expected address to be a str or bytes")
+ self.references.append(address)
+ if server_credentials is not None:
+ self.references.append(server_credentials)
+ return grpc.grpc_server_add_secure_http2_port(
+ self.c_server, address, server_credentials.c_credentials)
+ else:
+ return grpc.grpc_server_add_http2_port(self.c_server, address)
+
+ def shutdown(self, completion_queue.CompletionQueue queue not None, tag):
+ cdef records.OperationTag operation_tag
+ if queue.is_shutting_down:
+ raise ValueError("queue must be live")
+ elif not self.is_started:
+ raise ValueError("the server hasn't started yet")
+ elif self.is_shutting_down:
+ return
+ elif queue not in self.registered_completion_queues:
+ raise ValueError("expected registered completion queue")
+ else:
+ self.is_shutting_down = True
+ operation_tag = records.OperationTag(tag)
+ operation_tag.shutting_down_server = self
+ operation_tag.references.extend([self, queue])
+ cpython.Py_INCREF(operation_tag)
+ grpc.grpc_server_shutdown_and_notify(
+ self.c_server, queue.c_completion_queue,
+ <cpython.PyObject *>operation_tag)
+
+ cdef notify_shutdown_complete(self):
+ # called only by a completion queue on receiving our shutdown operation tag
+ self.is_shutdown = True
+
+ def cancel_all_calls(self):
+ if not self.is_shutting_down:
+ raise ValueError("the server must be shutting down to cancel all calls")
+ elif self.is_shutdown:
+ return
+ else:
+ grpc.grpc_server_cancel_all_calls(self.c_server)
+
+ def __dealloc__(self):
+ if self.c_server != NULL:
+ if not self.is_started:
+ pass
+ elif self.is_shutdown:
+ pass
+ elif not self.is_shutting_down:
+ # the user didn't call shutdown - use our backup queue
+ self.shutdown(self.backup_shutdown_queue, None)
+ # and now we wait
+ while not self.is_shutdown:
+ self.backup_shutdown_queue.poll()
+ else:
+ # We're in the process of shutting down, but have not shutdown; can't do
+ # much but repeatedly release the GIL and wait
+ while not self.is_shutdown:
+ time.sleep(0)
+ grpc.grpc_server_destroy(self.c_server)
+
diff --git a/src/python/src/grpc/_cython/adapter_low.py b/src/python/src/grpc/_cython/adapter_low.py
new file mode 100644
index 0000000000..7546dd1599
--- /dev/null
+++ b/src/python/src/grpc/_cython/adapter_low.py
@@ -0,0 +1,114 @@
+# 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.
+
+
+# Adapter from grpc._cython.types to the surface expected by
+# grpc._adapter._intermediary_low.
+#
+# TODO(atash): Once this is plugged into grpc._adapter._intermediary_low, remove
+# both grpc._adapter._intermediary_low and this file. The fore and rear links in
+# grpc._adapter should be able to use grpc._cython.types directly.
+
+from grpc._adapter import _types as type_interfaces
+from grpc._cython import cygrpc
+
+
+class ClientCredentials(object):
+ def __init__(self):
+ raise NotImplementedError()
+
+ @staticmethod
+ def google_default():
+ raise NotImplementedError()
+
+ @staticmethod
+ def ssl():
+ raise NotImplementedError()
+
+ @staticmethod
+ def composite():
+ raise NotImplementedError()
+
+ @staticmethod
+ def compute_engine():
+ raise NotImplementedError()
+
+ @staticmethod
+ def service_account():
+ raise NotImplementedError()
+
+ @staticmethod
+ def jwt():
+ raise NotImplementedError()
+
+ @staticmethod
+ def refresh_token():
+ raise NotImplementedError()
+
+ @staticmethod
+ def fake_transport_security():
+ raise NotImplementedError()
+
+ @staticmethod
+ def iam():
+ raise NotImplementedError()
+
+
+class ServerCredentials(object):
+ def __init__(self):
+ raise NotImplementedError()
+
+ @staticmethod
+ def ssl():
+ raise NotImplementedError()
+
+ @staticmethod
+ def fake_transport_security():
+ raise NotImplementedError()
+
+
+class CompletionQueue(type_interfaces.CompletionQueue):
+ def __init__(self):
+ raise NotImplementedError()
+
+
+class Call(type_interfaces.Call):
+ def __init__(self):
+ raise NotImplementedError()
+
+
+class Channel(type_interfaces.Channel):
+ def __init__(self):
+ raise NotImplementedError()
+
+
+class Server(type_interfaces.Server):
+ def __init__(self):
+ raise NotImplementedError()
+
diff --git a/src/python/src/grpc/_cython/adapter_low_test.py b/src/python/src/grpc/_cython/adapter_low_test.py
new file mode 100644
index 0000000000..9bab930e56
--- /dev/null
+++ b/src/python/src/grpc/_cython/adapter_low_test.py
@@ -0,0 +1,187 @@
+# 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.
+
+# Fork of grpc._adapter._low_test; the grpc._cython.types adapter in
+# grpc._cython.low should transparently support the semantics expected of
+# grpc._adapter._low.
+
+import time
+import unittest
+
+from grpc._adapter import _types
+from grpc._cython import adapter_low as _low
+
+
+class InsecureServerInsecureClient(unittest.TestCase):
+
+ def setUp(self):
+ self.server_completion_queue = _low.CompletionQueue()
+ self.server = _low.Server(self.server_completion_queue, [])
+ self.port = self.server.add_http2_port('[::]:0')
+ self.client_completion_queue = _low.CompletionQueue()
+ self.client_channel = _low.Channel('localhost:%d'%self.port, [])
+
+ self.server.start()
+
+ def tearDown(self):
+ self.server.shutdown()
+ del self.client_channel
+
+ self.client_completion_queue.shutdown()
+ while (self.client_completion_queue.next().type !=
+ _types.EventType.QUEUE_SHUTDOWN):
+ pass
+ self.server_completion_queue.shutdown()
+ while (self.server_completion_queue.next().type !=
+ _types.EventType.QUEUE_SHUTDOWN):
+ pass
+
+ del self.client_completion_queue
+ del self.server_completion_queue
+ del self.server
+
+ @unittest.skip('TODO(atash): implement grpc._cython.adapter_low')
+ def testEcho(self):
+ DEADLINE = time.time()+5
+ DEADLINE_TOLERANCE = 0.25
+ CLIENT_METADATA_ASCII_KEY = 'key'
+ CLIENT_METADATA_ASCII_VALUE = 'val'
+ CLIENT_METADATA_BIN_KEY = 'key-bin'
+ CLIENT_METADATA_BIN_VALUE = b'\0'*1000
+ SERVER_INITIAL_METADATA_KEY = 'init_me_me_me'
+ SERVER_INITIAL_METADATA_VALUE = 'whodawha?'
+ SERVER_TRAILING_METADATA_KEY = 'California_is_in_a_drought'
+ SERVER_TRAILING_METADATA_VALUE = 'zomg it is'
+ SERVER_STATUS_CODE = _types.StatusCode.OK
+ SERVER_STATUS_DETAILS = 'our work is never over'
+ REQUEST = 'in death a member of project mayhem has a name'
+ RESPONSE = 'his name is robert paulson'
+ METHOD = 'twinkies'
+ HOST = 'hostess'
+ server_request_tag = object()
+ request_call_result = self.server.request_call(self.server_completion_queue,
+ server_request_tag)
+
+ self.assertEqual(_types.CallError.OK, request_call_result)
+
+ client_call_tag = object()
+ client_call = self.client_channel.create_call(self.client_completion_queue,
+ METHOD, HOST, DEADLINE)
+ client_initial_metadata = [
+ (CLIENT_METADATA_ASCII_KEY, CLIENT_METADATA_ASCII_VALUE),
+ (CLIENT_METADATA_BIN_KEY, CLIENT_METADATA_BIN_VALUE)]
+ client_start_batch_result = client_call.start_batch([
+ _types.OpArgs.send_initial_metadata(client_initial_metadata),
+ _types.OpArgs.send_message(REQUEST),
+ _types.OpArgs.send_close_from_client(),
+ _types.OpArgs.recv_initial_metadata(),
+ _types.OpArgs.recv_message(),
+ _types.OpArgs.recv_status_on_client()
+ ], client_call_tag)
+ self.assertEqual(_types.CallError.OK, client_start_batch_result)
+
+ request_event = self.server_completion_queue.next(DEADLINE)
+ self.assertEqual(_types.EventType.OP_COMPLETE, request_event.type)
+ self.assertIsInstance(request_event.call, _low.Call)
+ self.assertIs(server_request_tag, request_event.tag)
+ self.assertEqual(1, len(request_event.results))
+ self.assertEqual(dict(client_initial_metadata),
+ dict(request_event.results[0].initial_metadata))
+ self.assertEqual(METHOD, request_event.call_details.method)
+ self.assertEqual(HOST, request_event.call_details.host)
+ self.assertLess(abs(DEADLINE - request_event.call_details.deadline),
+ DEADLINE_TOLERANCE)
+
+ server_call_tag = object()
+ server_call = request_event.call
+ server_initial_metadata = [
+ (SERVER_INITIAL_METADATA_KEY, SERVER_INITIAL_METADATA_VALUE)]
+ server_trailing_metadata = [
+ (SERVER_TRAILING_METADATA_KEY, SERVER_TRAILING_METADATA_VALUE)]
+ server_start_batch_result = server_call.start_batch([
+ _types.OpArgs.send_initial_metadata(server_initial_metadata),
+ _types.OpArgs.recv_message(),
+ _types.OpArgs.send_message(RESPONSE),
+ _types.OpArgs.recv_close_on_server(),
+ _types.OpArgs.send_status_from_server(
+ server_trailing_metadata, SERVER_STATUS_CODE, SERVER_STATUS_DETAILS)
+ ], server_call_tag)
+ self.assertEqual(_types.CallError.OK, server_start_batch_result)
+
+ client_event = self.client_completion_queue.next(DEADLINE)
+ server_event = self.server_completion_queue.next(DEADLINE)
+
+ self.assertEqual(6, len(client_event.results))
+ found_client_op_types = set()
+ for client_result in client_event.results:
+ # we expect each op type to be unique
+ self.assertNotIn(client_result.type, found_client_op_types)
+ found_client_op_types.add(client_result.type)
+ if client_result.type == _types.OpType.RECV_INITIAL_METADATA:
+ self.assertEqual(dict(server_initial_metadata),
+ dict(client_result.initial_metadata))
+ elif client_result.type == _types.OpType.RECV_MESSAGE:
+ self.assertEqual(RESPONSE, client_result.message)
+ elif client_result.type == _types.OpType.RECV_STATUS_ON_CLIENT:
+ self.assertEqual(dict(server_trailing_metadata),
+ dict(client_result.trailing_metadata))
+ self.assertEqual(SERVER_STATUS_DETAILS, client_result.status.details)
+ self.assertEqual(SERVER_STATUS_CODE, client_result.status.code)
+ self.assertEqual(set([
+ _types.OpType.SEND_INITIAL_METADATA,
+ _types.OpType.SEND_MESSAGE,
+ _types.OpType.SEND_CLOSE_FROM_CLIENT,
+ _types.OpType.RECV_INITIAL_METADATA,
+ _types.OpType.RECV_MESSAGE,
+ _types.OpType.RECV_STATUS_ON_CLIENT
+ ]), found_client_op_types)
+
+ self.assertEqual(5, len(server_event.results))
+ found_server_op_types = set()
+ for server_result in server_event.results:
+ self.assertNotIn(client_result.type, found_server_op_types)
+ found_server_op_types.add(server_result.type)
+ if server_result.type == _types.OpType.RECV_MESSAGE:
+ self.assertEqual(REQUEST, server_result.message)
+ elif server_result.type == _types.OpType.RECV_CLOSE_ON_SERVER:
+ self.assertFalse(server_result.cancelled)
+ self.assertEqual(set([
+ _types.OpType.SEND_INITIAL_METADATA,
+ _types.OpType.RECV_MESSAGE,
+ _types.OpType.SEND_MESSAGE,
+ _types.OpType.RECV_CLOSE_ON_SERVER,
+ _types.OpType.SEND_STATUS_FROM_SERVER
+ ]), found_server_op_types)
+
+ del client_call
+ del server_call
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/src/python/src/grpc/_cython/cygrpc.pyx b/src/python/src/grpc/_cython/cygrpc.pyx
new file mode 100644
index 0000000000..dcb06f345c
--- /dev/null
+++ b/src/python/src/grpc/_cython/cygrpc.pyx
@@ -0,0 +1,111 @@
+# 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.
+
+cimport cpython
+
+from grpc._cython._cygrpc cimport grpc
+from grpc._cython._cygrpc cimport call
+from grpc._cython._cygrpc cimport channel
+from grpc._cython._cygrpc cimport credentials
+from grpc._cython._cygrpc cimport completion_queue
+from grpc._cython._cygrpc cimport records
+from grpc._cython._cygrpc cimport server
+
+from grpc._cython._cygrpc import call
+from grpc._cython._cygrpc import channel
+from grpc._cython._cygrpc import credentials
+from grpc._cython._cygrpc import completion_queue
+from grpc._cython._cygrpc import records
+from grpc._cython._cygrpc import server
+
+StatusCode = records.StatusCode
+CallError = records.CallError
+CompletionType = records.CompletionType
+OperationType = records.OperationType
+Timespec = records.Timespec
+CallDetails = records.CallDetails
+Event = records.Event
+ByteBuffer = records.ByteBuffer
+SslPemKeyCertPair = records.SslPemKeyCertPair
+ChannelArg = records.ChannelArg
+ChannelArgs = records.ChannelArgs
+Metadatum = records.Metadatum
+Metadata = records.Metadata
+Operation = records.Operation
+
+operation_send_initial_metadata = records.operation_send_initial_metadata
+operation_send_message = records.operation_send_message
+operation_send_close_from_client = records.operation_send_close_from_client
+operation_send_status_from_server = records.operation_send_status_from_server
+operation_receive_initial_metadata = records.operation_receive_initial_metadata
+operation_receive_message = records.operation_receive_message
+operation_receive_status_on_client = records.operation_receive_status_on_client
+operation_receive_close_on_server = records.operation_receive_close_on_server
+
+Operations = records.Operations
+
+ClientCredentials = credentials.ClientCredentials
+ServerCredentials = credentials.ServerCredentials
+
+client_credentials_google_default = (
+ credentials.client_credentials_google_default)
+client_credentials_ssl = credentials.client_credentials_ssl
+client_credentials_composite_credentials = (
+ credentials.client_credentials_composite_credentials)
+client_credentials_compute_engine = (
+ credentials.client_credentials_compute_engine)
+client_credentials_jwt = credentials.client_credentials_jwt
+client_credentials_refresh_token = credentials.client_credentials_refresh_token
+client_credentials_fake_transport_security = (
+ credentials.client_credentials_fake_transport_security)
+client_credentials_iam = credentials.client_credentials_iam
+server_credentials_ssl = credentials.server_credentials_ssl
+server_credentials_fake_transport_security = (
+ credentials.server_credentials_fake_transport_security)
+
+CompletionQueue = completion_queue.CompletionQueue
+Channel = channel.Channel
+Server = server.Server
+Call = call.Call
+
+
+#
+# Global state
+#
+
+cdef class _ModuleState:
+
+ def __cinit__(self):
+ grpc.grpc_init()
+
+ def __dealloc__(self):
+ grpc.grpc_shutdown()
+
+_module_state = _ModuleState()
+
diff --git a/src/python/src/grpc/_cython/cygrpc_test.py b/src/python/src/grpc/_cython/cygrpc_test.py
new file mode 100644
index 0000000000..838e1e2254
--- /dev/null
+++ b/src/python/src/grpc/_cython/cygrpc_test.py
@@ -0,0 +1,276 @@
+# 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.
+
+import time
+import unittest
+
+from grpc._cython import cygrpc
+from grpc._cython import test_utilities
+
+
+class TypeSmokeTest(unittest.TestCase):
+
+ def testStringsInUtilitiesUpDown(self):
+ self.assertEqual(0, cygrpc.StatusCode.ok)
+ metadatum = cygrpc.Metadatum('a', 'b')
+ self.assertEqual('a'.encode(), metadatum.key)
+ self.assertEqual('b'.encode(), metadatum.value)
+ metadata = cygrpc.Metadata([metadatum])
+ self.assertEqual(1, len(metadata))
+ self.assertEqual(metadatum.key, metadata[0].key)
+
+ def testMetadataIteration(self):
+ metadata = cygrpc.Metadata([
+ cygrpc.Metadatum('a', 'b'), cygrpc.Metadatum('c', 'd')])
+ iterator = iter(metadata)
+ metadatum = next(iterator)
+ self.assertIsInstance(metadatum, cygrpc.Metadatum)
+ self.assertEqual(metadatum.key, 'a'.encode())
+ self.assertEqual(metadatum.value, 'b'.encode())
+ metadatum = next(iterator)
+ self.assertIsInstance(metadatum, cygrpc.Metadatum)
+ self.assertEqual(metadatum.key, 'c'.encode())
+ self.assertEqual(metadatum.value, 'd'.encode())
+ with self.assertRaises(StopIteration):
+ next(iterator)
+
+ def testOperationsIteration(self):
+ operations = cygrpc.Operations([
+ cygrpc.operation_send_message('asdf')])
+ iterator = iter(operations)
+ operation = next(iterator)
+ self.assertIsInstance(operation, cygrpc.Operation)
+ # `Operation`s are write-only structures; can't directly debug anything out
+ # of them. Just check that we stop iterating.
+ with self.assertRaises(StopIteration):
+ next(iterator)
+
+ def testTimespec(self):
+ now = time.time()
+ timespec = cygrpc.Timespec(now)
+ self.assertAlmostEqual(now, float(timespec), places=8)
+
+ def testClientCredentialsUpDown(self):
+ credentials = cygrpc.client_credentials_fake_transport_security()
+ del credentials
+
+ def testServerCredentialsUpDown(self):
+ credentials = cygrpc.server_credentials_fake_transport_security()
+ del credentials
+
+ def testCompletionQueueUpDown(self):
+ completion_queue = cygrpc.CompletionQueue()
+ del completion_queue
+
+ def testServerUpDown(self):
+ server = cygrpc.Server(cygrpc.ChannelArgs([]))
+ del server
+
+ def testChannelUpDown(self):
+ channel = cygrpc.Channel('[::]:0', cygrpc.ChannelArgs([]))
+ del channel
+
+ def testSecureChannelUpDown(self):
+ channel = cygrpc.Channel(
+ '[::]:0', cygrpc.ChannelArgs([]),
+ cygrpc.client_credentials_fake_transport_security())
+ del channel
+
+ @unittest.skip('TODO(atash): undo skip after #2229 is merged')
+ def testServerStartNoExplicitShutdown(self):
+ server = cygrpc.Server()
+ completion_queue = cygrpc.CompletionQueue()
+ server.register_completion_queue(completion_queue)
+ port = server.add_http2_port('[::]:0')
+ self.assertIsInstance(port, int)
+ server.start()
+ del server
+
+ @unittest.skip('TODO(atash): undo skip after #2229 is merged')
+ def testServerStartShutdown(self):
+ completion_queue = cygrpc.CompletionQueue()
+ server = cygrpc.Server()
+ server.add_http2_port('[::]:0')
+ server.register_completion_queue(completion_queue)
+ server.start()
+ shutdown_tag = object()
+ server.shutdown(completion_queue, shutdown_tag)
+ event = completion_queue.poll()
+ self.assertEqual(cygrpc.CompletionType.operation_complete, event.type)
+ self.assertIs(shutdown_tag, event.tag)
+ del server
+ del completion_queue
+
+
+class InsecureServerInsecureClient(unittest.TestCase):
+
+ def setUp(self):
+ self.server_completion_queue = cygrpc.CompletionQueue()
+ self.server = cygrpc.Server()
+ self.server.register_completion_queue(self.server_completion_queue)
+ self.port = self.server.add_http2_port('[::]:0')
+ self.server.start()
+ self.client_completion_queue = cygrpc.CompletionQueue()
+ self.client_channel = cygrpc.Channel('localhost:{}'.format(self.port))
+
+ def tearDown(self):
+ del self.server
+ del self.client_completion_queue
+ del self.server_completion_queue
+
+ def testEcho(self):
+ DEADLINE = time.time()+5
+ DEADLINE_TOLERANCE = 0.25
+ CLIENT_METADATA_ASCII_KEY = b'key'
+ CLIENT_METADATA_ASCII_VALUE = b'val'
+ CLIENT_METADATA_BIN_KEY = b'key-bin'
+ CLIENT_METADATA_BIN_VALUE = b'\0'*1000
+ SERVER_INITIAL_METADATA_KEY = b'init_me_me_me'
+ SERVER_INITIAL_METADATA_VALUE = b'whodawha?'
+ SERVER_TRAILING_METADATA_KEY = b'California_is_in_a_drought'
+ SERVER_TRAILING_METADATA_VALUE = b'zomg it is'
+ SERVER_STATUS_CODE = cygrpc.StatusCode.ok
+ SERVER_STATUS_DETAILS = b'our work is never over'
+ REQUEST = b'in death a member of project mayhem has a name'
+ RESPONSE = b'his name is robert paulson'
+ METHOD = b'twinkies'
+ HOST = b'hostess'
+
+ cygrpc_deadline = cygrpc.Timespec(DEADLINE)
+
+ server_request_tag = object()
+ request_call_result = self.server.request_call(
+ self.server_completion_queue, self.server_completion_queue,
+ server_request_tag)
+
+ self.assertEqual(cygrpc.CallError.ok, request_call_result)
+
+ client_call_tag = object()
+ client_call = self.client_channel.create_call(self.client_completion_queue,
+ METHOD, HOST, cygrpc_deadline)
+ client_initial_metadata = cygrpc.Metadata([
+ cygrpc.Metadatum(CLIENT_METADATA_ASCII_KEY,
+ CLIENT_METADATA_ASCII_VALUE),
+ cygrpc.Metadatum(CLIENT_METADATA_BIN_KEY, CLIENT_METADATA_BIN_VALUE)])
+ client_start_batch_result = client_call.start_batch(cygrpc.Operations([
+ cygrpc.operation_send_initial_metadata(client_initial_metadata),
+ cygrpc.operation_send_message(REQUEST),
+ cygrpc.operation_send_close_from_client(),
+ cygrpc.operation_receive_initial_metadata(),
+ cygrpc.operation_receive_message(),
+ cygrpc.operation_receive_status_on_client()
+ ]), client_call_tag)
+ self.assertEqual(cygrpc.CallError.ok, client_start_batch_result)
+ client_event_future = test_utilities.CompletionQueuePollFuture(
+ self.client_completion_queue, cygrpc_deadline)
+
+ request_event = self.server_completion_queue.poll(cygrpc_deadline)
+ self.assertEqual(cygrpc.CompletionType.operation_complete,
+ request_event.type)
+ self.assertIsInstance(request_event.operation_call, cygrpc.Call)
+ self.assertIs(server_request_tag, request_event.tag)
+ self.assertEqual(0, len(request_event.batch_operations))
+ self.assertEqual(dict(client_initial_metadata),
+ dict(request_event.request_metadata))
+ self.assertEqual(METHOD, request_event.request_call_details.method)
+ self.assertEqual(HOST, request_event.request_call_details.host)
+ self.assertLess(
+ abs(DEADLINE - float(request_event.request_call_details.deadline)),
+ DEADLINE_TOLERANCE)
+
+ server_call_tag = object()
+ server_call = request_event.operation_call
+ server_initial_metadata = cygrpc.Metadata([
+ cygrpc.Metadatum(SERVER_INITIAL_METADATA_KEY,
+ SERVER_INITIAL_METADATA_VALUE)])
+ server_trailing_metadata = cygrpc.Metadata([
+ cygrpc.Metadatum(SERVER_TRAILING_METADATA_KEY,
+ SERVER_TRAILING_METADATA_VALUE)])
+ server_start_batch_result = server_call.start_batch([
+ cygrpc.operation_send_initial_metadata(server_initial_metadata),
+ cygrpc.operation_receive_message(),
+ cygrpc.operation_send_message(RESPONSE),
+ cygrpc.operation_receive_close_on_server(),
+ cygrpc.operation_send_status_from_server(
+ server_trailing_metadata, SERVER_STATUS_CODE, SERVER_STATUS_DETAILS)
+ ], server_call_tag)
+ self.assertEqual(cygrpc.CallError.ok, server_start_batch_result)
+
+ client_event = client_event_future.result()
+ server_event = self.server_completion_queue.poll(cygrpc_deadline)
+
+ self.assertEqual(6, len(client_event.batch_operations))
+ found_client_op_types = set()
+ for client_result in client_event.batch_operations:
+ # we expect each op type to be unique
+ self.assertNotIn(client_result.type, found_client_op_types)
+ found_client_op_types.add(client_result.type)
+ if client_result.type == cygrpc.OperationType.receive_initial_metadata:
+ self.assertEqual(dict(server_initial_metadata),
+ dict(client_result.received_metadata))
+ elif client_result.type == cygrpc.OperationType.receive_message:
+ self.assertEqual(RESPONSE, client_result.received_message.bytes())
+ elif client_result.type == cygrpc.OperationType.receive_status_on_client:
+ self.assertEqual(dict(server_trailing_metadata),
+ dict(client_result.received_metadata))
+ self.assertEqual(SERVER_STATUS_DETAILS,
+ client_result.received_status_details)
+ self.assertEqual(SERVER_STATUS_CODE, client_result.received_status_code)
+ self.assertEqual(set([
+ cygrpc.OperationType.send_initial_metadata,
+ cygrpc.OperationType.send_message,
+ cygrpc.OperationType.send_close_from_client,
+ cygrpc.OperationType.receive_initial_metadata,
+ cygrpc.OperationType.receive_message,
+ cygrpc.OperationType.receive_status_on_client
+ ]), found_client_op_types)
+
+ self.assertEqual(5, len(server_event.batch_operations))
+ found_server_op_types = set()
+ for server_result in server_event.batch_operations:
+ self.assertNotIn(client_result.type, found_server_op_types)
+ found_server_op_types.add(server_result.type)
+ if server_result.type == cygrpc.OperationType.receive_message:
+ self.assertEqual(REQUEST, server_result.received_message.bytes())
+ elif server_result.type == cygrpc.OperationType.receive_close_on_server:
+ self.assertFalse(server_result.received_cancelled)
+ self.assertEqual(set([
+ cygrpc.OperationType.send_initial_metadata,
+ cygrpc.OperationType.receive_message,
+ cygrpc.OperationType.send_message,
+ cygrpc.OperationType.receive_close_on_server,
+ cygrpc.OperationType.send_status_from_server
+ ]), found_server_op_types)
+
+ del client_call
+ del server_call
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/src/python/src/grpc/_cython/test_utilities.py b/src/python/src/grpc/_cython/test_utilities.py
new file mode 100644
index 0000000000..21ea3075b4
--- /dev/null
+++ b/src/python/src/grpc/_cython/test_utilities.py
@@ -0,0 +1,46 @@
+# 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.
+
+import threading
+
+from grpc._cython._cygrpc import completion_queue
+
+
+class CompletionQueuePollFuture:
+
+ def __init__(self, completion_queue, deadline):
+ def poller_function():
+ self._event_result = completion_queue.poll(deadline)
+ self._event_result = None
+ self._thread = threading.Thread(target=poller_function)
+ self._thread.start()
+
+ def result(self):
+ self._thread.join()
+ return self._event_result
diff --git a/src/python/src/grpc/_links/__init__.py b/src/python/src/grpc/_links/__init__.py
new file mode 100644
index 0000000000..7086519106
--- /dev/null
+++ b/src/python/src/grpc/_links/__init__.py
@@ -0,0 +1,30 @@
+# 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.
+
+
diff --git a/src/python/src/grpc/_links/_lonely_invocation_link_test.py b/src/python/src/grpc/_links/_lonely_invocation_link_test.py
new file mode 100644
index 0000000000..3d629f4387
--- /dev/null
+++ b/src/python/src/grpc/_links/_lonely_invocation_link_test.py
@@ -0,0 +1,88 @@
+# 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.
+
+"""A test of invocation-side code unconnected to an RPC server."""
+
+import unittest
+
+from grpc._adapter import _intermediary_low
+from grpc._links import invocation
+from grpc.framework.common import test_constants
+from grpc.framework.interfaces.links import links
+from grpc.framework.interfaces.links import test_cases
+from grpc.framework.interfaces.links import test_utilities
+
+_NULL_BEHAVIOR = lambda unused_argument: None
+
+
+class LonelyInvocationLinkTest(unittest.TestCase):
+
+ def testUpAndDown(self):
+ channel = _intermediary_low.Channel('nonexistent:54321', None)
+ invocation_link = invocation.invocation_link(channel, 'nonexistent', {}, {})
+
+ invocation_link.start()
+ invocation_link.stop()
+
+ def _test_lonely_invocation_with_termination(self, termination):
+ test_operation_id = object()
+ test_group = 'test package.Test Service'
+ test_method = 'test method'
+ invocation_link_mate = test_utilities.RecordingLink()
+
+ channel = _intermediary_low.Channel('nonexistent:54321', None)
+ invocation_link = invocation.invocation_link(
+ channel, 'nonexistent', {(test_group, test_method): _NULL_BEHAVIOR},
+ {(test_group, test_method): _NULL_BEHAVIOR})
+ invocation_link.join_link(invocation_link_mate)
+ invocation_link.start()
+
+ ticket = links.Ticket(
+ test_operation_id, 0, test_group, test_method,
+ links.Ticket.Subscription.FULL, test_constants.SHORT_TIMEOUT, 1, None,
+ None, None, None, None, termination)
+ invocation_link.accept_ticket(ticket)
+ invocation_link_mate.block_until_tickets_satisfy(test_cases.terminated)
+
+ invocation_link.stop()
+
+ self.assertIsNot(
+ invocation_link_mate.tickets()[-1].termination,
+ links.Ticket.Termination.COMPLETION)
+
+ def testLonelyInvocationLinkWithCommencementTicket(self):
+ self._test_lonely_invocation_with_termination(None)
+
+ def testLonelyInvocationLinkWithEntireTicket(self):
+ self._test_lonely_invocation_with_termination(
+ links.Ticket.Termination.COMPLETION)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/src/python/src/grpc/_links/_proto_scenarios.py b/src/python/src/grpc/_links/_proto_scenarios.py
new file mode 100644
index 0000000000..ccf3c29782
--- /dev/null
+++ b/src/python/src/grpc/_links/_proto_scenarios.py
@@ -0,0 +1,261 @@
+# 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.
+
+"""Test scenarios using protocol buffers."""
+
+import abc
+import threading
+
+from grpc._junkdrawer import math_pb2
+
+
+class ProtoScenario(object):
+ """An RPC test scenario using protocol buffers."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def group_and_method(self):
+ """Access the test group and method.
+
+ Returns:
+ The test group and method as a pair.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def serialize_request(self, request):
+ """Serialize a request protocol buffer.
+
+ Args:
+ request: A request protocol buffer.
+
+ Returns:
+ The bytestring serialization of the given request protocol buffer.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def deserialize_request(self, request_bytestring):
+ """Deserialize a request protocol buffer.
+
+ Args:
+ request_bytestring: The bytestring serialization of a request protocol
+ buffer.
+
+ Returns:
+ The request protocol buffer deserialized from the given byte string.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def serialize_response(self, response):
+ """Serialize a response protocol buffer.
+
+ Args:
+ response: A response protocol buffer.
+
+ Returns:
+ The bytestring serialization of the given response protocol buffer.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def deserialize_response(self, response_bytestring):
+ """Deserialize a response protocol buffer.
+
+ Args:
+ response_bytestring: The bytestring serialization of a response protocol
+ buffer.
+
+ Returns:
+ The response protocol buffer deserialized from the given byte string.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def requests(self):
+ """Access the sequence of requests for this scenario.
+
+ Returns:
+ A sequence of request protocol buffers.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def response_for_request(self, request):
+ """Access the response for a particular request.
+
+ Args:
+ request: A request protocol buffer.
+
+ Returns:
+ The response protocol buffer appropriate for the given request.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def verify_requests(self, experimental_requests):
+ """Verify the requests transmitted through the system under test.
+
+ Args:
+ experimental_requests: The request protocol buffers transmitted through
+ the system under test.
+
+ Returns:
+ True if the requests satisfy this test scenario; False otherwise.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def verify_responses(self, experimental_responses):
+ """Verify the responses transmitted through the system under test.
+
+ Args:
+ experimental_responses: The response protocol buffers transmitted through
+ the system under test.
+
+ Returns:
+ True if the responses satisfy this test scenario; False otherwise.
+ """
+ raise NotImplementedError()
+
+
+class EmptyScenario(ProtoScenario):
+ """A scenario that transmits no protocol buffers in either direction."""
+
+ def group_and_method(self):
+ return 'math.Math', 'DivMany'
+
+ def serialize_request(self, request):
+ raise ValueError('This should not be necessary to call!')
+
+ def deserialize_request(self, request_bytestring):
+ raise ValueError('This should not be necessary to call!')
+
+ def serialize_response(self, response):
+ raise ValueError('This should not be necessary to call!')
+
+ def deserialize_response(self, response_bytestring):
+ raise ValueError('This should not be necessary to call!')
+
+ def requests(self):
+ return ()
+
+ def response_for_request(self, request):
+ raise ValueError('This should not be necessary to call!')
+
+ def verify_requests(self, experimental_requests):
+ return not experimental_requests
+
+ def verify_responses(self, experimental_responses):
+ return not experimental_responses
+
+
+class BidirectionallyUnaryScenario(ProtoScenario):
+ """A scenario that transmits no protocol buffers in either direction."""
+
+ _DIVIDEND = 59
+ _DIVISOR = 7
+ _QUOTIENT = 8
+ _REMAINDER = 3
+
+ _REQUEST = math_pb2.DivArgs(dividend=_DIVIDEND, divisor=_DIVISOR)
+ _RESPONSE = math_pb2.DivReply(quotient=_QUOTIENT, remainder=_REMAINDER)
+
+ def group_and_method(self):
+ return 'math.Math', 'Div'
+
+ def serialize_request(self, request):
+ return request.SerializeToString()
+
+ def deserialize_request(self, request_bytestring):
+ return math_pb2.DivArgs.FromString(request_bytestring)
+
+ def serialize_response(self, response):
+ return response.SerializeToString()
+
+ def deserialize_response(self, response_bytestring):
+ return math_pb2.DivReply.FromString(response_bytestring)
+
+ def requests(self):
+ return [self._REQUEST]
+
+ def response_for_request(self, request):
+ return self._RESPONSE
+
+ def verify_requests(self, experimental_requests):
+ return tuple(experimental_requests) == (self._REQUEST,)
+
+ def verify_responses(self, experimental_responses):
+ return tuple(experimental_responses) == (self._RESPONSE,)
+
+
+class BidirectionallyStreamingScenario(ProtoScenario):
+ """A scenario that transmits no protocol buffers in either direction."""
+
+ _STREAM_LENGTH = 200
+ _REQUESTS = tuple(
+ math_pb2.DivArgs(dividend=59 + index, divisor=7 + index)
+ for index in range(_STREAM_LENGTH))
+
+ def __init__(self):
+ self._lock = threading.Lock()
+ self._responses = []
+
+ def group_and_method(self):
+ return 'math.Math', 'DivMany'
+
+ def serialize_request(self, request):
+ return request.SerializeToString()
+
+ def deserialize_request(self, request_bytestring):
+ return math_pb2.DivArgs.FromString(request_bytestring)
+
+ def serialize_response(self, response):
+ return response.SerializeToString()
+
+ def deserialize_response(self, response_bytestring):
+ return math_pb2.DivReply.FromString(response_bytestring)
+
+ def requests(self):
+ return self._REQUESTS
+
+ def response_for_request(self, request):
+ quotient, remainder = divmod(request.dividend, request.divisor)
+ response = math_pb2.DivReply(quotient=quotient, remainder=remainder)
+ with self._lock:
+ self._responses.append(response)
+ return response
+
+ def verify_requests(self, experimental_requests):
+ return tuple(experimental_requests) == self._REQUESTS
+
+ def verify_responses(self, experimental_responses):
+ with self._lock:
+ return tuple(experimental_responses) == tuple(self._responses)
diff --git a/src/python/src/grpc/_links/_transmission_test.py b/src/python/src/grpc/_links/_transmission_test.py
new file mode 100644
index 0000000000..c5ef1edb25
--- /dev/null
+++ b/src/python/src/grpc/_links/_transmission_test.py
@@ -0,0 +1,226 @@
+# 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.
+
+"""Tests transmission of tickets across gRPC-on-the-wire."""
+
+import unittest
+
+from grpc._adapter import _intermediary_low
+from grpc._links import _proto_scenarios
+from grpc._links import invocation
+from grpc._links import service
+from grpc.framework.common import test_constants
+from grpc.framework.interfaces.links import links
+from grpc.framework.interfaces.links import test_cases
+from grpc.framework.interfaces.links import test_utilities
+
+_IDENTITY = lambda x: x
+
+
+class TransmissionTest(test_cases.TransmissionTest, unittest.TestCase):
+
+ def create_transmitting_links(self):
+ service_link = service.service_link(
+ {self.group_and_method(): self.deserialize_request},
+ {self.group_and_method(): self.serialize_response})
+ port = service_link.add_port(0, None)
+ service_link.start()
+ channel = _intermediary_low.Channel('localhost:%d' % port, None)
+ invocation_link = invocation.invocation_link(
+ channel, 'localhost',
+ {self.group_and_method(): self.serialize_request},
+ {self.group_and_method(): self.deserialize_response})
+ invocation_link.start()
+ return invocation_link, service_link
+
+ def destroy_transmitting_links(self, invocation_side_link, service_side_link):
+ invocation_side_link.stop()
+ service_side_link.stop_gracefully()
+
+ def create_invocation_initial_metadata(self):
+ return (
+ ('first invocation initial metadata key', 'just a string value'),
+ ('second invocation initial metadata key', '0123456789'),
+ ('third invocation initial metadata key-bin', '\x00\x57' * 100),
+ )
+
+ def create_invocation_terminal_metadata(self):
+ return None
+
+ def create_service_initial_metadata(self):
+ return (
+ ('first service initial metadata key', 'just another string value'),
+ ('second service initial metadata key', '9876543210'),
+ ('third service initial metadata key-bin', '\x00\x59\x02' * 100),
+ )
+
+ def create_service_terminal_metadata(self):
+ return (
+ ('first service terminal metadata key', 'yet another string value'),
+ ('second service terminal metadata key', 'abcdefghij'),
+ ('third service terminal metadata key-bin', '\x00\x37' * 100),
+ )
+
+ def create_invocation_completion(self):
+ return None, None
+
+ def create_service_completion(self):
+ return _intermediary_low.Code.OK, 'An exuberant test "details" message!'
+
+ def assertMetadataEqual(self, original_metadata, transmitted_metadata):
+ self.assertSequenceEqual(original_metadata, transmitted_metadata)
+
+
+class RoundTripTest(unittest.TestCase):
+
+ def testZeroMessageRoundTrip(self):
+ test_operation_id = object()
+ test_group = 'test package.Test Group'
+ test_method = 'test method'
+ identity_transformation = {(test_group, test_method): _IDENTITY}
+ test_code = _intermediary_low.Code.OK
+ test_message = 'a test message'
+
+ service_link = service.service_link(
+ identity_transformation, identity_transformation)
+ service_mate = test_utilities.RecordingLink()
+ service_link.join_link(service_mate)
+ port = service_link.add_port(0, None)
+ service_link.start()
+ channel = _intermediary_low.Channel('localhost:%d' % port, None)
+ invocation_link = invocation.invocation_link(
+ channel, 'localhost', identity_transformation, identity_transformation)
+ invocation_mate = test_utilities.RecordingLink()
+ invocation_link.join_link(invocation_mate)
+ invocation_link.start()
+
+ invocation_ticket = links.Ticket(
+ test_operation_id, 0, test_group, test_method,
+ links.Ticket.Subscription.FULL, test_constants.LONG_TIMEOUT, None, None,
+ None, None, None, None, links.Ticket.Termination.COMPLETION)
+ invocation_link.accept_ticket(invocation_ticket)
+ service_mate.block_until_tickets_satisfy(test_cases.terminated)
+
+ service_ticket = links.Ticket(
+ service_mate.tickets()[-1].operation_id, 0, None, None, None, None,
+ None, None, None, None, test_code, test_message,
+ links.Ticket.Termination.COMPLETION)
+ service_link.accept_ticket(service_ticket)
+ invocation_mate.block_until_tickets_satisfy(test_cases.terminated)
+
+ invocation_link.stop()
+ service_link.stop_gracefully()
+
+ self.assertIs(
+ service_mate.tickets()[-1].termination,
+ links.Ticket.Termination.COMPLETION)
+ self.assertIs(
+ invocation_mate.tickets()[-1].termination,
+ links.Ticket.Termination.COMPLETION)
+
+ def _perform_scenario_test(self, scenario):
+ test_operation_id = object()
+ test_group, test_method = scenario.group_and_method()
+ test_code = _intermediary_low.Code.OK
+ test_message = 'a scenario test message'
+
+ service_link = service.service_link(
+ {(test_group, test_method): scenario.deserialize_request},
+ {(test_group, test_method): scenario.serialize_response})
+ service_mate = test_utilities.RecordingLink()
+ service_link.join_link(service_mate)
+ port = service_link.add_port(0, None)
+ service_link.start()
+ channel = _intermediary_low.Channel('localhost:%d' % port, None)
+ invocation_link = invocation.invocation_link(
+ channel, 'localhost',
+ {(test_group, test_method): scenario.serialize_request},
+ {(test_group, test_method): scenario.deserialize_response})
+ invocation_mate = test_utilities.RecordingLink()
+ invocation_link.join_link(invocation_mate)
+ invocation_link.start()
+
+ invocation_ticket = links.Ticket(
+ test_operation_id, 0, test_group, test_method,
+ links.Ticket.Subscription.FULL, test_constants.LONG_TIMEOUT, None, None,
+ None, None, None, None, None)
+ invocation_link.accept_ticket(invocation_ticket)
+ requests = scenario.requests()
+ for request_index, request in enumerate(requests):
+ request_ticket = links.Ticket(
+ test_operation_id, 1 + request_index, None, None, None, None, 1, None,
+ request, None, None, None, None)
+ invocation_link.accept_ticket(request_ticket)
+ service_mate.block_until_tickets_satisfy(
+ test_cases.at_least_n_payloads_received_predicate(1 + request_index))
+ response_ticket = links.Ticket(
+ service_mate.tickets()[0].operation_id, request_index, None, None,
+ None, None, 1, None, scenario.response_for_request(request), None,
+ None, None, None)
+ service_link.accept_ticket(response_ticket)
+ invocation_mate.block_until_tickets_satisfy(
+ test_cases.at_least_n_payloads_received_predicate(1 + request_index))
+ request_count = len(requests)
+ invocation_completion_ticket = links.Ticket(
+ test_operation_id, request_count + 1, None, None, None, None, None,
+ None, None, None, None, None, links.Ticket.Termination.COMPLETION)
+ invocation_link.accept_ticket(invocation_completion_ticket)
+ service_mate.block_until_tickets_satisfy(test_cases.terminated)
+ service_completion_ticket = links.Ticket(
+ service_mate.tickets()[0].operation_id, request_count, None, None, None,
+ None, None, None, None, None, test_code, test_message,
+ links.Ticket.Termination.COMPLETION)
+ service_link.accept_ticket(service_completion_ticket)
+ invocation_mate.block_until_tickets_satisfy(test_cases.terminated)
+
+ invocation_link.stop()
+ service_link.stop_gracefully()
+
+ observed_requests = tuple(
+ ticket.payload for ticket in service_mate.tickets()
+ if ticket.payload is not None)
+ observed_responses = tuple(
+ ticket.payload for ticket in invocation_mate.tickets()
+ if ticket.payload is not None)
+ self.assertTrue(scenario.verify_requests(observed_requests))
+ self.assertTrue(scenario.verify_responses(observed_responses))
+
+ def testEmptyScenario(self):
+ self._perform_scenario_test(_proto_scenarios.EmptyScenario())
+
+ def testBidirectionallyUnaryScenario(self):
+ self._perform_scenario_test(_proto_scenarios.BidirectionallyUnaryScenario())
+
+ def testBidirectionallyStreamingScenario(self):
+ self._perform_scenario_test(
+ _proto_scenarios.BidirectionallyStreamingScenario())
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/src/python/src/grpc/_links/invocation.py b/src/python/src/grpc/_links/invocation.py
new file mode 100644
index 0000000000..0058ae91f8
--- /dev/null
+++ b/src/python/src/grpc/_links/invocation.py
@@ -0,0 +1,363 @@
+# 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.
+
+"""The RPC-invocation-side bridge between RPC Framework and GRPC-on-the-wire."""
+
+import abc
+import enum
+import logging
+import threading
+import time
+
+from grpc._adapter import _intermediary_low
+from grpc.framework.foundation import activated
+from grpc.framework.foundation import logging_pool
+from grpc.framework.foundation import relay
+from grpc.framework.interfaces.links import links
+
+
+@enum.unique
+class _Read(enum.Enum):
+ AWAITING_METADATA = 'awaiting metadata'
+ READING = 'reading'
+ AWAITING_ALLOWANCE = 'awaiting allowance'
+ CLOSED = 'closed'
+
+
+@enum.unique
+class _HighWrite(enum.Enum):
+ OPEN = 'open'
+ CLOSED = 'closed'
+
+
+@enum.unique
+class _LowWrite(enum.Enum):
+ OPEN = 'OPEN'
+ ACTIVE = 'ACTIVE'
+ CLOSED = 'CLOSED'
+
+
+class _RPCState(object):
+
+ def __init__(
+ self, call, request_serializer, response_deserializer, sequence_number,
+ read, allowance, high_write, low_write):
+ self.call = call
+ self.request_serializer = request_serializer
+ self.response_deserializer = response_deserializer
+ self.sequence_number = sequence_number
+ self.read = read
+ self.allowance = allowance
+ self.high_write = high_write
+ self.low_write = low_write
+
+
+class _Kernel(object):
+
+ def __init__(
+ self, channel, host, request_serializers, response_deserializers,
+ ticket_relay):
+ self._lock = threading.Lock()
+ self._channel = channel
+ self._host = host
+ self._request_serializers = request_serializers
+ self._response_deserializers = response_deserializers
+ self._relay = ticket_relay
+
+ self._completion_queue = None
+ self._rpc_states = None
+ self._pool = None
+
+ def _on_write_event(self, operation_id, unused_event, rpc_state):
+ if rpc_state.high_write is _HighWrite.CLOSED:
+ rpc_state.call.complete(operation_id)
+ rpc_state.low_write = _LowWrite.CLOSED
+ else:
+ ticket = links.Ticket(
+ operation_id, rpc_state.sequence_number, None, None, None, None, 1,
+ None, None, None, None, None, None)
+ rpc_state.sequence_number += 1
+ self._relay.add_value(ticket)
+ rpc_state.low_write = _LowWrite.OPEN
+
+ def _on_read_event(self, operation_id, event, rpc_state):
+ if event.bytes is None:
+ rpc_state.read = _Read.CLOSED
+ else:
+ if 0 < rpc_state.allowance:
+ rpc_state.allowance -= 1
+ rpc_state.call.read(operation_id)
+ else:
+ rpc_state.read = _Read.AWAITING_ALLOWANCE
+ ticket = links.Ticket(
+ operation_id, rpc_state.sequence_number, None, None, None, None, None,
+ None, rpc_state.response_deserializer(event.bytes), None, None, None,
+ None)
+ rpc_state.sequence_number += 1
+ self._relay.add_value(ticket)
+
+ def _on_metadata_event(self, operation_id, event, rpc_state):
+ rpc_state.allowance -= 1
+ rpc_state.call.read(operation_id)
+ rpc_state.read = _Read.READING
+ ticket = links.Ticket(
+ operation_id, rpc_state.sequence_number, None, None,
+ links.Ticket.Subscription.FULL, None, None, event.metadata, None, None,
+ None, None, None)
+ rpc_state.sequence_number += 1
+ self._relay.add_value(ticket)
+
+ def _on_finish_event(self, operation_id, event, rpc_state):
+ self._rpc_states.pop(operation_id, None)
+ if event.status.code is _intermediary_low.Code.OK:
+ termination = links.Ticket.Termination.COMPLETION
+ elif event.status.code is _intermediary_low.Code.CANCELLED:
+ termination = links.Ticket.Termination.CANCELLATION
+ elif event.status.code is _intermediary_low.Code.DEADLINE_EXCEEDED:
+ termination = links.Ticket.Termination.EXPIRATION
+ else:
+ termination = links.Ticket.Termination.TRANSMISSION_FAILURE
+ ticket = links.Ticket(
+ operation_id, rpc_state.sequence_number, None, None, None, None, None,
+ None, None, event.metadata, event.status.code, event.status.details,
+ termination)
+ rpc_state.sequence_number += 1
+ self._relay.add_value(ticket)
+
+ def _spin(self, completion_queue):
+ while True:
+ event = completion_queue.get(None)
+ if event.kind is _intermediary_low.Event.Kind.STOP:
+ return
+ operation_id = event.tag
+ with self._lock:
+ if self._completion_queue is None:
+ continue
+ rpc_state = self._rpc_states.get(operation_id)
+ if rpc_state is not None:
+ if event.kind is _intermediary_low.Event.Kind.WRITE_ACCEPTED:
+ self._on_write_event(operation_id, event, rpc_state)
+ elif event.kind is _intermediary_low.Event.Kind.METADATA_ACCEPTED:
+ self._on_metadata_event(operation_id, event, rpc_state)
+ elif event.kind is _intermediary_low.Event.Kind.READ_ACCEPTED:
+ self._on_read_event(operation_id, event, rpc_state)
+ elif event.kind is _intermediary_low.Event.Kind.FINISH:
+ self._on_finish_event(operation_id, event, rpc_state)
+ elif event.kind is _intermediary_low.Event.Kind.COMPLETE_ACCEPTED:
+ pass
+ else:
+ logging.error('Illegal RPC event! %s', (event,))
+
+ def _invoke(
+ self, operation_id, group, method, initial_metadata, payload, termination,
+ timeout, allowance):
+ """Invoke an RPC.
+
+ Args:
+ operation_id: Any object to be used as an operation ID for the RPC.
+ group: The group to which the RPC method belongs.
+ method: The RPC method name.
+ initial_metadata: The initial metadata object for the RPC.
+ payload: A payload object for the RPC or None if no payload was given at
+ invocation-time.
+ termination: A links.Ticket.Termination value or None indicated whether or
+ not more writes will follow from this side of the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ allowance: The number of payloads (beyond the free first one) that the
+ local ticket exchange mate has granted permission to be read.
+ """
+ if termination is links.Ticket.Termination.COMPLETION:
+ high_write = _HighWrite.CLOSED
+ elif termination is None:
+ high_write = _HighWrite.OPEN
+ else:
+ return
+
+ request_serializer = self._request_serializers.get((group, method))
+ response_deserializer = self._response_deserializers.get((group, method))
+ if request_serializer is None or response_deserializer is None:
+ cancellation_ticket = links.Ticket(
+ operation_id, 0, None, None, None, None, None, None, None, None, None,
+ None, links.Ticket.Termination.CANCELLATION)
+ self._relay.add_value(cancellation_ticket)
+ return
+
+ call = _intermediary_low.Call(
+ self._channel, self._completion_queue, '/%s/%s' % (group, method),
+ self._host, time.time() + timeout)
+ if initial_metadata is not None:
+ for metadata_key, metadata_value in initial_metadata:
+ call.add_metadata(metadata_key, metadata_value)
+ call.invoke(self._completion_queue, operation_id, operation_id)
+ if payload is None:
+ if high_write is _HighWrite.CLOSED:
+ call.complete(operation_id)
+ low_write = _LowWrite.CLOSED
+ else:
+ low_write = _LowWrite.OPEN
+ else:
+ call.write(request_serializer(payload), operation_id)
+ low_write = _LowWrite.ACTIVE
+ self._rpc_states[operation_id] = _RPCState(
+ call, request_serializer, response_deserializer, 0,
+ _Read.AWAITING_METADATA, 1 if allowance is None else (1 + allowance),
+ high_write, low_write)
+
+ def _advance(self, operation_id, rpc_state, payload, termination, allowance):
+ if payload is not None:
+ rpc_state.call.write(rpc_state.request_serializer(payload), operation_id)
+ rpc_state.low_write = _LowWrite.ACTIVE
+
+ if allowance is not None:
+ if rpc_state.read is _Read.AWAITING_ALLOWANCE:
+ rpc_state.allowance += allowance - 1
+ rpc_state.call.read(operation_id)
+ rpc_state.read = _Read.READING
+ else:
+ rpc_state.allowance += allowance
+
+ if termination is links.Ticket.Termination.COMPLETION:
+ rpc_state.high_write = _HighWrite.CLOSED
+ if rpc_state.low_write is _LowWrite.OPEN:
+ rpc_state.call.complete(operation_id)
+ rpc_state.low_write = _LowWrite.CLOSED
+ elif termination is not None:
+ rpc_state.call.cancel()
+
+ def add_ticket(self, ticket):
+ with self._lock:
+ if self._completion_queue is None:
+ return
+ if ticket.sequence_number == 0:
+ self._invoke(
+ ticket.operation_id, ticket.group, ticket.method,
+ ticket.initial_metadata, ticket.payload, ticket.termination,
+ ticket.timeout, ticket.allowance)
+ else:
+ rpc_state = self._rpc_states.get(ticket.operation_id)
+ if rpc_state is not None:
+ self._advance(
+ ticket.operation_id, rpc_state, ticket.payload,
+ ticket.termination, ticket.allowance)
+
+ def start(self):
+ """Starts this object.
+
+ This method must be called before attempting to exchange tickets with this
+ object.
+ """
+ with self._lock:
+ self._completion_queue = _intermediary_low.CompletionQueue()
+ self._rpc_states = {}
+ self._pool = logging_pool.pool(1)
+ self._pool.submit(self._spin, self._completion_queue)
+
+ def stop(self):
+ """Stops this object.
+
+ This method must be called for proper termination of this object, and no
+ attempts to exchange tickets with this object may be made after this method
+ has been called.
+ """
+ with self._lock:
+ self._completion_queue.stop()
+ self._completion_queue = None
+ pool = self._pool
+ self._pool = None
+ self._rpc_states = None
+ pool.shutdown(wait=True)
+
+
+class InvocationLink(links.Link, activated.Activated):
+ """A links.Link for use on the invocation-side of a gRPC connection.
+
+ Implementations of this interface are only valid for use when activated.
+ """
+ __metaclass__ = abc.ABCMeta
+
+
+class _InvocationLink(InvocationLink):
+
+ def __init__(
+ self, channel, host, request_serializers, response_deserializers):
+ self._relay = relay.relay(None)
+ self._kernel = _Kernel(
+ channel, host, request_serializers, response_deserializers, self._relay)
+
+ def _start(self):
+ self._relay.start()
+ self._kernel.start()
+ return self
+
+ def _stop(self):
+ self._kernel.stop()
+ self._relay.stop()
+
+ def accept_ticket(self, ticket):
+ """See links.Link.accept_ticket for specification."""
+ self._kernel.add_ticket(ticket)
+
+ def join_link(self, link):
+ """See links.Link.join_link for specification."""
+ self._relay.set_behavior(link.accept_ticket)
+
+ def __enter__(self):
+ """See activated.Activated.__enter__ for specification."""
+ return self._start()
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ """See activated.Activated.__exit__ for specification."""
+ self._stop()
+ return False
+
+ def start(self):
+ """See activated.Activated.start for specification."""
+ return self._start()
+
+ def stop(self):
+ """See activated.Activated.stop for specification."""
+ self._stop()
+
+
+def invocation_link(channel, host, request_serializers, response_deserializers):
+ """Creates an InvocationLink.
+
+ Args:
+ channel: A channel for use by the link.
+ host: The host to specify when invoking RPCs.
+ request_serializers: A dict from group-method pair to request object
+ serialization behavior.
+ response_deserializers: A dict from group-method pair to response object
+ deserialization behavior.
+
+ Returns:
+ An InvocationLink.
+ """
+ return _InvocationLink(
+ channel, host, request_serializers, response_deserializers)
diff --git a/src/python/src/grpc/_links/service.py b/src/python/src/grpc/_links/service.py
new file mode 100644
index 0000000000..7783e91824
--- /dev/null
+++ b/src/python/src/grpc/_links/service.py
@@ -0,0 +1,402 @@
+# 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.
+
+"""The RPC-service-side bridge between RPC Framework and GRPC-on-the-wire."""
+
+import abc
+import enum
+import logging
+import threading
+import time
+
+from grpc._adapter import _intermediary_low
+from grpc.framework.foundation import logging_pool
+from grpc.framework.foundation import relay
+from grpc.framework.interfaces.links import links
+
+
+@enum.unique
+class _Read(enum.Enum):
+ READING = 'reading'
+ AWAITING_ALLOWANCE = 'awaiting allowance'
+ CLOSED = 'closed'
+
+
+@enum.unique
+class _HighWrite(enum.Enum):
+ OPEN = 'open'
+ CLOSED = 'closed'
+
+
+@enum.unique
+class _LowWrite(enum.Enum):
+ """The possible categories of low-level write state."""
+
+ OPEN = 'OPEN'
+ ACTIVE = 'ACTIVE'
+ CLOSED = 'CLOSED'
+
+
+class _RPCState(object):
+
+ def __init__(
+ self, request_deserializer, response_serializer, sequence_number, read,
+ allowance, high_write, low_write, premetadataed, terminal_metadata, code,
+ message):
+ self.request_deserializer = request_deserializer
+ self.response_serializer = response_serializer
+ self.sequence_number = sequence_number
+ self.read = read
+ self.allowance = allowance
+ self.high_write = high_write
+ self.low_write = low_write
+ self.premetadataed = premetadataed
+ self.terminal_metadata = terminal_metadata
+ self.code = code
+ self.message = message
+
+
+def _metadatafy(call, metadata):
+ for metadata_key, metadata_value in metadata:
+ call.add_metadata(metadata_key, metadata_value)
+
+
+class _Kernel(object):
+
+ def __init__(self, request_deserializers, response_serializers, ticket_relay):
+ self._lock = threading.Lock()
+ self._request_deserializers = request_deserializers
+ self._response_serializers = response_serializers
+ self._relay = ticket_relay
+
+ self._completion_queue = None
+ self._server = None
+ self._rpc_states = {}
+ self._pool = None
+
+ def _on_service_acceptance_event(self, event, server):
+ server.service(None)
+
+ service_acceptance = event.service_acceptance
+ call = service_acceptance.call
+ call.accept(self._completion_queue, call)
+ try:
+ group, method = service_acceptance.method.split('/')[1:3]
+ except ValueError:
+ logging.info('Illegal path "%s"!', service_acceptance.method)
+ return
+ request_deserializer = self._request_deserializers.get((group, method))
+ response_serializer = self._response_serializers.get((group, method))
+ if request_deserializer is None or response_serializer is None:
+ # TODO(nathaniel): Terminate the RPC with code NOT_FOUND.
+ call.cancel()
+ return
+
+ call.read(call)
+ self._rpc_states[call] = _RPCState(
+ request_deserializer, response_serializer, 1, _Read.READING, 0,
+ _HighWrite.OPEN, _LowWrite.OPEN, False, None, None, None)
+ ticket = links.Ticket(
+ call, 0, group, method, links.Ticket.Subscription.FULL,
+ service_acceptance.deadline - time.time(), None, event.metadata, None,
+ None, None, None, None)
+ self._relay.add_value(ticket)
+
+ def _on_read_event(self, event):
+ call = event.tag
+ rpc_state = self._rpc_states.get(call, None)
+ if rpc_state is None:
+ return
+
+ if event.bytes is None:
+ rpc_state.read = _Read.CLOSED
+ payload = None
+ termination = links.Ticket.Termination.COMPLETION
+ else:
+ if 0 < rpc_state.allowance:
+ rpc_state.allowance -= 1
+ call.read(call)
+ else:
+ rpc_state.read = _Read.AWAITING_ALLOWANCE
+ payload = rpc_state.request_deserializer(event.bytes)
+ termination = None
+ ticket = links.Ticket(
+ call, rpc_state.sequence_number, None, None, None, None, None, None,
+ payload, None, None, None, termination)
+ rpc_state.sequence_number += 1
+ self._relay.add_value(ticket)
+
+ def _on_write_event(self, event):
+ call = event.tag
+ rpc_state = self._rpc_states.get(call, None)
+ if rpc_state is None:
+ return
+
+ if rpc_state.high_write is _HighWrite.CLOSED:
+ if rpc_state.terminal_metadata is not None:
+ _metadatafy(call, rpc_state.terminal_metadata)
+ call.status(
+ _intermediary_low.Status(rpc_state.code, rpc_state.message), call)
+ rpc_state.low_write = _LowWrite.CLOSED
+ else:
+ ticket = links.Ticket(
+ call, rpc_state.sequence_number, None, None, None, None, 1, None,
+ None, None, None, None, None)
+ rpc_state.sequence_number += 1
+ self._relay.add_value(ticket)
+ rpc_state.low_write = _LowWrite.OPEN
+
+ def _on_finish_event(self, event):
+ call = event.tag
+ rpc_state = self._rpc_states.pop(call, None)
+ if rpc_state is None:
+ return
+ code = event.status.code
+ if code is _intermediary_low.Code.OK:
+ return
+
+ if code is _intermediary_low.Code.CANCELLED:
+ termination = links.Ticket.Termination.CANCELLATION
+ elif code is _intermediary_low.Code.DEADLINE_EXCEEDED:
+ termination = links.Ticket.Termination.EXPIRATION
+ else:
+ termination = links.Ticket.Termination.TRANSMISSION_FAILURE
+ ticket = links.Ticket(
+ call, rpc_state.sequence_number, None, None, None, None, None, None,
+ None, None, None, None, termination)
+ rpc_state.sequence_number += 1
+ self._relay.add_value(ticket)
+
+ def _spin(self, completion_queue, server):
+ while True:
+ event = completion_queue.get(None)
+ if event.kind is _intermediary_low.Event.Kind.STOP:
+ return
+ with self._lock:
+ if self._server is None:
+ continue
+ elif event.kind is _intermediary_low.Event.Kind.SERVICE_ACCEPTED:
+ self._on_service_acceptance_event(event, server)
+ elif event.kind is _intermediary_low.Event.Kind.READ_ACCEPTED:
+ self._on_read_event(event)
+ elif event.kind is _intermediary_low.Event.Kind.WRITE_ACCEPTED:
+ self._on_write_event(event)
+ elif event.kind is _intermediary_low.Event.Kind.COMPLETE_ACCEPTED:
+ pass
+ elif event.kind is _intermediary_low.Event.Kind.FINISH:
+ self._on_finish_event(event)
+ else:
+ logging.error('Illegal event! %s', (event,))
+
+ def add_ticket(self, ticket):
+ with self._lock:
+ if self._server is None:
+ return
+ call = ticket.operation_id
+ rpc_state = self._rpc_states.get(call)
+ if rpc_state is None:
+ return
+
+ if ticket.initial_metadata is not None:
+ _metadatafy(call, ticket.initial_metadata)
+ call.premetadata()
+ rpc_state.premetadataed = True
+ elif not rpc_state.premetadataed:
+ if (ticket.terminal_metadata is not None or
+ ticket.payload is not None or
+ ticket.termination is links.Ticket.Termination.COMPLETION or
+ ticket.code is not None or
+ ticket.message is not None):
+ call.premetadata()
+ rpc_state.premetadataed = True
+
+ if ticket.allowance is not None:
+ if rpc_state.read is _Read.AWAITING_ALLOWANCE:
+ rpc_state.allowance += ticket.allowance - 1
+ call.read(call)
+ rpc_state.read = _Read.READING
+ else:
+ rpc_state.allowance += ticket.allowance
+
+ if ticket.payload is not None:
+ call.write(rpc_state.response_serializer(ticket.payload), call)
+ rpc_state.low_write = _LowWrite.ACTIVE
+
+ if ticket.terminal_metadata is not None:
+ rpc_state.terminal_metadata = ticket.terminal_metadata
+ if ticket.code is not None:
+ rpc_state.code = ticket.code
+ if ticket.message is not None:
+ rpc_state.message = ticket.message
+
+ if ticket.termination is links.Ticket.Termination.COMPLETION:
+ rpc_state.high_write = _HighWrite.CLOSED
+ if rpc_state.low_write is _LowWrite.OPEN:
+ if rpc_state.terminal_metadata is not None:
+ _metadatafy(call, rpc_state.terminal_metadata)
+ status = _intermediary_low.Status(
+ _intermediary_low.Code.OK
+ if rpc_state.code is None else rpc_state.code,
+ '' if rpc_state.message is None else rpc_state.message)
+ call.status(status, call)
+ rpc_state.low_write = _LowWrite.CLOSED
+ elif ticket.termination is not None:
+ call.cancel()
+ self._rpc_states.pop(call, None)
+
+ def add_port(self, port, server_credentials):
+ with self._lock:
+ address = '[::]:%d' % port
+ if self._server is None:
+ self._completion_queue = _intermediary_low.CompletionQueue()
+ self._server = _intermediary_low.Server(self._completion_queue)
+ if server_credentials is None:
+ return self._server.add_http2_addr(address)
+ else:
+ return self._server.add_secure_http2_addr(address, server_credentials)
+
+ def start(self):
+ with self._lock:
+ if self._server is None:
+ self._completion_queue = _intermediary_low.CompletionQueue()
+ self._server = _intermediary_low.Server(self._completion_queue)
+ self._pool = logging_pool.pool(1)
+ self._pool.submit(self._spin, self._completion_queue, self._server)
+ self._server.start()
+ self._server.service(None)
+
+ def graceful_stop(self):
+ with self._lock:
+ self._server.stop()
+ self._server = None
+ self._completion_queue.stop()
+ self._completion_queue = None
+ pool = self._pool
+ self._pool = None
+ self._rpc_states = None
+ pool.shutdown(wait=True)
+
+ def immediate_stop(self):
+ # TODO(nathaniel): Implementation.
+ raise NotImplementedError(
+ 'TODO(nathaniel): after merge of rewritten lower layers')
+
+
+class ServiceLink(links.Link):
+ """A links.Link for use on the service-side of a gRPC connection.
+
+ Implementations of this interface are only valid for use between calls to
+ their start method and one of their stop methods.
+ """
+
+ @abc.abstractmethod
+ def add_port(self, port, server_credentials):
+ """Adds a port on which to service RPCs after this link has been started.
+
+ Args:
+ port: The port on which to service RPCs, or zero to request that a port be
+ automatically selected and used.
+ server_credentials: A ServerCredentials object, or None for insecure
+ service.
+
+ Returns:
+ A port on which RPCs will be serviced after this link has been started.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def start(self):
+ """Starts this object.
+
+ This method must be called before attempting to use this Link in ticket
+ exchange.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def stop_gracefully(self):
+ """Stops this link.
+
+ New RPCs will be rejected as soon as this method is called, but ongoing RPCs
+ will be allowed to continue until they terminate. This method blocks until
+ all RPCs have terminated.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def stop_immediately(self):
+ """Stops this link.
+
+ All in-progress RPCs will be terminated immediately.
+ """
+ raise NotImplementedError()
+
+
+class _ServiceLink(ServiceLink):
+
+ def __init__(self, request_deserializers, response_serializers):
+ self._relay = relay.relay(None)
+ self._kernel = _Kernel(
+ request_deserializers, response_serializers, self._relay)
+
+ def accept_ticket(self, ticket):
+ self._kernel.add_ticket(ticket)
+
+ def join_link(self, link):
+ self._relay.set_behavior(link.accept_ticket)
+
+ def add_port(self, port, server_credentials):
+ return self._kernel.add_port(port, server_credentials)
+
+ def start(self):
+ self._relay.start()
+ return self._kernel.start()
+
+ def stop_gracefully(self):
+ self._kernel.graceful_stop()
+ self._relay.stop()
+
+ def stop_immediately(self):
+ self._kernel.immediate_stop()
+ self._relay.stop()
+
+
+def service_link(request_deserializers, response_serializers):
+ """Creates a ServiceLink.
+
+ Args:
+ request_deserializers: A dict from group-method pair to request object
+ deserialization behavior.
+ response_serializers: A dict from group-method pair to response ojbect
+ serialization behavior.
+
+ Returns:
+ A ServiceLink.
+ """
+ return _ServiceLink(request_deserializers, response_serializers)
diff --git a/src/python/src/grpc/framework/common/test_constants.py b/src/python/src/grpc/framework/common/test_constants.py
new file mode 100644
index 0000000000..237b8754ed
--- /dev/null
+++ b/src/python/src/grpc/framework/common/test_constants.py
@@ -0,0 +1,37 @@
+# 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.
+
+"""Constants shared among tests throughout RPC Framework."""
+
+# Value for maximum duration in seconds of RPCs that may time out as part of a
+# test.
+SHORT_TIMEOUT = 4
+# Absurdly large value for maximum duration in seconds for should-not-time-out
+# RPCs made during tests.
+LONG_TIMEOUT = 3000
diff --git a/src/python/src/grpc/framework/common/test_control.py b/src/python/src/grpc/framework/common/test_control.py
new file mode 100644
index 0000000000..3960c4e649
--- /dev/null
+++ b/src/python/src/grpc/framework/common/test_control.py
@@ -0,0 +1,87 @@
+# 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.
+
+"""Code for instructing systems under test to block or fail."""
+
+import abc
+import contextlib
+import threading
+
+
+class Control(object):
+ """An object that accepts program control from a system under test.
+
+ Systems under test passed a Control should call its control() method
+ frequently during execution. The control() method may block, raise an
+ exception, or do nothing, all according to the enclosing test's desire for
+ the system under test to simulate hanging, failing, or functioning.
+ """
+
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def control(self):
+ """Potentially does anything."""
+ raise NotImplementedError()
+
+
+class PauseFailControl(Control):
+ """A Control that can be used to pause or fail code under control."""
+
+ def __init__(self):
+ self._condition = threading.Condition()
+ self._paused = False
+ self._fail = False
+
+ def control(self):
+ with self._condition:
+ if self._fail:
+ raise ValueError()
+
+ while self._paused:
+ self._condition.wait()
+
+ @contextlib.contextmanager
+ def pause(self):
+ """Pauses code under control while controlling code is in context."""
+ with self._condition:
+ self._paused = True
+ yield
+ with self._condition:
+ self._paused = False
+ self._condition.notify_all()
+
+ @contextlib.contextmanager
+ def fail(self):
+ """Fails code under control while controlling code is in context."""
+ with self._condition:
+ self._fail = True
+ yield
+ with self._condition:
+ self._fail = False
diff --git a/src/python/src/grpc/framework/common/test_coverage.py b/src/python/src/grpc/framework/common/test_coverage.py
new file mode 100644
index 0000000000..a7ed3582c4
--- /dev/null
+++ b/src/python/src/grpc/framework/common/test_coverage.py
@@ -0,0 +1,116 @@
+# 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.
+
+"""Governs coverage for tests of RPCs throughout RPC Framework."""
+
+import abc
+
+# This code is designed for use with the unittest module.
+# pylint: disable=invalid-name
+
+
+class Coverage(object):
+ """Specification of test coverage."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def testSuccessfulUnaryRequestUnaryResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testSuccessfulUnaryRequestStreamResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testSuccessfulStreamRequestUnaryResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testSuccessfulStreamRequestStreamResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testSequentialInvocations(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testParallelInvocations(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testWaitingForSomeButNotAllParallelInvocations(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testCancelledUnaryRequestUnaryResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testCancelledUnaryRequestStreamResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testCancelledStreamRequestUnaryResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testCancelledStreamRequestStreamResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testExpiredUnaryRequestUnaryResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testExpiredUnaryRequestStreamResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testExpiredStreamRequestUnaryResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testExpiredStreamRequestStreamResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testFailedUnaryRequestUnaryResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testFailedUnaryRequestStreamResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testFailedStreamRequestUnaryResponse(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def testFailedStreamRequestStreamResponse(self):
+ raise NotImplementedError()
diff --git a/src/python/src/grpc/framework/foundation/relay.py b/src/python/src/grpc/framework/foundation/relay.py
new file mode 100644
index 0000000000..9c23946552
--- /dev/null
+++ b/src/python/src/grpc/framework/foundation/relay.py
@@ -0,0 +1,175 @@
+# 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.
+
+"""Implementations of in-order work deference."""
+
+import abc
+import enum
+import threading
+
+from grpc.framework.foundation import activated
+from grpc.framework.foundation import logging_pool
+
+_NULL_BEHAVIOR = lambda unused_value: None
+
+
+class Relay(object):
+ """Performs work submitted to it in another thread.
+
+ Performs work in the order in which work was submitted to it; otherwise there
+ would be no reason to use an implementation of this interface instead of a
+ thread pool.
+ """
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def add_value(self, value):
+ """Adds a value to be passed to the behavior registered with this Relay.
+
+ Args:
+ value: A value that will be passed to a call made in another thread to the
+ behavior registered with this Relay.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def set_behavior(self, behavior):
+ """Sets the behavior that this Relay should call when passed values.
+
+ Args:
+ behavior: The behavior that this Relay should call in another thread when
+ passed a value, or None to have passed values ignored.
+ """
+ raise NotImplementedError()
+
+
+class _PoolRelay(activated.Activated, Relay):
+
+ @enum.unique
+ class _State(enum.Enum):
+ INACTIVE = 'inactive'
+ IDLE = 'idle'
+ SPINNING = 'spinning'
+
+ def __init__(self, pool, behavior):
+ self._condition = threading.Condition()
+ self._pool = pool
+ self._own_pool = pool is None
+ self._state = _PoolRelay._State.INACTIVE
+ self._activated = False
+ self._spinning = False
+ self._values = []
+ self._behavior = _NULL_BEHAVIOR if behavior is None else behavior
+
+ def _spin(self, behavior, value):
+ while True:
+ behavior(value)
+ with self._condition:
+ if self._values:
+ value = self._values.pop(0)
+ behavior = self._behavior
+ else:
+ self._state = _PoolRelay._State.IDLE
+ self._condition.notify_all()
+ break
+
+ def add_value(self, value):
+ with self._condition:
+ if self._state is _PoolRelay._State.INACTIVE:
+ raise ValueError('add_value not valid on inactive Relay!')
+ elif self._state is _PoolRelay._State.IDLE:
+ self._pool.submit(self._spin, self._behavior, value)
+ self._state = _PoolRelay._State.SPINNING
+ else:
+ self._values.append(value)
+
+ def set_behavior(self, behavior):
+ with self._condition:
+ self._behavior = _NULL_BEHAVIOR if behavior is None else behavior
+
+ def _start(self):
+ with self._condition:
+ self._state = _PoolRelay._State.IDLE
+ if self._own_pool:
+ self._pool = logging_pool.pool(1)
+ return self
+
+ def _stop(self):
+ with self._condition:
+ while self._state is _PoolRelay._State.SPINNING:
+ self._condition.wait()
+ if self._own_pool:
+ self._pool.shutdown(wait=True)
+ self._state = _PoolRelay._State.INACTIVE
+
+ def __enter__(self):
+ return self._start()
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self._stop()
+ return False
+
+ def start(self):
+ return self._start()
+
+ def stop(self):
+ self._stop()
+
+
+def relay(behavior):
+ """Creates a Relay.
+
+ Args:
+ behavior: The behavior to be called by the created Relay, or None to have
+ passed values dropped until a different behavior is given to the returned
+ Relay later.
+
+ Returns:
+ An object that is both an activated.Activated and a Relay. The object is
+ only valid for use as a Relay when activated.
+ """
+ return _PoolRelay(None, behavior)
+
+
+def pool_relay(pool, behavior):
+ """Creates a Relay that uses a given thread pool.
+
+ This object will make use of at most one thread in the given pool.
+
+ Args:
+ pool: A futures.ThreadPoolExecutor for use by the created Relay.
+ behavior: The behavior to be called by the created Relay, or None to have
+ passed values dropped until a different behavior is given to the returned
+ Relay later.
+
+ Returns:
+ An object that is both an activated.Activated and a Relay. The object is
+ only valid for use as a Relay when activated.
+ """
+ return _PoolRelay(pool, behavior)
diff --git a/src/python/src/grpc/framework/interfaces/__init__.py b/src/python/src/grpc/framework/interfaces/__init__.py
new file mode 100644
index 0000000000..7086519106
--- /dev/null
+++ b/src/python/src/grpc/framework/interfaces/__init__.py
@@ -0,0 +1,30 @@
+# 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.
+
+
diff --git a/src/python/src/grpc/framework/interfaces/links/__init__.py b/src/python/src/grpc/framework/interfaces/links/__init__.py
new file mode 100644
index 0000000000..7086519106
--- /dev/null
+++ b/src/python/src/grpc/framework/interfaces/links/__init__.py
@@ -0,0 +1,30 @@
+# 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.
+
+
diff --git a/src/python/src/grpc/framework/interfaces/links/links.py b/src/python/src/grpc/framework/interfaces/links/links.py
new file mode 100644
index 0000000000..5ebbac8a6f
--- /dev/null
+++ b/src/python/src/grpc/framework/interfaces/links/links.py
@@ -0,0 +1,124 @@
+# 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.
+
+"""The low-level ticket-exchanging-links interface of RPC Framework."""
+
+import abc
+import collections
+import enum
+
+
+class Ticket(
+ collections.namedtuple(
+ 'Ticket',
+ ['operation_id', 'sequence_number', 'group', 'method', 'subscription',
+ 'timeout', 'allowance', 'initial_metadata', 'payload',
+ 'terminal_metadata', 'code', 'message', 'termination'])):
+ """A sum type for all values sent from a front to a back.
+
+ Attributes:
+ operation_id: A unique-with-respect-to-equality hashable object identifying
+ a particular operation.
+ sequence_number: A zero-indexed integer sequence number identifying the
+ ticket's place in the stream of tickets sent in one direction for the
+ particular operation.
+ group: The group to which the method of the operation belongs. Must be
+ present in the first ticket from invocation side to service side. Ignored
+ for all other tickets exchanged during the operation.
+ method: The name of an operation. Must be present in the first ticket from
+ invocation side to service side. Ignored for all other tickets exchanged
+ during the operation.
+ subscription: A Subscription value describing the interest one side has in
+ receiving information from the other side. Must be present in the first
+ ticket from either side. Ignored for all other tickets exchanged during
+ the operation.
+ timeout: A nonzero length of time (measured from the beginning of the
+ operation) to allow for the entire operation. Must be present in the first
+ ticket from invocation side to service side. Optional for all other
+ tickets exchanged during the operation. Receipt of a value from the other
+ side of the operation indicates the value in use by that side. Setting a
+ value on a later ticket allows either side to request time extensions (or
+ even time reductions!) on in-progress operations.
+ allowance: A positive integer granting permission for a number of payloads
+ to be transmitted to the communicating side of the operation, or None if
+ no additional allowance is being granted with this ticket.
+ initial_metadata: An optional metadata value communicated from one side to
+ the other at the beginning of the operation. May be non-None in at most
+ one ticket from each side. Any non-None value must appear no later than
+ the first payload value.
+ payload: A customer payload object. May be None.
+ terminal_metadata: A metadata value comminicated from one side to the other
+ at the end of the operation. May be non-None in the same ticket as
+ the code and message, but must be None for all earlier tickets.
+ code: A value communicated at operation completion. May be None.
+ message: A value communicated at operation completion. May be None.
+ termination: A Termination value describing the end of the operation, or
+ None if the operation has not yet terminated. If set, no further tickets
+ may be sent in the same direction.
+ """
+
+ @enum.unique
+ class Subscription(enum.Enum):
+ """Identifies the level of subscription of a side of an operation."""
+
+ NONE = 'none'
+ TERMINATION = 'termination'
+ FULL = 'full'
+
+ @enum.unique
+ class Termination(enum.Enum):
+ """Identifies the termination of an operation."""
+
+ COMPLETION = 'completion'
+ CANCELLATION = 'cancellation'
+ EXPIRATION = 'expiration'
+ LOCAL_SHUTDOWN = 'local shutdown'
+ RECEPTION_FAILURE = 'reception failure'
+ TRANSMISSION_FAILURE = 'transmission failure'
+ LOCAL_FAILURE = 'local failure'
+ REMOTE_FAILURE = 'remote failure'
+
+
+class Link(object):
+ """Accepts and emits tickets."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def accept_ticket(self, ticket):
+ """Accept a Ticket.
+
+ Args:
+ ticket: Any Ticket.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def join_link(self, link):
+ """Mates this object with a peer with which it will exchange tickets."""
+ raise NotImplementedError()
diff --git a/src/python/src/grpc/framework/interfaces/links/test_cases.py b/src/python/src/grpc/framework/interfaces/links/test_cases.py
new file mode 100644
index 0000000000..3ac212ebdf
--- /dev/null
+++ b/src/python/src/grpc/framework/interfaces/links/test_cases.py
@@ -0,0 +1,332 @@
+# 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.
+
+"""Tests of the links interface of RPC Framework."""
+
+# unittest is referenced from specification in this module.
+import abc
+import unittest # pylint: disable=unused-import
+
+from grpc.framework.common import test_constants
+from grpc.framework.interfaces.links import links
+from grpc.framework.interfaces.links import test_utilities
+
+
+def at_least_n_payloads_received_predicate(n):
+ def predicate(ticket_sequence):
+ payload_count = 0
+ for ticket in ticket_sequence:
+ if ticket.payload is not None:
+ payload_count += 1
+ if n <= payload_count:
+ return True
+ else:
+ return False
+ return predicate
+
+
+def terminated(ticket_sequence):
+ return ticket_sequence and ticket_sequence[-1].termination is not None
+
+_TRANSMISSION_GROUP = 'test.Group'
+_TRANSMISSION_METHOD = 'TestMethod'
+
+
+class TransmissionTest(object):
+ """Tests ticket transmission between two connected links.
+
+ This class must be mixed into a unittest.TestCase that implements the abstract
+ methods it provides.
+ """
+ __metaclass__ = abc.ABCMeta
+
+ # This is a unittest.TestCase mix-in.
+ # pylint: disable=invalid-name
+
+ @abc.abstractmethod
+ def create_transmitting_links(self):
+ """Creates two connected links for use in this test.
+
+ Returns:
+ Two links.Links, the first of which will be used on the invocation side
+ of RPCs and the second of which will be used on the service side of
+ RPCs.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def destroy_transmitting_links(self, invocation_side_link, service_side_link):
+ """Destroys the two connected links created for this test.
+
+
+ Args:
+ invocation_side_link: The link used on the invocation side of RPCs in
+ this test.
+ service_side_link: The link used on the service side of RPCs in this
+ test.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def create_invocation_initial_metadata(self):
+ """Creates a value for use as invocation-side initial metadata.
+
+ Returns:
+ A metadata value appropriate for use as invocation-side initial metadata
+ or None if invocation-side initial metadata transmission is not
+ supported by the links under test.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def create_invocation_terminal_metadata(self):
+ """Creates a value for use as invocation-side terminal metadata.
+
+ Returns:
+ A metadata value appropriate for use as invocation-side terminal
+ metadata or None if invocation-side terminal metadata transmission is
+ not supported by the links under test.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def create_service_initial_metadata(self):
+ """Creates a value for use as service-side initial metadata.
+
+ Returns:
+ A metadata value appropriate for use as service-side initial metadata or
+ None if service-side initial metadata transmission is not supported by
+ the links under test.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def create_service_terminal_metadata(self):
+ """Creates a value for use as service-side terminal metadata.
+
+ Returns:
+ A metadata value appropriate for use as service-side terminal metadata or
+ None if service-side terminal metadata transmission is not supported by
+ the links under test.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def create_invocation_completion(self):
+ """Creates values for use as invocation-side code and message.
+
+ Returns:
+ An invocation-side code value and an invocation-side message value.
+ Either or both may be None if invocation-side code and/or
+ invocation-side message transmission is not supported by the links
+ under test.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def create_service_completion(self):
+ """Creates values for use as service-side code and message.
+
+ Returns:
+ A service-side code value and a service-side message value. Either or
+ both may be None if service-side code and/or service-side message
+ transmission is not supported by the links under test.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def assertMetadataEqual(self, original_metadata, transmitted_metadata):
+ """Asserts that two metadata objects are equal.
+
+ Args:
+ original_metadata: A metadata object used in this test.
+ transmitted_metadata: A metadata object obtained after transmission
+ through the system under test.
+
+ Raises:
+ AssertionError: if the two metadata objects are not equal.
+ """
+ raise NotImplementedError()
+
+ def group_and_method(self):
+ """Returns the group and method used in this test case.
+
+ Returns:
+ A pair of the group and method used in this test case.
+ """
+ return _TRANSMISSION_GROUP, _TRANSMISSION_METHOD
+
+ def serialize_request(self, request):
+ """Serializes a request value used in this test case.
+
+ Args:
+ request: A request value created by this test case.
+
+ Returns:
+ A bytestring that is the serialization of the given request.
+ """
+ return request
+
+ def deserialize_request(self, serialized_request):
+ """Deserializes a request value used in this test case.
+
+ Args:
+ serialized_request: A bytestring that is the serialization of some request
+ used in this test case.
+
+ Returns:
+ The request value encoded by the given bytestring.
+ """
+ return serialized_request
+
+ def serialize_response(self, response):
+ """Serializes a response value used in this test case.
+
+ Args:
+ response: A response value created by this test case.
+
+ Returns:
+ A bytestring that is the serialization of the given response.
+ """
+ return response
+
+ def deserialize_response(self, serialized_response):
+ """Deserializes a response value used in this test case.
+
+ Args:
+ serialized_response: A bytestring that is the serialization of some
+ response used in this test case.
+
+ Returns:
+ The response value encoded by the given bytestring.
+ """
+ return serialized_response
+
+ def _assert_is_valid_metadata_payload_sequence(
+ self, ticket_sequence, payloads, initial_metadata, terminal_metadata):
+ initial_metadata_seen = False
+ seen_payloads = []
+ terminal_metadata_seen = False
+
+ for ticket in ticket_sequence:
+ if ticket.initial_metadata is not None:
+ self.assertFalse(initial_metadata_seen)
+ self.assertFalse(seen_payloads)
+ self.assertFalse(terminal_metadata_seen)
+ self.assertMetadataEqual(initial_metadata, ticket.initial_metadata)
+ initial_metadata_seen = True
+
+ if ticket.payload is not None:
+ self.assertFalse(terminal_metadata_seen)
+ seen_payloads.append(ticket.payload)
+
+ if ticket.terminal_metadata is not None:
+ self.assertFalse(terminal_metadata_seen)
+ self.assertMetadataEqual(terminal_metadata, ticket.terminal_metadata)
+ terminal_metadata_seen = True
+ self.assertSequenceEqual(payloads, seen_payloads)
+
+ def _assert_is_valid_invocation_sequence(
+ self, ticket_sequence, group, method, payloads, initial_metadata,
+ terminal_metadata, termination):
+ self.assertLess(0, len(ticket_sequence))
+ self.assertEqual(group, ticket_sequence[0].group)
+ self.assertEqual(method, ticket_sequence[0].method)
+ self._assert_is_valid_metadata_payload_sequence(
+ ticket_sequence, payloads, initial_metadata, terminal_metadata)
+ self.assertIs(termination, ticket_sequence[-1].termination)
+
+ def _assert_is_valid_service_sequence(
+ self, ticket_sequence, payloads, initial_metadata, terminal_metadata,
+ code, message, termination):
+ self.assertLess(0, len(ticket_sequence))
+ self._assert_is_valid_metadata_payload_sequence(
+ ticket_sequence, payloads, initial_metadata, terminal_metadata)
+ self.assertEqual(code, ticket_sequence[-1].code)
+ self.assertEqual(message, ticket_sequence[-1].message)
+ self.assertIs(termination, ticket_sequence[-1].termination)
+
+ def setUp(self):
+ self._invocation_link, self._service_link = self.create_transmitting_links()
+ self._invocation_mate = test_utilities.RecordingLink()
+ self._service_mate = test_utilities.RecordingLink()
+ self._invocation_link.join_link(self._invocation_mate)
+ self._service_link.join_link(self._service_mate)
+
+ def tearDown(self):
+ self.destroy_transmitting_links(self._invocation_link, self._service_link)
+
+ def testSimplestRoundTrip(self):
+ """Tests transmission of one ticket in each direction."""
+ invocation_operation_id = object()
+ invocation_payload = b'\x07' * 1023
+ timeout = test_constants.LONG_TIMEOUT
+ invocation_initial_metadata = self.create_invocation_initial_metadata()
+ invocation_terminal_metadata = self.create_invocation_terminal_metadata()
+ invocation_code, invocation_message = self.create_invocation_completion()
+ service_payload = b'\x08' * 1025
+ service_initial_metadata = self.create_service_initial_metadata()
+ service_terminal_metadata = self.create_service_terminal_metadata()
+ service_code, service_message = self.create_service_completion()
+
+ original_invocation_ticket = links.Ticket(
+ invocation_operation_id, 0, _TRANSMISSION_GROUP, _TRANSMISSION_METHOD,
+ links.Ticket.Subscription.FULL, timeout, 0, invocation_initial_metadata,
+ invocation_payload, invocation_terminal_metadata, invocation_code,
+ invocation_message, links.Ticket.Termination.COMPLETION)
+ self._invocation_link.accept_ticket(original_invocation_ticket)
+
+ # TODO(nathaniel): This shouldn't be necessary. Detecting the end of the
+ # invocation-side ticket sequence shouldn't require granting allowance for
+ # another payload.
+ self._service_mate.block_until_tickets_satisfy(
+ at_least_n_payloads_received_predicate(1))
+ service_operation_id = self._service_mate.tickets()[0].operation_id
+ self._service_link.accept_ticket(
+ links.Ticket(
+ service_operation_id, 0, None, None, links.Ticket.Subscription.FULL,
+ None, 1, None, None, None, None, None, None))
+
+ self._service_mate.block_until_tickets_satisfy(terminated)
+ self._assert_is_valid_invocation_sequence(
+ self._service_mate.tickets(), _TRANSMISSION_GROUP, _TRANSMISSION_METHOD,
+ (invocation_payload,), invocation_initial_metadata,
+ invocation_terminal_metadata, links.Ticket.Termination.COMPLETION)
+
+ original_service_ticket = links.Ticket(
+ service_operation_id, 1, None, None, links.Ticket.Subscription.FULL,
+ timeout, 0, service_initial_metadata, service_payload,
+ service_terminal_metadata, service_code, service_message,
+ links.Ticket.Termination.COMPLETION)
+ self._service_link.accept_ticket(original_service_ticket)
+ self._invocation_mate.block_until_tickets_satisfy(terminated)
+ self._assert_is_valid_service_sequence(
+ self._invocation_mate.tickets(), (service_payload,),
+ service_initial_metadata, service_terminal_metadata, service_code,
+ service_message, links.Ticket.Termination.COMPLETION)
diff --git a/src/python/src/grpc/framework/interfaces/links/test_utilities.py b/src/python/src/grpc/framework/interfaces/links/test_utilities.py
new file mode 100644
index 0000000000..6c2e3346aa
--- /dev/null
+++ b/src/python/src/grpc/framework/interfaces/links/test_utilities.py
@@ -0,0 +1,66 @@
+# 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.
+
+"""State and behavior appropriate for use in tests."""
+
+import threading
+
+from grpc.framework.interfaces.links import links
+
+
+class RecordingLink(links.Link):
+ """A Link that records every ticket passed to it."""
+
+ def __init__(self):
+ self._condition = threading.Condition()
+ self._tickets = []
+
+ def accept_ticket(self, ticket):
+ with self._condition:
+ self._tickets.append(ticket)
+ self._condition.notify_all()
+
+ def join_link(self, link):
+ pass
+
+ def block_until_tickets_satisfy(self, predicate):
+ """Blocks until the received tickets satisfy the given predicate.
+
+ Args:
+ predicate: A callable that takes a sequence of tickets and returns a
+ boolean value.
+ """
+ with self._condition:
+ while not predicate(self._tickets):
+ self._condition.wait()
+
+ def tickets(self):
+ """Returns a copy of the list of all tickets received by this Link."""
+ with self._condition:
+ return tuple(self._tickets)
diff --git a/src/python/src/grpc/framework/interfaces/links/utilities.py b/src/python/src/grpc/framework/interfaces/links/utilities.py
new file mode 100644
index 0000000000..6e4fd76d93
--- /dev/null
+++ b/src/python/src/grpc/framework/interfaces/links/utilities.py
@@ -0,0 +1,44 @@
+# 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.
+
+"""Utilities provided as part of the links interface."""
+
+from grpc.framework.interfaces.links import links
+
+
+class _NullLink(links.Link):
+ """A do-nothing links.Link."""
+
+ def accept_ticket(self, ticket):
+ pass
+
+ def join_link(self, link):
+ pass
+
+NULL_LINK = _NullLink()
diff --git a/src/python/src/setup.py b/src/python/src/setup.py
index 5398b09936..a857ae98cc 100644
--- a/src/python/src/setup.py
+++ b/src/python/src/setup.py
@@ -29,11 +29,19 @@
"""A setup module for the GRPC Python package."""
+import os
+import sys
+
from distutils import core as _core
import setuptools
-import sys
-_EXTENSION_SOURCES = (
+
+# Use environment variables to determine whether or not the Cython extension
+# should *use* Cython or use the generated C files. Note that this requires the
+# C files to have been generated by building first *with* Cython support.
+_BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False)
+
+_C_EXTENSION_SOURCES = (
'grpc/_adapter/_c/module.c',
'grpc/_adapter/_c/types.c',
'grpc/_adapter/_c/utility.c',
@@ -56,16 +64,19 @@ _EXTENSION_LIBRARIES = (
if not "darwin" in sys.platform:
_EXTENSION_LIBRARIES += ('rt',)
-_EXTENSION_MODULE = _core.Extension(
- 'grpc._adapter._c', sources=list(_EXTENSION_SOURCES),
+
+_C_EXTENSION_MODULE = _core.Extension(
+ 'grpc._adapter._c', sources=list(_C_EXTENSION_SOURCES),
include_dirs=list(_EXTENSION_INCLUDE_DIRECTORIES),
libraries=list(_EXTENSION_LIBRARIES),
- )
+)
+_EXTENSION_MODULES = [_C_EXTENSION_MODULE]
_PACKAGES = (
'grpc',
'grpc._adapter',
'grpc._junkdrawer',
+ 'grpc._links',
'grpc.early_adopter',
'grpc.framework',
'grpc.framework.alpha',
@@ -74,20 +85,23 @@ _PACKAGES = (
'grpc.framework.face',
'grpc.framework.face.testing',
'grpc.framework.foundation',
+ 'grpc.framework.interfaces',
+ 'grpc.framework.interfaces.links',
)
_PACKAGE_DIRECTORIES = {
'grpc': 'grpc',
'grpc._adapter': 'grpc/_adapter',
'grpc._junkdrawer': 'grpc/_junkdrawer',
+ 'grpc._links': 'grpc/_links',
'grpc.early_adopter': 'grpc/early_adopter',
'grpc.framework': 'grpc/framework',
}
setuptools.setup(
name='grpcio',
- version='0.9.0a1',
- ext_modules=[_EXTENSION_MODULE],
+ version='0.10.0a0',
+ ext_modules=_EXTENSION_MODULES,
packages=list(_PACKAGES),
package_dir=_PACKAGE_DIRECTORIES,
install_requires=[
diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb
index 6dd0234489..7972272e2d 100644
--- a/src/ruby/ext/grpc/extconf.rb
+++ b/src/ruby/ext/grpc/extconf.rb
@@ -54,44 +54,55 @@ LIB_DIRS = [
LIBDIR
]
-# Check to see if GRPC_ROOT is defined or available
-grpc_root = ENV['GRPC_ROOT']
-if grpc_root.nil?
- r = File.expand_path(File.join(File.dirname(__FILE__), '../../../..'))
- grpc_root = r if File.exist?(File.join(r, 'include/grpc/grpc.h'))
-end
-
-# When grpc_root is available attempt to build the grpc core.
-unless grpc_root.nil?
- grpc_config = ENV['GRPC_CONFIG'] || 'opt'
- if ENV.key?('GRPC_LIB_DIR')
- grpc_lib_dir = File.join(grpc_root, ENV['GRPC_LIB_DIR'])
- else
- grpc_lib_dir = File.join(File.join(grpc_root, 'libs'), grpc_config)
- end
- unless File.exist?(File.join(grpc_lib_dir, 'libgrpc.a'))
- system("make -C #{grpc_root} static_c CONFIG=#{grpc_config}")
+def check_grpc_root
+ grpc_root = ENV['GRPC_ROOT']
+ if grpc_root.nil?
+ r = File.expand_path(File.join(File.dirname(__FILE__), '../../../..'))
+ grpc_root = r if File.exist?(File.join(r, 'include/grpc/grpc.h'))
end
- HEADER_DIRS.unshift File.join(grpc_root, 'include')
- LIB_DIRS.unshift grpc_lib_dir
+ grpc_root
end
-def crash(msg)
- print(" extconf failure: #{msg}\n")
- exit 1
-end
+grpc_pkg_config = system('pkg-config --exists grpc')
+
+if grpc_pkg_config
+ $CFLAGS << ' ' + `pkg-config --static --cflags grpc`.strip + ' '
+ $LDFLAGS << ' ' + `pkg-config --static --libs grpc`.strip + ' '
+else
+ dir_config('grpc', HEADER_DIRS, LIB_DIRS)
+ fail 'libdl not found' unless have_library('dl', 'dlopen')
+ fail 'zlib not found' unless have_library('z', 'inflate')
+ begin
+ fail 'Fail' unless have_library('gpr', 'gpr_now')
+ fail 'Fail' unless have_library('grpc', 'grpc_channel_destroy')
+ rescue
+ # Check to see if GRPC_ROOT is defined or available
+ grpc_root = check_grpc_root
-dir_config('grpc', HEADER_DIRS, LIB_DIRS)
+ # Stop if there is still no grpc_root
+ exit 1 if grpc_root.nil?
-$CFLAGS << ' -Wno-implicit-function-declaration '
-$CFLAGS << ' -Wno-pointer-sign '
-$CFLAGS << ' -Wno-return-type '
+ grpc_config = ENV['GRPC_CONFIG'] || 'opt'
+ if ENV.key?('GRPC_LIB_DIR')
+ grpc_lib_dir = File.join(grpc_root, ENV['GRPC_LIB_DIR'])
+ else
+ grpc_lib_dir = File.join(File.join(grpc_root, 'libs'), grpc_config)
+ end
+ unless File.exist?(File.join(grpc_lib_dir, 'libgrpc.a'))
+ print "Building internal gRPC\n"
+ system("make -C #{grpc_root} static_c CONFIG=#{grpc_config}")
+ end
+ $CFLAGS << ' -I' + File.join(grpc_root, 'include')
+ $LDFLAGS << ' -L' + grpc_lib_dir
+ raise 'gpr not found' unless have_library('gpr', 'gpr_now')
+ raise 'grpc not found' unless have_library('grpc', 'grpc_channel_destroy')
+ end
+end
+
+$CFLAGS << ' -std=c99 '
$CFLAGS << ' -Wall '
+$CFLAGS << ' -Wextra '
$CFLAGS << ' -pedantic '
+$CFLAGS << ' -Werror '
-$LDFLAGS << ' -lgrpc -lgpr -lz -ldl'
-
-crash('need grpc lib') unless have_library('grpc', 'grpc_channel_destroy')
-have_library('grpc', 'grpc_channel_destroy')
-crash('need gpr lib') unless have_library('gpr', 'gpr_now')
create_makefile('grpc/grpc')
diff --git a/src/ruby/ext/grpc/rb_completion_queue.c b/src/ruby/ext/grpc/rb_completion_queue.c
index 8fb3949b3d..2d52d96dc8 100644
--- a/src/ruby/ext/grpc/rb_completion_queue.c
+++ b/src/ruby/ext/grpc/rb_completion_queue.c
@@ -91,7 +91,7 @@ static void grpc_rb_completion_queue_shutdown_drain(grpc_completion_queue *cq) {
* - investigate further, this is probably another example of C-level cleanup
* not working consistently in all cases.
*/
- next_call.timeout = gpr_time_add(gpr_now(), gpr_time_from_micros(5e3));
+ next_call.timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(5e3));
do {
rb_thread_call_without_gvl(grpc_rb_completion_queue_next_no_gil,
(void *)&next_call, NULL, NULL);
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index 9c0d24bf8f..bed3b26850 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -68,8 +68,12 @@ static void grpc_rb_server_free(void *p) {
/* Deletes the wrapped object if the mark object is Qnil, which indicates
that no other object is the actual owner. */
+ /* grpc_server_shutdown does not exist. Change this to something that does
+ or delete it */
if (svr->wrapped != NULL && svr->mark == Qnil) {
- grpc_server_shutdown(svr->wrapped);
+ // grpc_server_shutdown(svr->wrapped);
+ // Aborting to indicate a bug
+ abort();
grpc_server_destroy(svr->wrapped);
}
diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec
index 319da9470a..dd4e27df51 100755
--- a/src/ruby/grpc.gemspec
+++ b/src/ruby/grpc.gemspec
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
s.license = 'BSD-3-Clause'
s.required_ruby_version = '>= 2.0.0'
- s.requirements << 'libgrpc ~> 0.9.1 needs to be installed'
+ s.requirements << 'libgrpc ~> 0.10.0 needs to be installed'
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- spec/*`.split("\n")
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index a7e20d6b82..67bf35ce02 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -398,14 +398,14 @@ module GRPC
nil
end
- # Sends NOT_FOUND if the method can't be found
- def found?(an_rpc)
+ # Sends UNIMPLEMENTED if the method is not implemented by this server
+ def implemented?(an_rpc)
mth = an_rpc.method.to_sym
return an_rpc if rpc_descs.key?(mth)
- GRPC.logger.warn("NOT_FOUND: #{an_rpc}")
+ GRPC.logger.warn("UNIMPLEMENTED: #{an_rpc}")
noop = proc { |x| x }
c = ActiveCall.new(an_rpc.call, @cq, noop, noop, an_rpc.deadline)
- c.send_status(StatusCodes::NOT_FOUND, '')
+ c.send_status(StatusCodes::UNIMPLEMENTED, '')
nil
end
@@ -446,7 +446,7 @@ module GRPC
an_rpc.call.run_batch(@cq, handle_call_tag, INFINITE_FUTURE,
SEND_INITIAL_METADATA => connect_md)
return nil unless available?(an_rpc)
- return nil unless found?(an_rpc)
+ return nil unless implemented?(an_rpc)
# Create the ActiveCall
GRPC.logger.info("deadline is #{an_rpc.deadline}; (now=#{Time.now})")
diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb
index 028fea5a4c..431e8774b5 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 = '0.9.4'
+ VERSION = '0.10.0'
end
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 961c5722d3..77704fa965 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -229,6 +229,7 @@ endif
endif
INSTALL = install
RM = rm -f
+PKG_CONFIG = pkg-config
ifndef VALID_CONFIG_$(CONFIG)
$(error Invalid CONFIG value '$(CONFIG)')
@@ -345,19 +346,27 @@ HOST_LDLIBS = $(LDLIBS)
# These are automatically computed variables.
# There shouldn't be any need to change anything from now on.
-HAS_PKG_CONFIG = $(shell command -v pkg-config >/dev/null 2>&1 && echo true || echo false)
-
-PC_TEMPLATE = prefix=$(prefix)\n\
-exec_prefix=${'\$${prefix}'}\n\
-includedir=${'\$${prefix}'}/include\n\
-libdir=${'\$${exec_prefix}'}/lib\n\
-\n\
-Name: $(PC_NAME)\n\
-Description: $(PC_DESCRIPTION)\n\
-Version: $(VERSION)\n\
-Cflags: -I${'\$${includedir}'} $(PC_CFLAGS)\n\
-Requires.private: $(PC_REQUIRES_PRIVATE)\n\
-Libs: -L${'\$${libdir}'}\n\
+-include cache.mk
+
+CACHE_MK =
+
+HAS_PKG_CONFIG ?= $(shell command -v $(PKG_CONFIG) >/dev/null 2>&1 && echo true || echo false)
+
+ifeq ($(HAS_PKG_CONFIG), true)
+CACHE_MK += HAS_PKG_CONFIG = true,
+endif
+
+PC_TEMPLATE = prefix=$(prefix),\
+exec_prefix=${'\$${prefix}'},\
+includedir=${'\$${prefix}'}/include,\
+libdir=${'\$${exec_prefix}'}/lib,\
+,\
+Name: $(PC_NAME),\
+Description: $(PC_DESCRIPTION),\
+Version: $(VERSION),\
+Cflags: -I${'\$${includedir}'} $(PC_CFLAGS),\
+Requires.private: $(PC_REQUIRES_PRIVATE),\
+Libs: -L${'\$${libdir}'} $(PC_LIB),\
Libs.private: $(PC_LIBS_PRIVATE)
# gpr .pc file
@@ -366,7 +375,8 @@ PC_DESCRIPTION = gRPC Portable Runtime
PC_CFLAGS = -pthread
PC_REQUIRES_PRIVATE =
PC_LIBS_PRIVATE = -lpthread
-ifeq ($(SYSTEM),Darwin)
+PC_LIB = -lgpr
+ifneq ($(SYSTEM),Darwin)
PC_LIBS_PRIVATE += -lrt
endif
GPR_PC_FILE := $(PC_TEMPLATE)
@@ -396,10 +406,10 @@ OPENSSL_REQUIRES_DL = true
endif
ifeq ($(HAS_PKG_CONFIG),true)
-OPENSSL_ALPN_CHECK_CMD = pkg-config --atleast-version=1.0.2 openssl
-ZLIB_CHECK_CMD = pkg-config --exists zlib
-PERFTOOLS_CHECK_CMD = pkg-config --exists profiler
-PROTOBUF_CHECK_CMD = pkg-config --atleast-version=3.0.0-alpha-3 protobuf
+OPENSSL_ALPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.2 openssl
+OPENSSL_NPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.1 openssl
+ZLIB_CHECK_CMD = $(PKG_CONFIG) --exists zlib
+PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.0.0-alpha-3 protobuf
else # HAS_PKG_CONFIG
ifeq ($(SYSTEM),MINGW32)
@@ -409,16 +419,19 @@ OPENSSL_LIBS = ssl crypto
endif
OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/openssl-alpn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
+OPENSSL_NPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/openssl-npn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS)
-PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/perftools.c -lprofiler $(LDFLAGS)
PROTOBUF_CHECK_CMD = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS)
ifeq ($(OPENSSL_REQUIRES_DL),true)
OPENSSL_ALPN_CHECK_CMD += -ldl
+OPENSSL_NPN_CHECK_CMD += -ldl
endif
endif # HAS_PKG_CONFIG
+PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/perftools.c -lprofiler $(LDFLAGS)
+
PROTOC_CHECK_CMD = which protoc > /dev/null
PROTOC_CHECK_VERSION_CMD = protoc --version | grep -q libprotoc.3
DTRACE_CHECK_CMD = which dtrace > /dev/null
@@ -426,28 +439,49 @@ SYSTEMTAP_HEADERS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/buil
ZOOKEEPER_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/zookeeper.c $(LDFLAGS) -lzookeeper_mt
ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
-HAS_SYSTEM_PERFTOOLS = $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false)
+HAS_SYSTEM_PERFTOOLS ?= $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_SYSTEM_PERFTOOLS),true)
DEFINES += GRPC_HAVE_PERFTOOLS
LIBS += profiler
+CACHE_MK += HAS_SYSTEM_PERFTOOLS = true,
endif
endif
HAS_SYSTEM_PROTOBUF_VERIFY = $(shell $(PROTOBUF_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
-HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
-HAS_SYSTEM_ZLIB = $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false)
-HAS_SYSTEM_PROTOBUF = $(HAS_SYSTEM_PROTOBUF_VERIFY)
+HAS_SYSTEM_OPENSSL_ALPN ?= $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
+ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true)
+HAS_SYSTEM_OPENSSL_NPN = true
+CACHE_MK += HAS_SYSTEM_OPENSSL_ALPN = true,
+else
+HAS_SYSTEM_OPENSSL_NPN ?= $(shell $(OPENSSL_NPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
+endif
+ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
+CACHE_MK += HAS_SYSTEM_OPENSSL_NPN = true,
+endif
+HAS_SYSTEM_ZLIB ?= $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false)
+ifeq ($(HAS_SYSTEM_ZLIB),true)
+CACHE_MK += HAS_SYSTEM_ZLIB = true,
+endif
+HAS_SYSTEM_PROTOBUF ?= $(HAS_SYSTEM_PROTOBUF_VERIFY)
+ifeq ($(HAS_SYSTEM_PROTOBUF),true)
+CACHE_MK += HAS_SYSTEM_PROTOBUF = true,
+endif
else
# override system libraries if the config requires a custom compiled library
HAS_SYSTEM_OPENSSL_ALPN = false
+HAS_SYSTEM_OPENSSL_NPN = false
HAS_SYSTEM_ZLIB = false
HAS_SYSTEM_PROTOBUF = false
endif
-HAS_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false)
+HAS_PROTOC ?= $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_PROTOC),true)
-HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_VERSION_CMD) 2> /dev/null && echo true || echo false)
+CACHE_MK += HAS_PROTOC = true,
+HAS_VALID_PROTOC ?= $(shell $(PROTOC_CHECK_VERSION_CMD) 2> /dev/null && echo true || echo false)
+ifeq ($(HAS_VALID_PROTOC),true)
+CACHE_MK += HAS_VALID_PROTOC = true,
+endif
else
HAS_VALID_PROTOC = false
endif
@@ -455,6 +489,7 @@ endif
# Check for Systemtap (https://sourceware.org/systemtap/), first by making sure <sys/sdt.h> is present
# in the system and secondly by checking for the "dtrace" binary (on Linux, this is part of the Systemtap
# distribution. It's part of the base system on BSD/Solaris machines).
+ifndef HAS_SYSTEMTAP
HAS_SYSTEMTAP_HEADERS = $(shell $(SYSTEMTAP_HEADERS_CHECK_CMD) 2> /dev/null && echo true || echo false)
HAS_DTRACE = $(shell $(DTRACE_CHECK_CMD) 2> /dev/null && echo true || echo false)
HAS_SYSTEMTAP = false
@@ -463,9 +498,17 @@ ifeq ($(HAS_DTRACE),true)
HAS_SYSTEMTAP = true
endif
endif
+endif
+
+ifeq ($(HAS_SYSTEMTAP),true)
+CACHE_MK += HAS_SYSTEMTAP = true,
+endif
HAS_ZOOKEEPER = $(shell $(ZOOKEEPER_CHECK_CMD) 2> /dev/null && echo true || echo false)
+# Note that for testing purposes, one can do:
+# make HAS_EMBEDDED_OPENSSL_ALPN=false
+# to emulate the fact we do not have OpenSSL in the third_party folder.
ifeq ($(wildcard third_party/openssl/ssl/ssl.h),)
HAS_EMBEDDED_OPENSSL_ALPN = false
else
@@ -500,8 +543,8 @@ DEP_MISSING += zlib
endif
else
ifeq ($(HAS_PKG_CONFIG),true)
-CPPFLAGS += $(shell pkg-config --cflags zlib)
-LDFLAGS += $(shell pkg-config --libs-only-L zlib)
+CPPFLAGS += $(shell $(PKG_CONFIG) --cflags zlib)
+LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L zlib)
PC_REQUIRES_GRPC += zlib
else
PC_LIBS_GRPC += -lz
@@ -517,11 +560,11 @@ ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true)
ifeq ($(HAS_PKG_CONFIG),true)
OPENSSL_PKG_CONFIG = true
PC_REQUIRES_SECURE = openssl
-CPPFLAGS := $(shell pkg-config --cflags openssl) $(CPPFLAGS)
-LDFLAGS_OPENSSL_PKG_CONFIG = $(shell pkg-config --libs-only-L openssl)
+CPPFLAGS := $(shell $(PKG_CONFIG) --cflags openssl) $(CPPFLAGS)
+LDFLAGS_OPENSSL_PKG_CONFIG = $(shell $(PKG_CONFIG) --libs-only-L openssl)
ifeq ($(SYSTEM),Linux)
ifneq ($(LDFLAGS_OPENSSL_PKG_CONFIG),)
-LDFLAGS_OPENSSL_PKG_CONFIG += $(shell pkg-config --libs-only-L openssl | sed s/L/Wl,-rpath,/)
+LDFLAGS_OPENSSL_PKG_CONFIG += $(shell $(PKG_CONFIG) --libs-only-L openssl | sed s/L/Wl,-rpath,/)
endif
endif
LDFLAGS := $(LDFLAGS_OPENSSL_PKG_CONFIG) $(LDFLAGS)
@@ -534,6 +577,7 @@ endif
endif
else
ifeq ($(HAS_EMBEDDED_OPENSSL_ALPN),true)
+USE_SYSTEM_OPENSSL = false
OPENSSL_DEP = $(LIBDIR)/$(CONFIG)/openssl/libssl.a
OPENSSL_MERGE_LIBS += $(LIBDIR)/$(CONFIG)/openssl/libssl.a $(LIBDIR)/$(CONFIG)/openssl/libcrypto.a
# need to prefix these to ensure overriding system libraries
@@ -543,12 +587,21 @@ ifeq ($(OPENSSL_REQUIRES_DL),true)
LIBS_SECURE = dl
endif
else
+ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
+USE_SYSTEM_OPENSSL = true
+CPPFLAGS += -DTSI_OPENSSL_ALPN_SUPPORT=0
+LIBS_SECURE = $(OPENSSL_LIBS)
+ifeq ($(OPENSSL_REQUIRES_DL),true)
+LIBS_SECURE += dl
+endif
+else
NO_SECURE = true
endif
endif
+endif
ifeq ($(OPENSSL_PKG_CONFIG),true)
-LDLIBS_SECURE += $(shell pkg-config --libs-only-l openssl)
+LDLIBS_SECURE += $(shell $(PKG_CONFIG) --libs-only-l openssl)
else
LDLIBS_SECURE += $(addprefix -l, $(LIBS_SECURE))
endif
@@ -559,6 +612,7 @@ PC_DESCRIPTION = high performance general RPC framework
PC_CFLAGS =
PC_REQUIRES_PRIVATE = $(PC_REQUIRES_GRPC) $(PC_REQUIRES_SECURE)
PC_LIBS_PRIVATE = $(PC_LIBS_GRPC) $(PC_LIBS_SECURE)
+PC_LIB = -lgrpc
GRPC_PC_FILE := $(PC_TEMPLATE)
# gprc_unsecure .pc file
@@ -567,6 +621,7 @@ PC_DESCRIPTION = high performance general RPC framework without SSL
PC_CFLAGS =
PC_REQUIRES_PRIVATE = $(PC_REQUIRES_GRPC)
PC_LIBS_PRIVATE = $(PC_LIBS_GRPC)
+PC_LIB = -lgrpc
GRPC_UNSECURE_PC_FILE := $(PC_TEMPLATE)
# gprc_zookeeper .pc file
@@ -586,11 +641,11 @@ ifeq ($(HAS_SYSTEM_PROTOBUF),true)
ifeq ($(HAS_PKG_CONFIG),true)
PROTOBUF_PKG_CONFIG = true
PC_REQUIRES_GRPCXX = protobuf
-CPPFLAGS := $(shell pkg-config --cflags protobuf) $(CPPFLAGS)
-LDFLAGS_PROTOBUF_PKG_CONFIG = $(shell pkg-config --libs-only-L protobuf)
+CPPFLAGS := $(shell $(PKG_CONFIG) --cflags protobuf) $(CPPFLAGS)
+LDFLAGS_PROTOBUF_PKG_CONFIG = $(shell $(PKG_CONFIG) --libs-only-L protobuf)
ifeq ($(SYSTEM),Linux)
ifneq ($(LDFLAGS_PROTOBUF_PKG_CONFIG),)
-LDFLAGS_PROTOBUF_PKG_CONFIG += $(shell pkg-config --libs-only-L protobuf | sed s/L/Wl,-rpath,/)
+LDFLAGS_PROTOBUF_PKG_CONFIG += $(shell $(PKG_CONFIG) --libs-only-L protobuf | sed s/L/Wl,-rpath,/)
endif
endif
else
@@ -613,7 +668,7 @@ LIBS_PROTOC = protoc protobuf
HOST_LDLIBS_PROTOC += $(addprefix -l, $(LIBS_PROTOC))
ifeq ($(PROTOBUF_PKG_CONFIG),true)
-LDLIBS_PROTOBUF += $(shell pkg-config --libs-only-l protobuf)
+LDLIBS_PROTOBUF += $(shell $(PKG_CONFIG) --libs-only-l protobuf)
else
LDLIBS_PROTOBUF += $(addprefix -l, $(LIBS_PROTOBUF))
endif
@@ -624,6 +679,7 @@ PC_DESCRIPTION = C++ wrapper for gRPC
PC_CFLAGS =
PC_REQUIRES_PRIVATE = grpc $(PC_REQUIRES_GRPCXX)
PC_LIBS_PRIVATE = $(PC_LIBS_GRPCXX)
+PC_LIB = -lgrpc++
GRPCXX_PC_FILE := $(PC_TEMPLATE)
# grpc++_unsecure .pc file
@@ -632,6 +688,7 @@ PC_DESCRIPTION = C++ wrapper for gRPC without SSL
PC_CFLAGS =
PC_REQUIRES_PRIVATE = grpc_unsecure $(PC_REQUIRES_GRPCXX)
PC_LIBS_PRIVATE = $(PC_LIBS_GRPCXX)
+PC_LIB = -lgrpc++
GRPCXX_UNSECURE_PC_FILE := $(PC_TEMPLATE)
ifeq ($(MAKECMDGOALS),clean)
@@ -704,7 +761,7 @@ openssl_dep_message:
@echo
@echo "DEPENDENCY ERROR"
@echo
- @echo "The target you are trying to run requires OpenSSL with ALPN support."
+ @echo "The target you are trying to run requires OpenSSL."
@echo "Your system doesn't have it, and neither does the third_party directory."
@echo
@echo "Please consult INSTALL to get more information."
@@ -762,6 +819,7 @@ ${tgt.name}: $(BINDIR)/$(CONFIG)/${tgt.name}
run_dep_checks:
$(OPENSSL_ALPN_CHECK_CMD) || true
+ $(OPENSSL_NPN_CHECK_CMD) || true
$(ZLIB_CHECK_CMD) || true
$(PERFTOOLS_CHECK_CMD) || true
$(PROTOBUF_CHECK_CMD) || true
@@ -783,7 +841,7 @@ ifeq ($(SYSTEM),Darwin)
else
ifeq ($(SYSTEM),MINGW32)
@echo "We currently don't have a good way to compile OpenSSL in-place under msys."
- @echo "Please provide an ALPN-capable OpenSSL in your mingw32 system."
+ @echo "Please provide a OpenSSL in your mingw32 system."
@echo
@echo "Note that you can find a compatible version of the libraries here:"
@echo
@@ -825,7 +883,7 @@ $(LIBDIR)/$(CONFIG)/protobuf/libprotobuf.a: third_party/protobuf/configure
static: static_c static_cxx
-static_c: pc_c pc_c_unsecure pc_gpr pc_c_zookeeper\
+static_c: pc_c pc_c_unsecure cache.mk pc_gpr pc_c_zookeeper\
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c' and not lib.get('external_deps', None):
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a\
@@ -834,7 +892,7 @@ static_c: pc_c pc_c_unsecure pc_gpr pc_c_zookeeper\
static_zookeeper_libs
-static_cxx: pc_cxx pc_cxx_unsecure pc_gpr\
+static_cxx: pc_cxx pc_cxx_unsecure pc_gpr cache.mk \
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c++':
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a\
@@ -844,7 +902,7 @@ static_cxx: pc_cxx pc_cxx_unsecure pc_gpr\
shared: shared_c shared_cxx
-shared_c: pc_c pc_c_unsecure pc_gpr pc_c_zookeeper\
+shared_c: pc_c pc_c_unsecure pc_gpr cache.mk pc_c_zookeeper\
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c' and not lib.get('external_deps', None):
$(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\
@@ -852,7 +910,7 @@ shared_c: pc_c pc_c_unsecure pc_gpr pc_c_zookeeper\
% endfor
shared_zookeeper_libs
-shared_cxx: pc_cxx pc_cxx_unsecure \
+shared_cxx: pc_cxx pc_cxx_unsecure cache.mk\
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c++':
$(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\
@@ -1119,20 +1177,24 @@ ifeq ($(CONFIG),opt)
% endfor
endif
+cache.mk::
+ $(E) "[MAKE] Generating $@"
+ $(Q) echo "$(CACHE_MK)" | tr , '\n' >$@
+
$(LIBDIR)/$(CONFIG)/pkgconfig/gpr.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
- $(Q) echo -e "$(GPR_PC_FILE)" >$@
+ $(Q) echo "$(GPR_PC_FILE)" | tr , '\n' >$@
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
- $(Q) echo -e "$(GRPC_PC_FILE)" >$@
+ $(Q) echo "$(GRPC_PC_FILE)" | tr , '\n' >$@
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
- $(Q) echo -e "$(GRPC_UNSECURE_PC_FILE)" >$@
+ $(Q) echo "$(GRPC_UNSECURE_PC_FILE)" | tr , '\n' >$@
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc_zookeeper.pc:
$(E) "[MAKE] Generating $@"
@@ -1142,12 +1204,12 @@ $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_zookeeper.pc:
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
- $(Q) echo -e "$(GRPCXX_PC_FILE)" >$@
+ $(Q) echo "$(GRPCXX_PC_FILE)" | tr , '\n' >$@
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
- $(Q) echo -e "$(GRPCXX_UNSECURE_PC_FILE)" >$@
+ $(Q) echo "$(GRPCXX_UNSECURE_PC_FILE)" | tr , '\n' >$@
% for p in protos:
ifeq ($(NO_PROTOC),true)
@@ -1379,7 +1441,7 @@ endif
clean:
$(E) "[CLEAN] Cleaning build directories."
- $(Q) $(RM) -rf $(OBJDIR) $(LIBDIR) $(BINDIR) $(GENDIR)
+ $(Q) $(RM) -rf $(OBJDIR) $(LIBDIR) $(BINDIR) $(GENDIR) cache.mk
# The various libraries
@@ -1419,11 +1481,11 @@ PUBLIC_HEADERS_C += \\
LIB${lib.name.upper()}_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIB${lib.name.upper()}_SRC))))
-## If the library requires OpenSSL with ALPN, let's add some restrictions.
+## If the library requires OpenSSL, let's add some restrictions.
% if lib.get('secure', 'check') == 'yes' or lib.get('secure', 'check') == 'check':
ifeq ($(NO_SECURE),true)
-# You can't build secure libraries if you don't have OpenSSL with ALPN.
+# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a: openssl_dep_error
@@ -1566,7 +1628,7 @@ endif
% endif
% if lib.get('secure', 'check') == 'yes' or lib.get('secure', 'check') == 'check':
## If the lib was secure, we have to close the Makefile's if that tested
-## the presence of an ALPN-capable OpenSSL.
+## the presence of OpenSSL.
endif
% endif
@@ -1607,7 +1669,7 @@ ${tgt.name.upper()}_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(b
% if tgt.get('secure', 'check') == 'yes' or tgt.get('secure', 'check') == 'check':
ifeq ($(NO_SECURE),true)
-# You can't build secure targets if you don't have OpenSSL with ALPN.
+# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/${tgt.name}: openssl_dep_error
diff --git a/templates/src/core/surface/version.c.template b/templates/src/core/surface/version.c.template
new file mode 100644
index 0000000000..936341c3cf
--- /dev/null
+++ b/templates/src/core/surface/version.c.template
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* This file is autogenerated from:
+ templates/src/core/surface/version.c.template */
+
+#include <grpc/grpc.h>
+
+const char *grpc_version_string(void) {
+ return "${settings.version.major}.${settings.version.minor}.${settings.version.micro}.${settings.version.build}";
+}
diff --git a/templates/vsprojects/Grpc.mak.template b/templates/vsprojects/Grpc.mak.template
index b75537dba7..9d85376648 100644
--- a/templates/vsprojects/Grpc.mak.template
+++ b/templates/vsprojects/Grpc.mak.template
@@ -72,6 +72,12 @@ LIBS=$(OPENSSL_LIBS) $(ZLIB_LIBS) $(GENERAL_LIBS) $(WINSOCK_LIBS)
all: buildtests
+tools:
+
+tools_c:
+
+tools_cxx:
+
$(OUT_DIR):
mkdir $(OUT_DIR)
diff --git a/test/build/openssl-npn.c b/test/build/openssl-npn.c
new file mode 100644
index 0000000000..90ae8ef940
--- /dev/null
+++ b/test/build/openssl-npn.c
@@ -0,0 +1,45 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* This is just a compilation test, to see if we have a version of OpenSSL with
+ NPN support installed. It's not meant to be run, and all of the values and
+ function calls there are non-sensical. The code is only meant to test the
+ presence of symbols, and we're expecting a compilation failure otherwise. */
+
+#include <stdlib.h>
+#include <openssl/ssl.h>
+
+int main() {
+ SSL_get0_next_proto_negotiated(NULL, NULL, NULL);
+ return OPENSSL_NPN_UNSUPPORTED;
+}
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c
index 8ce666dcde..b050227b61 100644
--- a/test/core/bad_client/bad_client.c
+++ b/test/core/bad_client/bad_client.c
@@ -86,8 +86,8 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator,
gpr_slice slice =
gpr_slice_from_copied_buffer(client_payload, client_payload_length);
- hex =
- gpr_hexdump(client_payload, client_payload_length, GPR_HEXDUMP_PLAINTEXT);
+ hex = gpr_dump(client_payload, client_payload_length,
+ GPR_DUMP_HEX | GPR_DUMP_ASCII);
/* Add a debug log */
gpr_log(GPR_INFO, "TEST: %s", hex);
diff --git a/test/core/client_config/uri_parser_test.c b/test/core/client_config/uri_parser_test.c
index 776e27ae7e..4f5bb9bfd0 100644
--- a/test/core/client_config/uri_parser_test.c
+++ b/test/core/client_config/uri_parser_test.c
@@ -61,6 +61,7 @@ int main(int argc, char **argv) {
test_succeeds("http://www.google.com:90", "http", "www.google.com:90", "");
test_succeeds("a192.4-df:foo.coom", "a192.4-df", "", "foo.coom");
test_succeeds("a+b:foo.coom", "a+b", "", "foo.coom");
+ test_succeeds("zookeeper://127.0.0.1:2181/foo/bar", "zookeeper", "127.0.0.1:2181", "/foo/bar");
test_fails("xyz");
test_fails("http://www.google.com?why-are-you-using-queries");
test_fails("dns:foo.com#fragments-arent-supported-here");
diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c
index 33f7c02b61..407c72b519 100644
--- a/test/core/end2end/cq_verifier.c
+++ b/test/core/end2end/cq_verifier.c
@@ -248,7 +248,8 @@ void cq_verify(cq_verifier *v) {
}
void cq_verify_empty(cq_verifier *v) {
- gpr_timespec deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(1));
+ gpr_timespec deadline =
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(1));
grpc_event ev;
GPR_ASSERT(v->expect.next == &v->expect && "expectation queue must be empty");
diff --git a/test/core/end2end/tests/request_response_with_payload_and_call_creds.c b/test/core/end2end/tests/request_response_with_payload_and_call_creds.c
index 665ad3d2a6..b5c743b405 100644
--- a/test/core/end2end/tests/request_response_with_payload_and_call_creds.c
+++ b/test/core/end2end/tests/request_response_with_payload_and_call_creds.c
@@ -173,7 +173,7 @@ static void request_response_with_payload_and_call_creds(
size_t details_capacity = 0;
int was_cancelled = 2;
grpc_credentials *creds = NULL;
- const grpc_auth_context *s_auth_context = NULL;
+ grpc_auth_context *s_auth_context = NULL;
c = grpc_channel_create_call(f.client, f.cq, "/foo", "foo.test.google.fr",
deadline);
@@ -239,6 +239,7 @@ static void request_response_with_payload_and_call_creds(
s_auth_context = grpc_call_auth_context(s);
GPR_ASSERT(s_auth_context != NULL);
print_auth_context(0, s_auth_context);
+ grpc_auth_context_release(s_auth_context);
/* Cannot set creds on the server call object. */
GPR_ASSERT(grpc_call_set_credentials(s, NULL) != GRPC_CALL_OK);
diff --git a/test/core/fling/client.c b/test/core/fling/client.c
index ee5e390c39..6741a9dec8 100644
--- a/test/core/fling/client.c
+++ b/test/core/fling/client.c
@@ -124,7 +124,7 @@ static void step_ping_pong_stream(void) {
}
static double now(void) {
- gpr_timespec tv = gpr_now();
+ gpr_timespec tv = gpr_now(GPR_CLOCK_REALTIME);
return 1e9 * tv.tv_sec + tv.tv_nsec;
}
diff --git a/test/core/fling/server.c b/test/core/fling/server.c
index 9542e15ad0..468013c3ec 100644
--- a/test/core/fling/server.c
+++ b/test/core/fling/server.c
@@ -241,7 +241,8 @@ int main(int argc, char **argv) {
shutdown_started = 1;
}
ev = grpc_completion_queue_next(
- cq, gpr_time_add(gpr_now(), gpr_time_from_micros(1000000)));
+ cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(1000000)));
s = ev.tag;
switch (ev.type) {
case GRPC_OP_COMPLETE:
diff --git a/test/core/httpcli/httpcli_test.c b/test/core/httpcli/httpcli_test.c
index 6e579bc045..ca0b2d1519 100644
--- a/test/core/httpcli/httpcli_test.c
+++ b/test/core/httpcli/httpcli_test.c
@@ -145,7 +145,8 @@ int main(int argc, char **argv) {
gpr_free(args[0]);
gpr_free(args[2]);
- gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(5)));
+ gpr_sleep_until(
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(5)));
grpc_test_init(argc, argv);
grpc_init();
diff --git a/test/core/iomgr/alarm_list_test.c b/test/core/iomgr/alarm_list_test.c
index 684e3f579a..225c449d4b 100644
--- a/test/core/iomgr/alarm_list_test.c
+++ b/test/core/iomgr/alarm_list_test.c
@@ -51,7 +51,7 @@ static void cb(void *arg, int success) {
}
static void add_test(void) {
- gpr_timespec start = gpr_now();
+ gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME);
int i;
grpc_alarm alarms[20];
@@ -61,13 +61,13 @@ static void add_test(void) {
/* 10 ms alarms. will expire in the current epoch */
for (i = 0; i < 10; i++) {
grpc_alarm_init(&alarms[i], gpr_time_add(start, gpr_time_from_millis(10)),
- cb, (void *)(gpr_intptr) i, start);
+ cb, (void *)(gpr_intptr)i, start);
}
/* 1010 ms alarms. will expire in the next epoch */
for (i = 10; i < 20; i++) {
grpc_alarm_init(&alarms[i], gpr_time_add(start, gpr_time_from_millis(1010)),
- cb, (void *)(gpr_intptr) i, start);
+ cb, (void *)(gpr_intptr)i, start);
}
/* collect alarms. Only the first batch should be ready. */
@@ -115,15 +115,15 @@ void destruction_test(void) {
memset(cb_called, 0, sizeof(cb_called));
grpc_alarm_init(&alarms[0], gpr_time_from_millis(100), cb,
- (void *)(gpr_intptr) 0, gpr_time_0);
+ (void *)(gpr_intptr)0, gpr_time_0);
grpc_alarm_init(&alarms[1], gpr_time_from_millis(3), cb,
- (void *)(gpr_intptr) 1, gpr_time_0);
+ (void *)(gpr_intptr)1, gpr_time_0);
grpc_alarm_init(&alarms[2], gpr_time_from_millis(100), cb,
- (void *)(gpr_intptr) 2, gpr_time_0);
+ (void *)(gpr_intptr)2, gpr_time_0);
grpc_alarm_init(&alarms[3], gpr_time_from_millis(3), cb,
- (void *)(gpr_intptr) 3, gpr_time_0);
+ (void *)(gpr_intptr)3, gpr_time_0);
grpc_alarm_init(&alarms[4], gpr_time_from_millis(1), cb,
- (void *)(gpr_intptr) 4, gpr_time_0);
+ (void *)(gpr_intptr)4, gpr_time_0);
GPR_ASSERT(1 == grpc_alarm_check(NULL, gpr_time_from_millis(2), NULL));
GPR_ASSERT(1 == cb_called[4][1]);
grpc_alarm_cancel(&alarms[0]);
diff --git a/test/core/iomgr/alarm_test.c b/test/core/iomgr/alarm_test.c
index 0ccec435e6..362eb5fe63 100644
--- a/test/core/iomgr/alarm_test.c
+++ b/test/core/iomgr/alarm_test.c
@@ -113,7 +113,7 @@ static void test_grpc_alarm(void) {
gpr_event_init(&arg.fcb_arg);
grpc_alarm_init(&alarm, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100), alarm_cb, &arg,
- gpr_now());
+ gpr_now(GPR_CLOCK_REALTIME));
alarm_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1);
gpr_mu_lock(&arg.mu);
@@ -165,7 +165,7 @@ static void test_grpc_alarm(void) {
gpr_event_init(&arg2.fcb_arg);
grpc_alarm_init(&alarm_to_cancel, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100),
- alarm_cb, &arg2, gpr_now());
+ alarm_cb, &arg2, gpr_now(GPR_CLOCK_REALTIME));
grpc_alarm_cancel(&alarm_to_cancel);
alarm_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1);
diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c
index 8198c24752..0cfba5fac8 100644
--- a/test/core/iomgr/endpoint_tests.c
+++ b/test/core/iomgr/endpoint_tests.c
@@ -254,7 +254,7 @@ static void read_and_write_test(grpc_endpoint_test_config config,
gpr_mu_lock(GRPC_POLLSET_MU(g_pollset));
while (!state.read_done || !state.write_done) {
- GPR_ASSERT(gpr_time_cmp(gpr_now(), deadline) < 0);
+ GPR_ASSERT(gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
grpc_pollset_work(g_pollset, deadline);
}
gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset));
@@ -350,14 +350,14 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config,
deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
gpr_mu_lock(GRPC_POLLSET_MU(g_pollset));
while (!write_st.done) {
- GPR_ASSERT(gpr_time_cmp(gpr_now(), deadline) < 0);
+ GPR_ASSERT(gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
grpc_pollset_work(g_pollset, deadline);
}
gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset));
grpc_endpoint_destroy(write_st.ep);
gpr_mu_lock(GRPC_POLLSET_MU(g_pollset));
while (!read_st.done) {
- GPR_ASSERT(gpr_time_cmp(gpr_now(), deadline) < 0);
+ GPR_ASSERT(gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
grpc_pollset_work(g_pollset, deadline);
}
gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset));
diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c
index b673c032b2..710cd725df 100644
--- a/test/core/iomgr/tcp_client_posix_test.c
+++ b/test/core/iomgr/tcp_client_posix_test.c
@@ -187,11 +187,12 @@ void test_times_out(void) {
/* Make sure the event doesn't trigger early */
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
while (gpr_time_cmp(gpr_time_add(connect_deadline, gpr_time_from_seconds(2)),
- gpr_now()) > 0) {
- int is_after_deadline = gpr_time_cmp(connect_deadline, gpr_now()) <= 0;
+ gpr_now(GPR_CLOCK_REALTIME)) > 0) {
+ int is_after_deadline =
+ gpr_time_cmp(connect_deadline, gpr_now(GPR_CLOCK_REALTIME)) <= 0;
if (is_after_deadline &&
gpr_time_cmp(gpr_time_add(connect_deadline, gpr_time_from_seconds(1)),
- gpr_now()) > 0) {
+ gpr_now(GPR_CLOCK_REALTIME)) > 0) {
/* allow some slack before insisting that things be done */
} else {
GPR_ASSERT(g_connections_complete ==
diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c
index fb262711c0..83252a889b 100644
--- a/test/core/iomgr/tcp_server_posix_test.c
+++ b/test/core/iomgr/tcp_server_posix_test.c
@@ -125,7 +125,7 @@ static void test_connect(int n) {
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
for (i = 0; i < n; i++) {
- deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(4000);
+ deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
nconnects_before = g_nconnects;
clifd = socket(addr.ss_family, SOCK_STREAM, 0);
@@ -135,7 +135,7 @@ static void test_connect(int n) {
gpr_log(GPR_DEBUG, "wait");
while (g_nconnects == nconnects_before &&
- gpr_time_cmp(deadline, gpr_now()) > 0) {
+ gpr_time_cmp(deadline, gpr_now(GPR_CLOCK_REALTIME)) > 0) {
grpc_pollset_work(&g_pollset, deadline);
}
gpr_log(GPR_DEBUG, "wait done");
diff --git a/test/core/network_benchmarks/low_level_ping_pong.c b/test/core/network_benchmarks/low_level_ping_pong.c
index 78a0eef1a2..0ce4bd4b25 100644
--- a/test/core/network_benchmarks/low_level_ping_pong.c
+++ b/test/core/network_benchmarks/low_level_ping_pong.c
@@ -296,7 +296,7 @@ static void print_histogram(gpr_histogram *histogram) {
}
static double now(void) {
- gpr_timespec tv = gpr_now();
+ gpr_timespec tv = gpr_now(GPR_CLOCK_REALTIME);
return 1e9 * tv.tv_sec + tv.tv_nsec;
}
diff --git a/test/core/security/auth_context_test.c b/test/core/security/auth_context_test.c
index 2b12551a06..a30505a63b 100644
--- a/test/core/security/auth_context_test.c
+++ b/test/core/security/auth_context_test.c
@@ -31,7 +31,7 @@
*
*/
-#include<string.h>
+#include <string.h>
#include "src/core/security/security_context.h"
#include "src/core/support/string.h"
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 4253be6b07..d3fea9680a 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -37,12 +37,17 @@
#include "src/core/httpcli/httpcli.h"
#include "src/core/security/json_token.h"
+#include "src/core/support/env.h"
+#include "src/core/support/file.h"
#include "src/core/support/string.h"
+
+#include "test/core/util/test_config.h"
+
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
-#include "test/core/util/test_config.h"
+
#include <openssl/rsa.h>
static const char test_iam_authorization_token[] = "blahblahblhahb";
@@ -331,6 +336,27 @@ static void test_iam_creds(void) {
check_iam_metadata, creds);
}
+static void check_access_token_metadata(void *user_data,
+ grpc_credentials_md *md_elems,
+ size_t num_md,
+ grpc_credentials_status status) {
+ grpc_credentials *c = (grpc_credentials *)user_data;
+ expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}};
+ GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
+ GPR_ASSERT(num_md == 1);
+ check_metadata(emd, md_elems, num_md);
+ grpc_credentials_unref(c);
+}
+
+static void test_access_token_creds(void) {
+ grpc_credentials *creds = grpc_access_token_credentials_create("blah");
+ GPR_ASSERT(grpc_credentials_has_request_metadata(creds));
+ GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds));
+ GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_OAUTH2) == 0);
+ grpc_credentials_get_request_metadata(creds, NULL, test_service_url,
+ check_access_token_metadata, creds);
+}
+
static void check_ssl_oauth2_composite_metadata(
void *user_data, grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) {
@@ -847,6 +873,68 @@ static void test_jwt_creds_signing_failure(void) {
grpc_jwt_encode_and_sign_set_override(NULL);
}
+static void set_google_default_creds_env_var_with_file_contents(
+ const char *file_prefix, const char *contents) {
+ size_t contents_len = strlen(contents);
+ char *creds_file_name;
+ FILE *creds_file = gpr_tmpfile(file_prefix, &creds_file_name);
+ GPR_ASSERT(creds_file_name != NULL);
+ GPR_ASSERT(creds_file != NULL);
+ GPR_ASSERT(fwrite(contents, 1, contents_len, creds_file) == contents_len);
+ fclose(creds_file);
+ gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, creds_file_name);
+ gpr_free(creds_file_name);
+}
+
+static grpc_credentials *composite_inner_creds(grpc_credentials *creds,
+ const char *inner_creds_type) {
+ size_t i;
+ grpc_composite_credentials *composite;
+ GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0);
+ composite = (grpc_composite_credentials *)creds;
+ for (i = 0; i < composite->inner.num_creds; i++) {
+ grpc_credentials *c = composite->inner.creds_array[i];
+ if (strcmp(c->type, inner_creds_type) == 0) return c;
+ }
+ GPR_ASSERT(0); /* Not found. */
+}
+
+static void test_google_default_creds_auth_key(void) {
+ grpc_jwt_credentials *jwt;
+ grpc_credentials *creds;
+ char *json_key = test_json_key_str();
+ grpc_flush_cached_google_default_credentials();
+ set_google_default_creds_env_var_with_file_contents(
+ "json_key_google_default_creds", json_key);
+ gpr_free(json_key);
+ creds = grpc_google_default_credentials_create();
+ GPR_ASSERT(creds != NULL);
+ jwt = (grpc_jwt_credentials *)composite_inner_creds(
+ creds, GRPC_CREDENTIALS_TYPE_JWT);
+ GPR_ASSERT(
+ strcmp(jwt->key.client_id,
+ "777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") ==
+ 0);
+ grpc_credentials_unref(creds);
+ gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
+}
+
+static void test_google_default_creds_access_token(void) {
+ grpc_refresh_token_credentials *refresh;
+ grpc_credentials *creds;
+ grpc_flush_cached_google_default_credentials();
+ set_google_default_creds_env_var_with_file_contents(
+ "refresh_token_google_default_creds", test_refresh_token_str);
+ creds = grpc_google_default_credentials_create();
+ GPR_ASSERT(creds != NULL);
+ refresh = (grpc_refresh_token_credentials *)composite_inner_creds(
+ creds, GRPC_CREDENTIALS_TYPE_OAUTH2);
+ GPR_ASSERT(strcmp(refresh->refresh_token.client_id,
+ "32555999999.apps.googleusercontent.com") == 0);
+ grpc_credentials_unref(creds);
+ gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
+}
+
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_empty_md_store();
@@ -863,6 +951,7 @@ int main(int argc, char **argv) {
test_oauth2_token_fetcher_creds_parsing_missing_token_type();
test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime();
test_iam_creds();
+ test_access_token_creds();
test_ssl_oauth2_composite_creds();
test_ssl_oauth2_iam_composite_creds();
test_compute_engine_creds_success();
@@ -874,5 +963,7 @@ int main(int argc, char **argv) {
test_service_account_creds_signing_failure();
test_jwt_creds_success();
test_jwt_creds_signing_failure();
+ test_google_default_creds_auth_key();
+ test_google_default_creds_access_token();
return 0;
}
diff --git a/test/core/security/jwt_verifier_test.c b/test/core/security/jwt_verifier_test.c
new file mode 100644
index 0000000000..46b96d9ecb
--- /dev/null
+++ b/test/core/security/jwt_verifier_test.c
@@ -0,0 +1,565 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/core/security/jwt_verifier.h"
+
+#include <string.h>
+
+#include "src/core/httpcli/httpcli.h"
+#include "src/core/security/base64.h"
+#include "src/core/security/json_token.h"
+#include "test/core/util/test_config.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/string_util.h>
+
+/* This JSON key was generated with the GCE console and revoked immediately.
+ The identifiers have been changed as well.
+ Maximum size for a string literal is 509 chars in C89, yay! */
+static const char json_key_str_part1[] =
+ "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----"
+ "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE"
+ "qg"
+ "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/"
+ "rWBQvS4hle4LfijkP3J5BG+"
+ "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+"
+ "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/"
+ "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/"
+ "8HpCqFYM9V8f34SBWfD4fRFT+n/"
+ "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+";
+static const char json_key_str_part2[] =
+ "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+"
+ "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/"
+ "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA"
+ "G"
+ "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz"
+ "A"
+ "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+"
+ "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/"
+ "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ"
+ "Y"
+ "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", ";
+static const char json_key_str_part3_for_google_email_issuer[] =
+ "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
+ "\"client_email\": "
+ "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount."
+ "com\", \"client_id\": "
+ "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
+ "com\", \"type\": \"service_account\" }";
+/* Trick our JWT library into issuing a JWT with iss=accounts.google.com. */
+static const char json_key_str_part3_for_url_issuer[] =
+ "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
+ "\"client_email\": \"accounts.google.com\", "
+ "\"client_id\": "
+ "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
+ "com\", \"type\": \"service_account\" }";
+static const char json_key_str_part3_for_custom_email_issuer[] =
+ "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
+ "\"client_email\": "
+ "\"foo@bar.com\", \"client_id\": "
+ "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
+ "com\", \"type\": \"service_account\" }";
+
+static grpc_jwt_verifier_email_domain_key_url_mapping custom_mapping = {
+ "bar.com", "keys.bar.com/jwk"
+};
+
+static const char expected_user_data[] = "user data";
+
+static const char good_jwk_set[] =
+ "{"
+ " \"keys\": ["
+ " {"
+ " \"kty\": \"RSA\","
+ " \"alg\": \"RS256\","
+ " \"use\": \"sig\","
+ " \"kid\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\","
+ " \"n\": "
+ "\"4S8myegefIeRdynuYkSqBYaOLDvU19cHKC56RIqGjrkXFoZuydIz1IxACpWTtDasb4jQ6mxP"
+ "QutZC1nKNJ6D-tYFC9LiGV7gt-KOQ_cnkEb4hcMw_xF_OI1FCx6cBcM0-"
+ "RjiQkK8q7HbF0M6dUXo3t0vedNhmD65Cs2wxPP1TFU=\","
+ " \"e\": \"AQAB\""
+ " }"
+ " ]"
+ "}";
+
+static gpr_timespec expected_lifetime = {3600, 0};
+
+static const char good_google_email_keys_part1[] =
+ "{\"e6b5137873db8d2ef81e06a47289e6434ec8a165\": \"-----BEGIN "
+ "CERTIFICATE-----"
+ "\\nMIICATCCAWoCCQDEywLhxvHjnDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB\\nVTET"
+ "MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0\\ncyBQdHkgTHR"
+ "kMB4XDTE1MDYyOTA4Mzk1MFoXDTI1MDYyNjA4Mzk1MFowRTELMAkG\\nA1UEBhMCQVUxEzARBg"
+ "NVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0\\nIFdpZGdpdHMgUHR5IEx0ZDCBn"
+ "zANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4S8m\\nyegefIeRdynuYkSqBYaOLDvU19cHKC56"
+ "RIqGjrkXFoZuydIz1IxACpWTtDasb4jQ\\n6mxPQutZC1nKNJ6D+tYFC9LiGV7gt+KOQ/";
+
+static const char good_google_email_keys_part2[] =
+ "cnkEb4hcMw/xF/OI1FCx6cBcM0+"
+ "Rji\\nQkK8q7HbF0M6dUXo3t0vedNhmD65Cs2wxPP1TFUCAwEAATANBgkqhkiG9w0BAQsF\\nA"
+ "AOBgQBfu69FkPmBknbKNFgurPz78kbs3VNN+k/"
+ "PUgO5DHKskJmgK2TbtvX2VMpx\\nkftmHGzgzMzUlOtigCaGMgHWjfqjpP9uuDbahXrZBJzB8c"
+ "Oq7MrQF8r17qVvo3Ue\\nPjTKQMAsU8uxTEMmeuz9L6yExs0rfd6bPOrQkAoVfFfiYB3/"
+ "pA==\\n-----END CERTIFICATE-----\\n\"}";
+
+static const char expected_audience[] = "https://foo.com";
+
+static const char good_openid_config[] =
+ "{"
+ " \"issuer\": \"https://accounts.google.com\","
+ " \"authorization_endpoint\": "
+ "\"https://accounts.google.com/o/oauth2/v2/auth\","
+ " \"token_endpoint\": \"https://www.googleapis.com/oauth2/v4/token\","
+ " \"userinfo_endpoint\": \"https://www.googleapis.com/oauth2/v3/userinfo\","
+ " \"revocation_endpoint\": \"https://accounts.google.com/o/oauth2/revoke\","
+ " \"jwks_uri\": \"https://www.googleapis.com/oauth2/v3/certs\""
+ "}";
+
+static const char expired_claims[] =
+ "{ \"aud\": \"https://foo.com\","
+ " \"iss\": \"blah.foo.com\","
+ " \"sub\": \"juju@blah.foo.com\","
+ " \"jti\": \"jwtuniqueid\","
+ " \"iat\": 100," /* Way back in the past... */
+ " \"exp\": 120,"
+ " \"nbf\": 60,"
+ " \"foo\": \"bar\"}";
+
+static const char claims_without_time_constraint[] =
+ "{ \"aud\": \"https://foo.com\","
+ " \"iss\": \"blah.foo.com\","
+ " \"sub\": \"juju@blah.foo.com\","
+ " \"jti\": \"jwtuniqueid\","
+ " \"foo\": \"bar\"}";
+
+static const char invalid_claims[] =
+ "{ \"aud\": \"https://foo.com\","
+ " \"iss\": 46," /* Issuer cannot be a number. */
+ " \"sub\": \"juju@blah.foo.com\","
+ " \"jti\": \"jwtuniqueid\","
+ " \"foo\": \"bar\"}";
+
+typedef struct {
+ grpc_jwt_verifier_status expected_status;
+ const char *expected_issuer;
+ const char *expected_subject;
+} verifier_test_config;
+
+static void test_claims_success(void) {
+ grpc_jwt_claims *claims;
+ gpr_slice s = gpr_slice_from_copied_string(claims_without_time_constraint);
+ grpc_json *json = grpc_json_parse_string_with_len(
+ (char *)GPR_SLICE_START_PTR(s), GPR_SLICE_LENGTH(s));
+ GPR_ASSERT(json != NULL);
+ claims = grpc_jwt_claims_from_json(json, s);
+ GPR_ASSERT(claims != NULL);
+ GPR_ASSERT(grpc_jwt_claims_json(claims) == json);
+ GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), "https://foo.com") == 0);
+ GPR_ASSERT(strcmp(grpc_jwt_claims_issuer(claims), "blah.foo.com") == 0);
+ GPR_ASSERT(strcmp(grpc_jwt_claims_subject(claims), "juju@blah.foo.com") == 0);
+ GPR_ASSERT(strcmp(grpc_jwt_claims_id(claims), "jwtuniqueid") == 0);
+ GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") ==
+ GRPC_JWT_VERIFIER_OK);
+ grpc_jwt_claims_destroy(claims);
+}
+
+static void test_expired_claims_failure(void) {
+ grpc_jwt_claims *claims;
+ gpr_slice s = gpr_slice_from_copied_string(expired_claims);
+ grpc_json *json = grpc_json_parse_string_with_len(
+ (char *)GPR_SLICE_START_PTR(s), GPR_SLICE_LENGTH(s));
+ gpr_timespec exp_iat = {100, 0};
+ gpr_timespec exp_exp = {120, 0};
+ gpr_timespec exp_nbf = {60, 0};
+ GPR_ASSERT(json != NULL);
+ claims = grpc_jwt_claims_from_json(json, s);
+ GPR_ASSERT(claims != NULL);
+ GPR_ASSERT(grpc_jwt_claims_json(claims) == json);
+ GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), "https://foo.com") == 0);
+ GPR_ASSERT(strcmp(grpc_jwt_claims_issuer(claims), "blah.foo.com") == 0);
+ GPR_ASSERT(strcmp(grpc_jwt_claims_subject(claims), "juju@blah.foo.com") == 0);
+ GPR_ASSERT(strcmp(grpc_jwt_claims_id(claims), "jwtuniqueid") == 0);
+ GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_issued_at(claims), exp_iat) == 0);
+ GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_expires_at(claims), exp_exp) == 0);
+ GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_not_before(claims), exp_nbf) == 0);
+
+ GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") ==
+ GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE);
+ grpc_jwt_claims_destroy(claims);
+}
+
+static void test_invalid_claims_failure(void) {
+ gpr_slice s = gpr_slice_from_copied_string(invalid_claims);
+ grpc_json *json = grpc_json_parse_string_with_len(
+ (char *)GPR_SLICE_START_PTR(s), GPR_SLICE_LENGTH(s));
+ GPR_ASSERT(grpc_jwt_claims_from_json(json, s) == NULL);
+}
+
+static void test_bad_audience_claims_failure(void) {
+ grpc_jwt_claims *claims;
+ gpr_slice s = gpr_slice_from_copied_string(claims_without_time_constraint);
+ grpc_json *json = grpc_json_parse_string_with_len(
+ (char *)GPR_SLICE_START_PTR(s), GPR_SLICE_LENGTH(s));
+ GPR_ASSERT(json != NULL);
+ claims = grpc_jwt_claims_from_json(json, s);
+ GPR_ASSERT(claims != NULL);
+ GPR_ASSERT(grpc_jwt_claims_check(claims, "https://bar.com") ==
+ GRPC_JWT_VERIFIER_BAD_AUDIENCE);
+ grpc_jwt_claims_destroy(claims);
+}
+
+static char *json_key_str(const char *last_part) {
+ size_t result_len = strlen(json_key_str_part1) + strlen(json_key_str_part2) +
+ strlen(last_part);
+ char *result = gpr_malloc(result_len + 1);
+ char *current = result;
+ strcpy(result, json_key_str_part1);
+ current += strlen(json_key_str_part1);
+ strcpy(current, json_key_str_part2);
+ current += strlen(json_key_str_part2);
+ strcpy(current, last_part);
+ return result;
+}
+
+static char *good_google_email_keys(void) {
+ size_t result_len = strlen(good_google_email_keys_part1) +
+ strlen(good_google_email_keys_part2);
+ char *result = gpr_malloc(result_len + 1);
+ char *current = result;
+ strcpy(result, good_google_email_keys_part1);
+ current += strlen(good_google_email_keys_part1);
+ strcpy(current, good_google_email_keys_part2);
+ return result;
+}
+
+static grpc_httpcli_response http_response(int status, char *body) {
+ grpc_httpcli_response response;
+ memset(&response, 0, sizeof(grpc_httpcli_response));
+ response.status = status;
+ response.body = body;
+ response.body_length = strlen(body);
+ return response;
+}
+
+static int httpcli_post_should_not_be_called(
+ const grpc_httpcli_request *request, const char *body_bytes,
+ size_t body_size, gpr_timespec deadline,
+ grpc_httpcli_response_cb on_response, void *user_data) {
+ GPR_ASSERT("HTTP POST should not be called" == NULL);
+ return 1;
+}
+
+static int httpcli_get_google_keys_for_email(
+ const grpc_httpcli_request *request, gpr_timespec deadline,
+ grpc_httpcli_response_cb on_response, void *user_data) {
+ grpc_httpcli_response response = http_response(200, good_google_email_keys());
+ GPR_ASSERT(request->use_ssl);
+ GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
+ GPR_ASSERT(strcmp(request->path,
+ "/robot/v1/metadata/x509/"
+ "777-abaslkan11hlb6nmim3bpspl31ud@developer."
+ "gserviceaccount.com") == 0);
+ on_response(user_data, &response);
+ gpr_free(response.body);
+ return 1;
+}
+
+static void on_verification_success(void *user_data,
+ grpc_jwt_verifier_status status,
+ grpc_jwt_claims *claims) {
+ GPR_ASSERT(status == GRPC_JWT_VERIFIER_OK);
+ GPR_ASSERT(claims != NULL);
+ GPR_ASSERT(user_data == (void *)expected_user_data);
+ GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), expected_audience) == 0);
+ grpc_jwt_claims_destroy(claims);
+}
+
+static void test_jwt_verifier_google_email_issuer_success(void) {
+ grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
+ char *jwt = NULL;
+ char *key_str = json_key_str(json_key_str_part3_for_google_email_issuer);
+ grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
+ gpr_free(key_str);
+ GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
+ grpc_httpcli_set_override(httpcli_get_google_keys_for_email,
+ httpcli_post_should_not_be_called);
+ jwt =
+ grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, NULL);
+ grpc_auth_json_key_destruct(&key);
+ GPR_ASSERT(jwt != NULL);
+ grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
+ on_verification_success, (void *)expected_user_data);
+ gpr_free(jwt);
+ grpc_jwt_verifier_destroy(verifier);
+ grpc_httpcli_set_override(NULL, NULL);
+}
+
+static int httpcli_get_custom_keys_for_email(
+ const grpc_httpcli_request *request, gpr_timespec deadline,
+ grpc_httpcli_response_cb on_response, void *user_data) {
+ grpc_httpcli_response response = http_response(200, gpr_strdup(good_jwk_set));
+ GPR_ASSERT(request->use_ssl);
+ GPR_ASSERT(strcmp(request->host, "keys.bar.com") == 0);
+ GPR_ASSERT(strcmp(request->path, "/jwk/foo@bar.com") == 0);
+ on_response(user_data, &response);
+ gpr_free(response.body);
+ return 1;
+}
+
+static void test_jwt_verifier_custom_email_issuer_success(void) {
+ grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(&custom_mapping, 1);
+ char *jwt = NULL;
+ char *key_str = json_key_str(json_key_str_part3_for_custom_email_issuer);
+ grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
+ gpr_free(key_str);
+ GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
+ grpc_httpcli_set_override(httpcli_get_custom_keys_for_email,
+ httpcli_post_should_not_be_called);
+ jwt =
+ grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, NULL);
+ grpc_auth_json_key_destruct(&key);
+ GPR_ASSERT(jwt != NULL);
+ grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
+ on_verification_success, (void *)expected_user_data);
+ gpr_free(jwt);
+ grpc_jwt_verifier_destroy(verifier);
+ grpc_httpcli_set_override(NULL, NULL);
+}
+
+static int httpcli_get_jwk_set(
+ const grpc_httpcli_request *request, gpr_timespec deadline,
+ grpc_httpcli_response_cb on_response, void *user_data) {
+ grpc_httpcli_response response = http_response(200, gpr_strdup(good_jwk_set));
+ GPR_ASSERT(request->use_ssl);
+ GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
+ GPR_ASSERT(strcmp(request->path, "/oauth2/v3/certs") == 0);
+ on_response(user_data, &response);
+ gpr_free(response.body);
+ return 1;
+}
+
+static int httpcli_get_openid_config(const grpc_httpcli_request *request,
+ gpr_timespec deadline,
+ grpc_httpcli_response_cb on_response,
+ void *user_data) {
+ grpc_httpcli_response response =
+ http_response(200, gpr_strdup(good_openid_config));
+ GPR_ASSERT(request->use_ssl);
+ GPR_ASSERT(strcmp(request->host, "accounts.google.com") == 0);
+ GPR_ASSERT(strcmp(request->path, GRPC_OPENID_CONFIG_URL_SUFFIX) == 0);
+ grpc_httpcli_set_override(httpcli_get_jwk_set,
+ httpcli_post_should_not_be_called);
+ on_response(user_data, &response);
+ gpr_free(response.body);
+ return 1;
+}
+
+static void test_jwt_verifier_url_issuer_success(void) {
+ grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
+ char *jwt = NULL;
+ char *key_str = json_key_str(json_key_str_part3_for_url_issuer);
+ grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
+ gpr_free(key_str);
+ GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
+ grpc_httpcli_set_override(httpcli_get_openid_config,
+ httpcli_post_should_not_be_called);
+ jwt =
+ grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, NULL);
+ grpc_auth_json_key_destruct(&key);
+ GPR_ASSERT(jwt != NULL);
+ grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
+ on_verification_success, (void *)expected_user_data);
+ gpr_free(jwt);
+ grpc_jwt_verifier_destroy(verifier);
+ grpc_httpcli_set_override(NULL, NULL);
+}
+
+static void on_verification_key_retrieval_error(void *user_data,
+ grpc_jwt_verifier_status status,
+ grpc_jwt_claims *claims) {
+ GPR_ASSERT(status == GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR);
+ GPR_ASSERT(claims == NULL);
+ GPR_ASSERT(user_data == (void *)expected_user_data);
+}
+
+static int httpcli_get_bad_json(const grpc_httpcli_request *request,
+ gpr_timespec deadline,
+ grpc_httpcli_response_cb on_response,
+ void *user_data) {
+ grpc_httpcli_response response =
+ http_response(200, gpr_strdup("{\"bad\": \"stuff\"}"));
+ GPR_ASSERT(request->use_ssl);
+ on_response(user_data, &response);
+ gpr_free(response.body);
+ return 1;
+}
+
+static void test_jwt_verifier_url_issuer_bad_config(void) {
+ grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
+ char *jwt = NULL;
+ char *key_str = json_key_str(json_key_str_part3_for_url_issuer);
+ grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
+ gpr_free(key_str);
+ GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
+ grpc_httpcli_set_override(httpcli_get_bad_json,
+ httpcli_post_should_not_be_called);
+ jwt =
+ grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, NULL);
+ grpc_auth_json_key_destruct(&key);
+ GPR_ASSERT(jwt != NULL);
+ grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
+ on_verification_key_retrieval_error,
+ (void *)expected_user_data);
+ gpr_free(jwt);
+ grpc_jwt_verifier_destroy(verifier);
+ grpc_httpcli_set_override(NULL, NULL);
+}
+
+static void test_jwt_verifier_bad_json_key(void) {
+ grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
+ char *jwt = NULL;
+ char *key_str = json_key_str(json_key_str_part3_for_google_email_issuer);
+ grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
+ gpr_free(key_str);
+ GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
+ grpc_httpcli_set_override(httpcli_get_bad_json,
+ httpcli_post_should_not_be_called);
+ jwt =
+ grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, NULL);
+ grpc_auth_json_key_destruct(&key);
+ GPR_ASSERT(jwt != NULL);
+ grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
+ on_verification_key_retrieval_error,
+ (void *)expected_user_data);
+ gpr_free(jwt);
+ grpc_jwt_verifier_destroy(verifier);
+ grpc_httpcli_set_override(NULL, NULL);
+}
+
+static void corrupt_jwt_sig(char *jwt) {
+ gpr_slice sig;
+ char *bad_b64_sig;
+ gpr_uint8 *sig_bytes;
+ char *last_dot = strrchr(jwt, '.');
+ GPR_ASSERT(last_dot != NULL);
+ sig = grpc_base64_decode(last_dot + 1, 1);
+ GPR_ASSERT(!GPR_SLICE_IS_EMPTY(sig));
+ sig_bytes = GPR_SLICE_START_PTR(sig);
+ (*sig_bytes)++; /* Corrupt first byte. */
+ bad_b64_sig =
+ grpc_base64_encode(GPR_SLICE_START_PTR(sig), GPR_SLICE_LENGTH(sig), 1, 0);
+ memcpy(last_dot + 1, bad_b64_sig, strlen(bad_b64_sig));
+ gpr_free(bad_b64_sig);
+ gpr_slice_unref(sig);
+}
+
+static void on_verification_bad_signature(void *user_data,
+ grpc_jwt_verifier_status status,
+ grpc_jwt_claims *claims) {
+ GPR_ASSERT(status == GRPC_JWT_VERIFIER_BAD_SIGNATURE);
+ GPR_ASSERT(claims == NULL);
+ GPR_ASSERT(user_data == (void *)expected_user_data);
+}
+
+static void test_jwt_verifier_bad_signature(void) {
+ grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
+ char *jwt = NULL;
+ char *key_str = json_key_str(json_key_str_part3_for_url_issuer);
+ grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
+ gpr_free(key_str);
+ GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
+ grpc_httpcli_set_override(httpcli_get_openid_config,
+ httpcli_post_should_not_be_called);
+ jwt =
+ grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, NULL);
+ grpc_auth_json_key_destruct(&key);
+ corrupt_jwt_sig(jwt);
+ GPR_ASSERT(jwt != NULL);
+ grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
+ on_verification_bad_signature,
+ (void *)expected_user_data);
+ gpr_free(jwt);
+ grpc_jwt_verifier_destroy(verifier);
+ grpc_httpcli_set_override(NULL, NULL);
+}
+
+static int httpcli_get_should_not_be_called(
+ const grpc_httpcli_request *request, gpr_timespec deadline,
+ grpc_httpcli_response_cb on_response, void *user_data) {
+ GPR_ASSERT(0);
+ return 1;
+}
+
+static void on_verification_bad_format(void *user_data,
+ grpc_jwt_verifier_status status,
+ grpc_jwt_claims *claims) {
+ GPR_ASSERT(status == GRPC_JWT_VERIFIER_BAD_FORMAT);
+ GPR_ASSERT(claims == NULL);
+ GPR_ASSERT(user_data == (void *)expected_user_data);
+}
+
+static void test_jwt_verifier_bad_format(void) {
+ grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
+ grpc_httpcli_set_override(httpcli_get_should_not_be_called,
+ httpcli_post_should_not_be_called);
+ grpc_jwt_verifier_verify(verifier, NULL, "bad jwt", expected_audience,
+ on_verification_bad_format,
+ (void *)expected_user_data);
+ grpc_jwt_verifier_destroy(verifier);
+ grpc_httpcli_set_override(NULL, NULL);
+}
+
+/* find verification key: bad jks, cannot find key in jks */
+/* bad signature custom provided email*/
+/* bad key */
+
+
+int main(int argc, char **argv) {
+ grpc_test_init(argc, argv);
+ test_claims_success();
+ test_expired_claims_failure();
+ test_invalid_claims_failure();
+ test_bad_audience_claims_failure();
+ test_jwt_verifier_google_email_issuer_success();
+ test_jwt_verifier_custom_email_issuer_success();
+ test_jwt_verifier_url_issuer_success();
+ test_jwt_verifier_url_issuer_bad_config();
+ test_jwt_verifier_bad_json_key();
+ test_jwt_verifier_bad_signature();
+ test_jwt_verifier_bad_format();
+ return 0;
+}
+
diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c
index a0da5b2d93..5b55a4da13 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -35,6 +35,7 @@
#include <string.h>
#include "src/core/security/credentials.h"
+#include "src/core/support/string.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
@@ -56,9 +57,11 @@ static void on_metadata_response(void *user_data,
if (status == GRPC_CREDENTIALS_ERROR) {
fprintf(stderr, "Fetching token failed.\n");
} else {
+ char *token;
GPR_ASSERT(num_md == 1);
- printf("\nGot token: %s\n\n",
- (const char *)GPR_SLICE_START_PTR(md_elems[0].value));
+ token = gpr_dump_slice(md_elems[0].value, GPR_DUMP_ASCII);
+ printf("\nGot token: %s\n\n", token);
+ gpr_free(token);
}
gpr_mu_lock(GRPC_POLLSET_MU(&sync->pollset));
sync->is_done = 1;
@@ -88,13 +91,13 @@ int main(int argc, char **argv) {
grpc_pollset_init(&sync.pollset);
sync.is_done = 0;
- grpc_credentials_get_request_metadata(creds, &sync.pollset, "", on_metadata_response, &sync);
+ grpc_credentials_get_request_metadata(creds, &sync.pollset, service_url,
+ on_metadata_response, &sync);
gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
while (!sync.is_done) grpc_pollset_work(&sync.pollset, gpr_inf_future);
gpr_mu_unlock(GRPC_POLLSET_MU(&sync.pollset));
- grpc_pollset_destroy(&sync.pollset);
grpc_credentials_release(creds);
end:
diff --git a/test/core/security/verify_jwt.c b/test/core/security/verify_jwt.c
new file mode 100644
index 0000000000..e90be5de98
--- /dev/null
+++ b/test/core/security/verify_jwt.c
@@ -0,0 +1,119 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "src/core/security/jwt_verifier.h"
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/cmdline.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/sync.h>
+
+typedef struct {
+ grpc_pollset pollset;
+ int is_done;
+ int success;
+} synchronizer;
+
+static void print_usage_and_exit(gpr_cmdline *cl, const char *argv0) {
+ char *usage = gpr_cmdline_usage_string(cl, argv0);
+ fprintf(stderr, "%s", usage);
+ gpr_free(usage);
+ gpr_cmdline_destroy(cl);
+ exit(1);
+}
+
+static void on_jwt_verification_done(void *user_data,
+ grpc_jwt_verifier_status status,
+ grpc_jwt_claims *claims) {
+ synchronizer *sync = user_data;
+
+ sync->success = (status == GRPC_JWT_VERIFIER_OK);
+ if (sync->success) {
+ char *claims_str;
+ GPR_ASSERT(claims != NULL);
+ claims_str =
+ grpc_json_dump_to_string((grpc_json *)grpc_jwt_claims_json(claims), 2);
+ printf("Claims: \n\n%s\n", claims_str);
+ gpr_free(claims_str);
+ grpc_jwt_claims_destroy(claims);
+ } else {
+ GPR_ASSERT(claims == NULL);
+ fprintf(stderr, "Verification failed with error %s\n",
+ grpc_jwt_verifier_status_to_string(status));
+ }
+
+ gpr_mu_lock(GRPC_POLLSET_MU(&sync->pollset));
+ sync->is_done = 1;
+ grpc_pollset_kick(&sync->pollset);
+ gpr_mu_unlock(GRPC_POLLSET_MU(&sync->pollset));
+}
+
+int main(int argc, char **argv) {
+ synchronizer sync;
+ grpc_jwt_verifier *verifier;
+ gpr_cmdline *cl;
+ char *jwt = NULL;
+ char *aud = NULL;
+
+ cl = gpr_cmdline_create("JWT verifier tool");
+ gpr_cmdline_add_string(cl, "jwt", "JSON web token to verify", &jwt);
+ gpr_cmdline_add_string(cl, "aud", "Audience for the JWT", &aud);
+ gpr_cmdline_parse(cl, argc, argv);
+ if (jwt == NULL || aud == NULL) {
+ print_usage_and_exit(cl, argv[0]);
+ }
+
+ verifier = grpc_jwt_verifier_create(NULL, 0);
+
+ grpc_init();
+
+ grpc_pollset_init(&sync.pollset);
+ sync.is_done = 0;
+
+ grpc_jwt_verifier_verify(verifier, &sync.pollset, jwt, aud,
+ on_jwt_verification_done, &sync);
+
+ gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
+ while (!sync.is_done) grpc_pollset_work(&sync.pollset, gpr_inf_future);
+ gpr_mu_unlock(GRPC_POLLSET_MU(&sync.pollset));
+
+ grpc_jwt_verifier_destroy(verifier);
+ gpr_cmdline_destroy(cl);
+ return !sync.success;
+}
+
diff --git a/test/core/statistics/census_log_tests.c b/test/core/statistics/census_log_tests.c
index 241ec1ce4f..a34dcf07c4 100644
--- a/test/core/statistics/census_log_tests.c
+++ b/test/core/statistics/census_log_tests.c
@@ -568,7 +568,7 @@ void test_performance(void) {
double write_time_micro = 0.0;
int nrecords = 0;
setup_test(0);
- start_time = gpr_now();
+ start_time = gpr_now(GPR_CLOCK_REALTIME);
while (1) {
void* record = census_log_start_write(write_size);
if (record == NULL) {
@@ -577,7 +577,7 @@ void test_performance(void) {
census_log_end_write(record, write_size);
nrecords++;
}
- write_time = gpr_time_sub(gpr_now(), start_time);
+ write_time = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start_time);
write_time_micro = write_time.tv_sec * 1000000 + write_time.tv_nsec / 1000;
census_log_shutdown();
printf(
diff --git a/test/core/statistics/multiple_writers_circular_buffer_test.c b/test/core/statistics/multiple_writers_circular_buffer_test.c
index a645e15918..56ada893ef 100644
--- a/test/core/statistics/multiple_writers_circular_buffer_test.c
+++ b/test/core/statistics/multiple_writers_circular_buffer_test.c
@@ -40,7 +40,7 @@
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
- srand(gpr_now().tv_nsec);
+ srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
test_multiple_writers_circular_log();
return 0;
}
diff --git a/test/core/statistics/multiple_writers_test.c b/test/core/statistics/multiple_writers_test.c
index 84aef15c1a..e524927da6 100644
--- a/test/core/statistics/multiple_writers_test.c
+++ b/test/core/statistics/multiple_writers_test.c
@@ -40,7 +40,7 @@
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
- srand(gpr_now().tv_nsec);
+ srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
test_multiple_writers();
return 0;
}
diff --git a/test/core/statistics/performance_test.c b/test/core/statistics/performance_test.c
index 3c1e28241e..3f0e080093 100644
--- a/test/core/statistics/performance_test.c
+++ b/test/core/statistics/performance_test.c
@@ -40,7 +40,7 @@
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
- srand(gpr_now().tv_nsec);
+ srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
test_performance();
return 0;
}
diff --git a/test/core/statistics/quick_test.c b/test/core/statistics/quick_test.c
index 0e432314bb..c72ae77b98 100644
--- a/test/core/statistics/quick_test.c
+++ b/test/core/statistics/quick_test.c
@@ -40,7 +40,7 @@
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
- srand(gpr_now().tv_nsec);
+ srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
test_invalid_record_size();
test_end_write_with_different_size();
test_read_pending_record();
diff --git a/test/core/statistics/small_log_test.c b/test/core/statistics/small_log_test.c
index c151b77f63..b26b95f639 100644
--- a/test/core/statistics/small_log_test.c
+++ b/test/core/statistics/small_log_test.c
@@ -40,7 +40,7 @@
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
- srand(gpr_now().tv_nsec);
+ srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
test_small_log();
return 0;
}
diff --git a/test/core/statistics/window_stats_test.c b/test/core/statistics/window_stats_test.c
index d893f7f792..1c66a87407 100644
--- a/test/core/statistics/window_stats_test.c
+++ b/test/core/statistics/window_stats_test.c
@@ -83,7 +83,7 @@ void empty_test(void) {
result.statistic = &sum;
census_window_stats_get_sums(stats, zero, &result);
GPR_ASSERT(result.count == 0 && sum.value1 == 0 && sum.value2 == 0);
- census_window_stats_get_sums(stats, gpr_now(), &result);
+ census_window_stats_get_sums(stats, gpr_now(GPR_CLOCK_REALTIME), &result);
GPR_ASSERT(result.count == 0 && sum.value1 == 0 && sum.value2 == 0);
census_window_stats_destroy(stats);
}
@@ -268,7 +268,7 @@ void rolling_time_test(void) {
struct census_window_stats* stats =
census_window_stats_create(1, &kMinInterval, 7, &kMyStatInfo);
GPR_ASSERT(stats != NULL);
- srand(gpr_now().tv_nsec);
+ srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
for (i = 0; i < 100000; i++) {
increment.tv_nsec = rand() % 100000000; /* up to 1/10th second */
when = gpr_time_add(when, increment);
@@ -292,7 +292,7 @@ void infinite_interval_test(void) {
gpr_timespec increment = {0, 0};
struct census_window_stats* stats =
census_window_stats_create(1, &gpr_inf_future, 10, &kMyStatInfo);
- srand(gpr_now().tv_nsec);
+ srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
for (i = 0; i < count; i++) {
increment.tv_sec = rand() % 21600; /* 6 hours */
when = gpr_time_add(when, increment);
diff --git a/test/core/support/cancellable_test.c b/test/core/support/cancellable_test.c
index b2db1afc76..2f4b67a785 100644
--- a/test/core/support/cancellable_test.c
+++ b/test/core/support/cancellable_test.c
@@ -81,22 +81,23 @@ static void test(void) {
GPR_ASSERT(!gpr_cancellable_is_cancelled(&t.cancel));
/* Test timeout on event wait for uncancelled gpr_cancellable */
- interval = gpr_now();
- gpr_event_cancellable_wait(
- &t.ev, gpr_time_add(gpr_now(), gpr_time_from_micros(1000000)), &t.cancel);
- interval = gpr_time_sub(gpr_now(), interval);
+ interval = gpr_now(GPR_CLOCK_REALTIME);
+ gpr_event_cancellable_wait(&t.ev, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(1000000)),
+ &t.cancel);
+ interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval);
GPR_ASSERT(gpr_time_cmp(interval, gpr_time_from_micros(500000)) >= 0);
GPR_ASSERT(gpr_time_cmp(gpr_time_from_micros(2000000), interval) >= 0);
/* Test timeout on cv wait for uncancelled gpr_cancellable */
gpr_mu_lock(&t.mu);
- interval = gpr_now();
+ interval = gpr_now(GPR_CLOCK_REALTIME);
while (!gpr_cv_cancellable_wait(
- &t.cv, &t.mu,
- gpr_time_add(gpr_now(), gpr_time_from_micros(1000000)),
- &t.cancel)) {
+ &t.cv, &t.mu,
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(1000000)),
+ &t.cancel)) {
}
- interval = gpr_time_sub(gpr_now(), interval);
+ interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval);
GPR_ASSERT(gpr_time_cmp(interval, gpr_time_from_micros(500000)) >= 0);
GPR_ASSERT(gpr_time_cmp(gpr_time_from_micros(2000000), interval) >= 0);
gpr_mu_unlock(&t.mu);
@@ -112,8 +113,8 @@ static void test(void) {
/* Wait a second, and check that no threads have finished waiting. */
gpr_mu_lock(&t.mu);
- gpr_cv_wait(&t.cv, &t.mu,
- gpr_time_add(gpr_now(), gpr_time_from_micros(1000000)));
+ gpr_cv_wait(&t.cv, &t.mu, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(1000000)));
GPR_ASSERT(t.n == n);
gpr_mu_unlock(&t.mu);
@@ -129,21 +130,22 @@ static void test(void) {
/* Test timeout on cv wait for cancelled gpr_cancellable */
gpr_mu_lock(&t.mu);
- interval = gpr_now();
+ interval = gpr_now(GPR_CLOCK_REALTIME);
while (!gpr_cv_cancellable_wait(
- &t.cv, &t.mu,
- gpr_time_add(gpr_now(), gpr_time_from_micros(1000000)),
- &t.cancel)) {
+ &t.cv, &t.mu,
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(1000000)),
+ &t.cancel)) {
}
- interval = gpr_time_sub(gpr_now(), interval);
+ interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval);
GPR_ASSERT(gpr_time_cmp(gpr_time_from_micros(100000), interval) >= 0);
gpr_mu_unlock(&t.mu);
/* Test timeout on event wait for cancelled gpr_cancellable */
- interval = gpr_now();
- gpr_event_cancellable_wait(
- &t.ev, gpr_time_add(gpr_now(), gpr_time_from_micros(1000000)), &t.cancel);
- interval = gpr_time_sub(gpr_now(), interval);
+ interval = gpr_now(GPR_CLOCK_REALTIME);
+ gpr_event_cancellable_wait(&t.ev, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(1000000)),
+ &t.cancel);
+ interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval);
GPR_ASSERT(gpr_time_cmp(gpr_time_from_micros(100000), interval) >= 0);
gpr_mu_destroy(&t.mu);
diff --git a/test/core/support/slice_test.c b/test/core/support/slice_test.c
index 63dedea50f..3ca87427dd 100644
--- a/test/core/support/slice_test.c
+++ b/test/core/support/slice_test.c
@@ -35,6 +35,7 @@
#include <string.h>
+#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "test/core/util/test_config.h"
diff --git a/test/core/support/stack_lockfree_test.c b/test/core/support/stack_lockfree_test.c
new file mode 100644
index 0000000000..42082de389
--- /dev/null
+++ b/test/core/support/stack_lockfree_test.c
@@ -0,0 +1,154 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/core/support/stack_lockfree.h"
+
+#include <stdlib.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
+#include "test/core/util/test_config.h"
+
+/* max stack size supported */
+#define MAX_STACK_SIZE 65534
+
+#define MAX_THREADS 32
+
+static void test_serial_sized(int size) {
+ gpr_stack_lockfree *stack = gpr_stack_lockfree_create(size);
+ int i;
+
+ /* First try popping empty */
+ GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1);
+
+ /* Now add one item and check it */
+ gpr_stack_lockfree_push(stack, 3);
+ GPR_ASSERT(gpr_stack_lockfree_pop(stack) == 3);
+ GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1);
+
+ /* Now add repeatedly more items and check them */
+ for (i = 1; i < size; i *= 2) {
+ int j;
+ for (j = 0; j <= i; j++) {
+ gpr_stack_lockfree_push(stack, j);
+ }
+ for (j = 0; j <= i; j++) {
+ GPR_ASSERT(gpr_stack_lockfree_pop(stack) == i - j);
+ }
+ GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1);
+ }
+
+ gpr_stack_lockfree_destroy(stack);
+}
+
+static void test_serial() {
+ int i;
+ for (i = 128; i < MAX_STACK_SIZE; i *= 2) {
+ test_serial_sized(i);
+ }
+ test_serial_sized(MAX_STACK_SIZE);
+}
+
+struct test_arg {
+ gpr_stack_lockfree *stack;
+ int stack_size;
+ int nthreads;
+ int rank;
+ int sum;
+};
+
+static void test_mt_body(void *v) {
+ struct test_arg *arg = (struct test_arg *)v;
+ int lo, hi;
+ int i;
+ int res;
+ lo = arg->rank * arg->stack_size / arg->nthreads;
+ hi = (arg->rank + 1) * arg->stack_size / arg->nthreads;
+ for (i = lo; i < hi; i++) {
+ gpr_stack_lockfree_push(arg->stack, i);
+ if ((res = gpr_stack_lockfree_pop(arg->stack)) != -1) {
+ arg->sum += res;
+ }
+ }
+ while ((res = gpr_stack_lockfree_pop(arg->stack)) != -1) {
+ arg->sum += res;
+ }
+}
+
+static void test_mt_sized(int size, int nth) {
+ gpr_stack_lockfree *stack;
+ struct test_arg args[MAX_THREADS];
+ gpr_thd_id thds[MAX_THREADS];
+ int sum;
+ int i;
+ gpr_thd_options options = gpr_thd_options_default();
+
+ stack = gpr_stack_lockfree_create(size);
+ for (i = 0; i < nth; i++) {
+ args[i].stack = stack;
+ args[i].stack_size = size;
+ args[i].nthreads = nth;
+ args[i].rank = i;
+ args[i].sum = 0;
+ }
+ gpr_thd_options_set_joinable(&options);
+ for (i = 0; i < nth; i++) {
+ GPR_ASSERT(gpr_thd_new(&thds[i], test_mt_body, &args[i], &options));
+ }
+ sum = 0;
+ for (i = 0; i < nth; i++) {
+ gpr_thd_join(thds[i]);
+ sum = sum + args[i].sum;
+ }
+ GPR_ASSERT((unsigned)sum == ((unsigned)size * (size - 1)) / 2);
+ gpr_stack_lockfree_destroy(stack);
+}
+
+static void test_mt() {
+ int size, nth;
+ for (nth = 1; nth < MAX_THREADS; nth++) {
+ for (size = 128; size < MAX_STACK_SIZE; size *= 2) {
+ test_mt_sized(size, nth);
+ }
+ test_mt_sized(MAX_STACK_SIZE, nth);
+ }
+}
+
+int main(int argc, char **argv) {
+ grpc_test_init(argc, argv);
+ test_serial();
+ test_mt();
+ return 0;
+}
diff --git a/test/core/support/string_test.c b/test/core/support/string_test.c
index b59082eecf..f04e72ac2b 100644
--- a/test/core/support/string_test.c
+++ b/test/core/support/string_test.c
@@ -58,21 +58,49 @@ static void test_strdup(void) {
GPR_ASSERT(NULL == gpr_strdup(NULL));
}
-static void expect_hexdump(const char *buf, size_t len, gpr_uint32 flags,
- const char *result) {
- char *got = gpr_hexdump(buf, len, flags);
+static void expect_dump(const char *buf, size_t len, gpr_uint32 flags,
+ const char *result) {
+ char *got = gpr_dump(buf, len, flags);
GPR_ASSERT(0 == strcmp(got, result));
gpr_free(got);
}
-static void test_hexdump(void) {
- LOG_TEST_NAME("test_hexdump");
- expect_hexdump("\x01", 1, 0, "01");
- expect_hexdump("\x01", 1, GPR_HEXDUMP_PLAINTEXT, "01 '.'");
- expect_hexdump("\x01\x02", 2, 0, "01 02");
- expect_hexdump("\x01\x23\x45\x67\x89\xab\xcd\xef", 8, 0,
+static void test_dump(void) {
+ LOG_TEST_NAME("test_dump");
+ expect_dump("\x01", 1, GPR_DUMP_HEX, "01");
+ expect_dump("\x01", 1, GPR_DUMP_HEX | GPR_DUMP_ASCII, "01 '.'");
+ expect_dump("\x01\x02", 2, GPR_DUMP_HEX, "01 02");
+ expect_dump("\x01\x23\x45\x67\x89\xab\xcd\xef", 8, GPR_DUMP_HEX,
"01 23 45 67 89 ab cd ef");
- expect_hexdump("ab", 2, GPR_HEXDUMP_PLAINTEXT, "61 62 'ab'");
+ expect_dump("ab", 2, GPR_DUMP_HEX | GPR_DUMP_ASCII, "61 62 'ab'");
+}
+
+static void expect_slice_dump(gpr_slice slice, gpr_uint32 flags,
+ const char *result) {
+ char *got = gpr_dump_slice(slice, flags);
+ GPR_ASSERT(0 == strcmp(got, result));
+ gpr_free(got);
+ gpr_slice_unref(slice);
+}
+
+static void test_dump_slice(void) {
+ static const char *text = "HELLO WORLD!";
+ static const char *long_text =
+ "It was a bright cold day in April, and the clocks were striking "
+ "thirteen. Winston Smith, his chin nuzzled into his breast in an effort "
+ "to escape the vile wind, slipped quickly through the glass doors of "
+ "Victory Mansions, though not quickly enough to prevent a swirl of "
+ "gritty dust from entering along with him.";
+
+ LOG_TEST_NAME("test_dump_slice");
+
+ expect_slice_dump(gpr_slice_from_copied_string(text), GPR_DUMP_ASCII, text);
+ expect_slice_dump(gpr_slice_from_copied_string(long_text), GPR_DUMP_ASCII,
+ long_text);
+ expect_slice_dump(gpr_slice_from_copied_buffer("\x01", 1), GPR_DUMP_HEX,
+ "01");
+ expect_slice_dump(gpr_slice_from_copied_buffer("\x01", 1),
+ GPR_DUMP_HEX | GPR_DUMP_ASCII, "01 '.'");
}
static void test_pu32_fail(const char *s) {
@@ -148,7 +176,8 @@ static void test_asprintf(void) {
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_strdup();
- test_hexdump();
+ test_dump();
+ test_dump_slice();
test_parse_uint32();
test_asprintf();
return 0;
diff --git a/test/core/support/sync_test.c b/test/core/support/sync_test.c
index 44bc6ba471..99be5cdc90 100644
--- a/test/core/support/sync_test.c
+++ b/test/core/support/sync_test.c
@@ -242,12 +242,12 @@ static void test(const char *name, void (*body)(void *m),
void (*extra)(void *m), int timeout_s) {
gpr_int64 iterations = 1024;
struct test *m;
- gpr_timespec start = gpr_now();
+ gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME);
gpr_timespec time_taken;
gpr_timespec deadline =
gpr_time_add(start, gpr_time_from_micros(timeout_s * 1000000));
fprintf(stderr, "%s:", name);
- while (gpr_time_cmp(gpr_now(), deadline) < 0) {
+ while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) {
iterations <<= 1;
fprintf(stderr, " %ld", (long)iterations);
m = test_new(10, iterations);
@@ -265,7 +265,7 @@ static void test(const char *name, void (*body)(void *m),
}
test_destroy(m);
}
- time_taken = gpr_time_sub(gpr_now(), start);
+ time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start);
fprintf(stderr, " done %ld.%09d s\n", (long)time_taken.tv_sec,
(int)time_taken.tv_nsec);
}
@@ -323,7 +323,8 @@ static void inc_with_1ms_delay(void *v /*=m*/) {
for (i = 0; i != m->iterations; i++) {
gpr_timespec deadline;
gpr_mu_lock(&m->mu);
- deadline = gpr_time_add(gpr_now(), gpr_time_from_micros(1000));
+ deadline =
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(1000));
while (!gpr_cv_wait(&m->cv, &m->mu, deadline)) {
}
m->counter++;
@@ -339,7 +340,8 @@ static void inc_with_1ms_delay_event(void *v /*=m*/) {
gpr_int64 i;
for (i = 0; i != m->iterations; i++) {
gpr_timespec deadline;
- deadline = gpr_time_add(gpr_now(), gpr_time_from_micros(1000));
+ deadline =
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(1000));
GPR_ASSERT(gpr_event_wait(&m->event, deadline) == NULL);
gpr_mu_lock(&m->mu);
m->counter++;
@@ -382,9 +384,9 @@ static void consumer(void *v /*=m*/) {
gpr_mu_lock(&m->mu);
m->counter = n;
gpr_mu_unlock(&m->mu);
- GPR_ASSERT(
- !queue_remove(&m->q, &value,
- gpr_time_add(gpr_now(), gpr_time_from_micros(1000000))));
+ GPR_ASSERT(!queue_remove(&m->q, &value,
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(1000000))));
mark_thread_done(m);
}
diff --git a/test/core/support/useful_test.c b/test/core/support/useful_test.c
index feaf436379..cbf4f02e26 100644
--- a/test/core/support/useful_test.c
+++ b/test/core/support/useful_test.c
@@ -39,6 +39,7 @@
int main(int argc, char **argv) {
int four[4];
int five[5];
+ gpr_uint32 bitset = 0;
grpc_test_init(argc, argv);
GPR_ASSERT(GPR_MIN(1, 2) == 1);
@@ -55,5 +56,18 @@ int main(int argc, char **argv) {
GPR_ASSERT(GPR_ARRAY_SIZE(four) == 4);
GPR_ASSERT(GPR_ARRAY_SIZE(five) == 5);
+ GPR_ASSERT(GPR_BITCOUNT((1u << 31) - 1) == 31);
+ GPR_ASSERT(GPR_BITCOUNT(1u << 3) == 1);
+ GPR_ASSERT(GPR_BITCOUNT(0) == 0);
+
+ GPR_ASSERT(GPR_BITSET(&bitset, 3) == 8);
+ GPR_ASSERT(GPR_BITCOUNT(bitset) == 1);
+ GPR_ASSERT(GPR_BITGET(bitset, 3) == 1);
+ GPR_ASSERT(GPR_BITSET(&bitset, 1) == 10);
+ GPR_ASSERT(GPR_BITCOUNT(bitset) == 2);
+ GPR_ASSERT(GPR_BITCLEAR(&bitset, 3) == 2);
+ GPR_ASSERT(GPR_BITCOUNT(bitset) == 1);
+ GPR_ASSERT(GPR_BITGET(bitset, 3) == 0);
+
return 0;
}
diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c
index eba24f5c6e..177adbebc2 100644
--- a/test/core/surface/completion_queue_test.c
+++ b/test/core/surface/completion_queue_test.c
@@ -69,22 +69,25 @@ static void test_wait_empty(void) {
LOG_TEST("test_wait_empty");
cc = grpc_completion_queue_create();
- GPR_ASSERT(grpc_completion_queue_next(cc, gpr_now()).type ==
+ GPR_ASSERT(grpc_completion_queue_next(cc, gpr_now(GPR_CLOCK_REALTIME)).type ==
GRPC_QUEUE_TIMEOUT);
shutdown_and_destroy(cc);
}
+static void do_nothing_end_completion(void *arg, grpc_cq_completion *c) {}
+
static void test_cq_end_op(void) {
grpc_event ev;
grpc_completion_queue *cc;
+ grpc_cq_completion completion;
void *tag = create_test_tag();
LOG_TEST("test_cq_end_op");
cc = grpc_completion_queue_create();
- grpc_cq_begin_op(cc, NULL);
- grpc_cq_end_op(cc, tag, NULL, 1);
+ grpc_cq_begin_op(cc);
+ grpc_cq_end_op(cc, tag, 1, do_nothing_end_completion, NULL, &completion);
ev = grpc_completion_queue_next(cc, gpr_inf_past);
GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
@@ -120,6 +123,7 @@ static void test_pluck(void) {
grpc_event ev;
grpc_completion_queue *cc;
void *tags[128];
+ grpc_cq_completion completions[GPR_ARRAY_SIZE(tags)];
unsigned i, j;
LOG_TEST("test_pluck");
@@ -134,8 +138,9 @@ static void test_pluck(void) {
cc = grpc_completion_queue_create();
for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
- grpc_cq_begin_op(cc, NULL);
- grpc_cq_end_op(cc, tags[i], NULL, 1);
+ grpc_cq_begin_op(cc);
+ grpc_cq_end_op(cc, tags[i], 1, do_nothing_end_completion, NULL,
+ &completions[i]);
}
for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
@@ -144,8 +149,9 @@ static void test_pluck(void) {
}
for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
- grpc_cq_begin_op(cc, NULL);
- grpc_cq_end_op(cc, tags[i], NULL, 1);
+ grpc_cq_begin_op(cc);
+ grpc_cq_end_op(cc, tags[i], 1, do_nothing_end_completion, NULL,
+ &completions[i]);
}
for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
@@ -171,7 +177,11 @@ typedef struct test_thread_options {
} test_thread_options;
gpr_timespec ten_seconds_time(void) {
- return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1);
+ return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
+}
+
+static void free_completion(void *arg, grpc_cq_completion *completion) {
+ gpr_free(completion);
}
static void producer_thread(void *arg) {
@@ -184,7 +194,7 @@ static void producer_thread(void *arg) {
gpr_log(GPR_INFO, "producer %d phase 1", opt->id);
for (i = 0; i < TEST_THREAD_EVENTS; i++) {
- grpc_cq_begin_op(opt->cc, NULL);
+ grpc_cq_begin_op(opt->cc);
}
gpr_log(GPR_INFO, "producer %d phase 1 done", opt->id);
@@ -193,7 +203,8 @@ static void producer_thread(void *arg) {
gpr_log(GPR_INFO, "producer %d phase 2", opt->id);
for (i = 0; i < TEST_THREAD_EVENTS; i++) {
- grpc_cq_end_op(opt->cc, (void *)(gpr_intptr)1, NULL, 1);
+ grpc_cq_end_op(opt->cc, (void *)(gpr_intptr)1, 1, free_completion, NULL,
+ gpr_malloc(sizeof(grpc_cq_completion)));
opt->events_triggered++;
}
diff --git a/test/core/transport/chttp2/bin_encoder_test.c b/test/core/transport/chttp2/bin_encoder_test.c
index 983eaf5a0d..1ffd8ed3cb 100644
--- a/test/core/transport/chttp2/bin_encoder_test.c
+++ b/test/core/transport/chttp2/bin_encoder_test.c
@@ -44,10 +44,8 @@ static int all_ok = 1;
static void expect_slice_eq(gpr_slice expected, gpr_slice slice, char *debug,
int line) {
if (0 != gpr_slice_cmp(slice, expected)) {
- char *hs = gpr_hexdump((const char *)GPR_SLICE_START_PTR(slice),
- GPR_SLICE_LENGTH(slice), GPR_HEXDUMP_PLAINTEXT);
- char *he = gpr_hexdump((const char *)GPR_SLICE_START_PTR(expected),
- GPR_SLICE_LENGTH(expected), GPR_HEXDUMP_PLAINTEXT);
+ char *hs = gpr_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ char *he = gpr_dump_slice(expected, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_ERROR, "FAILED:%d: %s\ngot: %s\nwant: %s", line, debug, hs,
he);
gpr_free(hs);
@@ -83,12 +81,9 @@ static void expect_combined_equiv(const char *s, size_t len, int line) {
gpr_slice expect = grpc_chttp2_huffman_compress(base64);
gpr_slice got = grpc_chttp2_base64_encode_and_huffman_compress(input);
if (0 != gpr_slice_cmp(expect, got)) {
- char *t = gpr_hexdump((const char *)GPR_SLICE_START_PTR(input),
- GPR_SLICE_LENGTH(input), GPR_HEXDUMP_PLAINTEXT);
- char *e = gpr_hexdump((const char *)GPR_SLICE_START_PTR(expect),
- GPR_SLICE_LENGTH(expect), GPR_HEXDUMP_PLAINTEXT);
- char *g = gpr_hexdump((const char *)GPR_SLICE_START_PTR(got),
- GPR_SLICE_LENGTH(got), GPR_HEXDUMP_PLAINTEXT);
+ char *t = gpr_dump_slice(input, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ char *e = gpr_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ char *g = gpr_dump_slice(got, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_ERROR, "FAILED:%d:\ntest: %s\ngot: %s\nwant: %s", t, g, e);
gpr_free(t);
gpr_free(e);
diff --git a/test/core/transport/chttp2/hpack_parser_test.c b/test/core/transport/chttp2/hpack_parser_test.c
index 1d6ad2a758..3a313375a4 100644
--- a/test/core/transport/chttp2/hpack_parser_test.c
+++ b/test/core/transport/chttp2/hpack_parser_test.c
@@ -53,7 +53,7 @@ static void onhdr(void *ud, grpc_mdelem *md) {
GPR_ASSERT(evalue);
GPR_ASSERT(gpr_slice_str_cmp(md->key->slice, ekey) == 0);
GPR_ASSERT(gpr_slice_str_cmp(md->value->slice, evalue) == 0);
- grpc_mdelem_unref(md);
+ GRPC_MDELEM_UNREF(md);
}
static void test_vector(grpc_chttp2_hpack_parser *parser,
diff --git a/test/core/transport/chttp2/hpack_table_test.c b/test/core/transport/chttp2/hpack_table_test.c
index 8b86e08168..15b37d17b6 100644
--- a/test/core/transport/chttp2/hpack_table_test.c
+++ b/test/core/transport/chttp2/hpack_table_test.c
@@ -167,7 +167,7 @@ static grpc_chttp2_hptbl_find_result find_simple(grpc_chttp2_hptbl *tbl,
const char *value) {
grpc_mdelem *md = grpc_mdelem_from_strings(tbl->mdctx, key, value);
grpc_chttp2_hptbl_find_result r = grpc_chttp2_hptbl_find(tbl, md);
- grpc_mdelem_unref(md);
+ GRPC_MDELEM_UNREF(md);
return r;
}
diff --git a/test/core/transport/chttp2/stream_encoder_test.c b/test/core/transport/chttp2/stream_encoder_test.c
index bf70d43e78..e6731ff195 100644
--- a/test/core/transport/chttp2/stream_encoder_test.c
+++ b/test/core/transport/chttp2/stream_encoder_test.c
@@ -85,12 +85,8 @@ static void verify_sopb(size_t window_available, int eof,
grpc_sopb_destroy(&encops);
if (0 != gpr_slice_cmp(merged, expect)) {
- char *expect_str =
- gpr_hexdump((char *)GPR_SLICE_START_PTR(expect),
- GPR_SLICE_LENGTH(expect), GPR_HEXDUMP_PLAINTEXT);
- char *got_str =
- gpr_hexdump((char *)GPR_SLICE_START_PTR(merged),
- GPR_SLICE_LENGTH(merged), GPR_HEXDUMP_PLAINTEXT);
+ char *expect_str = gpr_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ char *got_str = gpr_dump_slice(merged, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_ERROR, "mismatched output for %s", expected);
gpr_log(GPR_ERROR, "EXPECT: %s", expect_str);
gpr_log(GPR_ERROR, "GOT: %s", got_str);
@@ -266,7 +262,7 @@ static void chk_hdr(void *p, grpc_mdelem *el) {
GPR_ASSERT(0 == gpr_slice_str_cmp(el->key->slice, st->key));
GPR_ASSERT(0 == gpr_slice_str_cmp(el->value->slice, st->value));
st->got_hdr = 1;
- grpc_mdelem_unref(el);
+ GRPC_MDELEM_UNREF(el);
}
static void test_decode_random_headers_inner(int max_len) {
diff --git a/test/core/transport/metadata_test.c b/test/core/transport/metadata_test.c
index 89deee5a40..a932e04f33 100644
--- a/test/core/transport/metadata_test.c
+++ b/test/core/transport/metadata_test.c
@@ -70,10 +70,10 @@ static void test_create_string(void) {
GPR_ASSERT(s3 != s1);
GPR_ASSERT(gpr_slice_str_cmp(s1->slice, "hello") == 0);
GPR_ASSERT(gpr_slice_str_cmp(s3->slice, "very much not hello") == 0);
- grpc_mdstr_unref(s1);
- grpc_mdstr_unref(s2);
+ GRPC_MDSTR_UNREF(s1);
+ GRPC_MDSTR_UNREF(s2);
grpc_mdctx_unref(ctx);
- grpc_mdstr_unref(s3);
+ GRPC_MDSTR_UNREF(s3);
}
static void test_create_metadata(void) {
@@ -93,9 +93,9 @@ static void test_create_metadata(void) {
GPR_ASSERT(gpr_slice_str_cmp(m1->key->slice, "a") == 0);
GPR_ASSERT(gpr_slice_str_cmp(m1->value->slice, "b") == 0);
GPR_ASSERT(gpr_slice_str_cmp(m3->value->slice, "c") == 0);
- grpc_mdelem_unref(m1);
- grpc_mdelem_unref(m2);
- grpc_mdelem_unref(m3);
+ GRPC_MDELEM_UNREF(m1);
+ GRPC_MDELEM_UNREF(m2);
+ GRPC_MDELEM_UNREF(m3);
grpc_mdctx_unref(ctx);
}
@@ -112,7 +112,7 @@ static void test_create_many_ephemeral_metadata(void) {
/* add, and immediately delete a bunch of different elements */
for (i = 0; i < MANY; i++) {
gpr_ltoa(i, buffer);
- grpc_mdelem_unref(grpc_mdelem_from_strings(ctx, "a", buffer));
+ GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", buffer));
}
/* capacity should not grow */
GPR_ASSERT(mdtab_capacity_before ==
@@ -140,11 +140,11 @@ static void test_create_many_persistant_metadata(void) {
gpr_ltoa(i, buffer);
md = grpc_mdelem_from_strings(ctx, "a", buffer);
GPR_ASSERT(md == created[i]);
- grpc_mdelem_unref(md);
+ GRPC_MDELEM_UNREF(md);
}
/* cleanup phase */
for (i = 0; i < MANY; i++) {
- grpc_mdelem_unref(created[i]);
+ GRPC_MDELEM_UNREF(created[i]);
}
grpc_mdctx_unref(ctx);
@@ -160,15 +160,15 @@ static void test_spin_creating_the_same_thing(void) {
GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 0);
GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 0);
- grpc_mdelem_unref(grpc_mdelem_from_strings(ctx, "a", "b"));
+ GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", "b"));
GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1);
GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1);
- grpc_mdelem_unref(grpc_mdelem_from_strings(ctx, "a", "b"));
+ GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", "b"));
GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1);
GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1);
- grpc_mdelem_unref(grpc_mdelem_from_strings(ctx, "a", "b"));
+ GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", "b"));
GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1);
GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1);
@@ -196,8 +196,8 @@ static void test_things_stick_around(void) {
}
for (i = 0; i < nstrs; i++) {
- grpc_mdstr_ref(strs[i]);
- grpc_mdstr_unref(strs[i]);
+ GRPC_MDSTR_REF(strs[i]);
+ GRPC_MDSTR_UNREF(strs[i]);
}
for (i = 0; i < nstrs; i++) {
@@ -209,12 +209,12 @@ static void test_things_stick_around(void) {
}
for (i = 0; i < nstrs; i++) {
- grpc_mdstr_unref(strs[shuf[i]]);
+ GRPC_MDSTR_UNREF(strs[shuf[i]]);
for (j = i + 1; j < nstrs; j++) {
gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", shuf[j]);
test = grpc_mdstr_from_string(ctx, buffer);
GPR_ASSERT(test == strs[shuf[j]]);
- grpc_mdstr_unref(test);
+ GRPC_MDSTR_UNREF(test);
gpr_free(buffer);
}
}
@@ -237,14 +237,14 @@ static void test_slices_work(void) {
str = grpc_mdstr_from_string(
ctx, "123456789012345678901234567890123456789012345678901234567890");
slice = gpr_slice_ref(str->slice);
- grpc_mdstr_unref(str);
+ GRPC_MDSTR_UNREF(str);
gpr_slice_unref(slice);
str = grpc_mdstr_from_string(
ctx, "123456789012345678901234567890123456789012345678901234567890");
slice = gpr_slice_ref(str->slice);
gpr_slice_unref(slice);
- grpc_mdstr_unref(str);
+ GRPC_MDSTR_UNREF(str);
grpc_mdctx_unref(ctx);
}
@@ -264,7 +264,7 @@ static void test_base64_and_huffman_works(void) {
GPR_ASSERT(0 == gpr_slice_cmp(slice1, slice2));
gpr_slice_unref(slice2);
- grpc_mdstr_unref(str);
+ GRPC_MDSTR_UNREF(str);
grpc_mdctx_unref(ctx);
}
diff --git a/test/core/tsi/transport_security_test.c b/test/core/tsi/transport_security_test.c
index bba6744194..bec3866166 100644
--- a/test/core/tsi/transport_security_test.c
+++ b/test/core/tsi/transport_security_test.c
@@ -46,9 +46,6 @@
#include "src/core/tsi/ssl_transport_security.h"
#include "test/core/util/test_config.h"
-/* Currently points to 1.0.2a. */
-#define GRPC_MIN_OPENSSL_VERSION_NUMBER 0x1000201fL
-
typedef struct {
/* 1 if success, 0 if failure. */
int expected;
@@ -299,13 +296,8 @@ static void test_peer_matches_name(void) {
}
}
-static void test_openssl_version(void) {
- GPR_ASSERT(OPENSSL_VERSION_NUMBER >= GRPC_MIN_OPENSSL_VERSION_NUMBER);
-}
-
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_peer_matches_name();
- test_openssl_version();
return 0;
}
diff --git a/test/core/util/grpc_profiler.c b/test/core/util/grpc_profiler.c
index d5b6cfeef1..c2c0c9cf53 100644
--- a/test/core/util/grpc_profiler.c
+++ b/test/core/util/grpc_profiler.c
@@ -43,11 +43,17 @@ void grpc_profiler_stop() { ProfilerStop(); }
#include <grpc/support/log.h>
void grpc_profiler_start(const char *filename) {
- gpr_log(GPR_DEBUG,
- "You do not have google-perftools installed, profiling is disabled [for %s]", filename);
- gpr_log(GPR_DEBUG,
- "To install on ubuntu: sudo apt-get install google-perftools "
- "libgoogle-perftools-dev");
+ static int printed_warning = 0;
+ if (!printed_warning) {
+ gpr_log(GPR_DEBUG,
+ "You do not have google-perftools installed, profiling is disabled "
+ "[for %s]",
+ filename);
+ gpr_log(GPR_DEBUG,
+ "To install on ubuntu: sudo apt-get install google-perftools "
+ "libgoogle-perftools-dev");
+ printed_warning = 1;
+ }
}
void grpc_profiler_stop(void) {}
diff --git a/test/core/util/test_config.c b/test/core/util/test_config.c
index 20ab67ec15..225658f5e2 100644
--- a/test/core/util/test_config.c
+++ b/test/core/util/test_config.c
@@ -48,7 +48,45 @@ static int seed(void) { return getpid(); }
static int seed(void) { return _getpid(); }
#endif
+#if GPR_WINDOWS_CRASH_HANDLER
+LONG crash_handler(struct _EXCEPTION_POINTERS* ex_info) {
+ gpr_log(GPR_DEBUG, "Exception handler called, dumping information");
+ while (ex_info->ExceptionRecord) {
+ DWORD code = ex_info->ExceptionRecord->ExceptionCode;
+ DWORD flgs = ex_info->ExceptionRecord->ExceptionFlags;
+ PVOID addr = ex_info->ExceptionRecord->ExceptionAddress;
+ gpr_log("code: %x - flags: %d - address: %p", code, flgs, addr);
+ ex_info->ExceptionRecord = ex_info->ExceptionRecord->ExceptionRecord;
+ }
+ if (IsDebuggerPresent()) {
+ __debugbreak();
+ } else {
+ _exit(1);
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+void abort_handler(int sig) {
+ gpr_log(GPR_DEBUG, "Abort handler called.");
+ if (IsDebuggerPresent()) {
+ __debugbreak();
+ } else {
+ _exit(1);
+ }
+}
+
+static void install_crash_handler() {
+ SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) crash_handler);
+ _set_abort_behavior(0, _WRITE_ABORT_MSG);
+ _set_abort_behavior(0, _CALL_REPORTFAULT);
+ signal(SIGABRT, abort_handler);
+}
+#else
+static void install_crash_handler() { }
+#endif
+
void grpc_test_init(int argc, char **argv) {
+ install_crash_handler();
gpr_log(GPR_DEBUG, "test slowdown: machine=%f build=%f total=%f",
(double)GRPC_TEST_SLOWDOWN_MACHINE_FACTOR,
(double)GRPC_TEST_SLOWDOWN_BUILD_FACTOR,
diff --git a/test/core/util/test_config.h b/test/core/util/test_config.h
index 0b3c54373d..3218953166 100644
--- a/test/core/util/test_config.h
+++ b/test/core/util/test_config.h
@@ -52,11 +52,11 @@ extern "C" {
(GRPC_TEST_SLOWDOWN_BUILD_FACTOR * GRPC_TEST_SLOWDOWN_MACHINE_FACTOR)
#define GRPC_TIMEOUT_SECONDS_TO_DEADLINE(x) \
- gpr_time_add(gpr_now(), \
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), \
gpr_time_from_micros(GRPC_TEST_SLOWDOWN_FACTOR * 1e6 * (x)))
-#define GRPC_TIMEOUT_MILLIS_TO_DEADLINE(x) \
- gpr_time_add(gpr_now(), \
+#define GRPC_TIMEOUT_MILLIS_TO_DEADLINE(x) \
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), \
gpr_time_from_micros(GRPC_TEST_SLOWDOWN_FACTOR * 1e3 * (x)))
#ifndef GRPC_TEST_CUSTOM_PICK_PORT
@@ -69,4 +69,4 @@ void grpc_test_init(int argc, char **argv);
}
#endif /* __cplusplus */
-#endif /* GRPC_TEST_CORE_UTIL_TEST_CONFIG_H */
+#endif /* GRPC_TEST_CORE_UTIL_TEST_CONFIG_H */
diff --git a/test/cpp/common/auth_property_iterator_test.cc b/test/cpp/common/auth_property_iterator_test.cc
new file mode 100644
index 0000000000..3d983fa310
--- /dev/null
+++ b/test/cpp/common/auth_property_iterator_test.cc
@@ -0,0 +1,101 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc++/auth_context.h>
+#include <gtest/gtest.h>
+#include "src/cpp/common/secure_auth_context.h"
+#include "src/core/security/security_context.h"
+
+namespace grpc {
+namespace {
+
+class TestAuthPropertyIterator : public AuthPropertyIterator {
+ public:
+ TestAuthPropertyIterator() {}
+ TestAuthPropertyIterator(const grpc_auth_property* property,
+ const grpc_auth_property_iterator* iter)
+ : AuthPropertyIterator(property, iter) {}
+};
+
+class AuthPropertyIteratorTest : public ::testing::Test {
+ protected:
+ void SetUp() GRPC_OVERRIDE {
+ ctx_ = grpc_auth_context_create(NULL, 3);
+ ctx_->properties[0] = grpc_auth_property_init_from_cstring("name", "chapi");
+ ctx_->properties[1] = grpc_auth_property_init_from_cstring("name", "chapo");
+ ctx_->properties[2] = grpc_auth_property_init_from_cstring("foo", "bar");
+ ctx_->peer_identity_property_name = ctx_->properties[0].name;
+ }
+ void TearDown() GRPC_OVERRIDE {
+ GRPC_AUTH_CONTEXT_UNREF(ctx_, "AuthPropertyIteratorTest");
+ }
+ grpc_auth_context* ctx_;
+
+};
+
+TEST_F(AuthPropertyIteratorTest, DefaultCtor) {
+ TestAuthPropertyIterator iter1;
+ TestAuthPropertyIterator iter2;
+ EXPECT_EQ(iter1, iter2);
+}
+
+TEST_F(AuthPropertyIteratorTest, GeneralTest) {
+ grpc_auth_property_iterator c_iter =
+ grpc_auth_context_property_iterator(ctx_);
+ const grpc_auth_property* property =
+ grpc_auth_property_iterator_next(&c_iter);
+ TestAuthPropertyIterator iter(property, &c_iter);
+ TestAuthPropertyIterator empty_iter;
+ EXPECT_FALSE(iter == empty_iter);
+ AuthProperty p0 = *iter;
+ ++iter;
+ AuthProperty p1 = *iter;
+ iter++;
+ AuthProperty p2 = *iter;
+ EXPECT_EQ("name", p0.first);
+ EXPECT_EQ("chapi", p0.second);
+ EXPECT_EQ("name", p1.first);
+ EXPECT_EQ("chapo", p1.second);
+ EXPECT_EQ("foo", p2.first);
+ EXPECT_EQ("bar", p2.second);
+ ++iter;
+ EXPECT_EQ(empty_iter, iter);
+}
+
+} // namespace
+} // namespace grpc
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc
new file mode 100644
index 0000000000..f18a04178e
--- /dev/null
+++ b/test/cpp/common/secure_auth_context_test.cc
@@ -0,0 +1,123 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc++/auth_context.h>
+#include <gtest/gtest.h>
+#include "src/cpp/common/secure_auth_context.h"
+#include "src/core/security/security_context.h"
+
+namespace grpc {
+namespace {
+
+class SecureAuthContextTest : public ::testing::Test {};
+
+// Created with nullptr
+TEST_F(SecureAuthContextTest, EmptyContext) {
+ SecureAuthContext context(nullptr);
+ EXPECT_TRUE(context.GetPeerIdentity().empty());
+ EXPECT_TRUE(context.GetPeerIdentityPropertyName().empty());
+ EXPECT_TRUE(context.FindPropertyValues("").empty());
+ EXPECT_TRUE(context.FindPropertyValues("whatever").empty());
+ EXPECT_TRUE(context.begin() == context.end());
+}
+
+TEST_F(SecureAuthContextTest, Properties) {
+ grpc_auth_context* ctx = grpc_auth_context_create(NULL, 3);
+ ctx->properties[0] = grpc_auth_property_init_from_cstring("name", "chapi");
+ ctx->properties[1] = grpc_auth_property_init_from_cstring("name", "chapo");
+ ctx->properties[2] = grpc_auth_property_init_from_cstring("foo", "bar");
+ ctx->peer_identity_property_name = ctx->properties[0].name;
+
+ SecureAuthContext context(ctx);
+ std::vector<grpc::string> peer_identity = context.GetPeerIdentity();
+ EXPECT_EQ(2u, peer_identity.size());
+ EXPECT_EQ("chapi", peer_identity[0]);
+ EXPECT_EQ("chapo", peer_identity[1]);
+ EXPECT_EQ("name", context.GetPeerIdentityPropertyName());
+ std::vector<grpc::string> bar = context.FindPropertyValues("foo");
+ EXPECT_EQ(1u, bar.size());
+ EXPECT_EQ("bar", bar[0]);
+}
+
+TEST_F(SecureAuthContextTest, Iterators) {
+ grpc_auth_context* ctx = grpc_auth_context_create(NULL, 3);
+ ctx->properties[0] = grpc_auth_property_init_from_cstring("name", "chapi");
+ ctx->properties[1] = grpc_auth_property_init_from_cstring("name", "chapo");
+ ctx->properties[2] = grpc_auth_property_init_from_cstring("foo", "bar");
+ ctx->peer_identity_property_name = ctx->properties[0].name;
+
+ SecureAuthContext context(ctx);
+ AuthPropertyIterator iter = context.begin();
+ EXPECT_TRUE(context.end() != iter);
+ AuthProperty p0 = *iter;
+ ++iter;
+ AuthProperty p1 = *iter;
+ iter++;
+ AuthProperty p2 = *iter;
+ EXPECT_EQ("name", p0.first);
+ EXPECT_EQ("chapi", p0.second);
+ EXPECT_EQ("name", p1.first);
+ EXPECT_EQ("chapo", p1.second);
+ EXPECT_EQ("foo", p2.first);
+ EXPECT_EQ("bar", p2.second);
+ ++iter;
+ EXPECT_EQ(context.end(), iter);
+ // Range-based for loop test.
+ int i = 0;
+ for (auto p : context) {
+ switch (i++) {
+ case 0:
+ EXPECT_EQ("name", p.first);
+ EXPECT_EQ("chapi", p.second);
+ break;
+ case 1:
+ EXPECT_EQ("name", p.first);
+ EXPECT_EQ("chapo", p.second);
+ break;
+ case 2:
+ EXPECT_EQ("foo", p.first);
+ EXPECT_EQ("bar", p.second);
+ break;
+ default:
+ EXPECT_TRUE(0);
+ }
+ }
+}
+
+} // namespace
+} // namespace grpc
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc
index 645226f375..906f124c05 100644
--- a/test/cpp/end2end/client_crash_test.cc
+++ b/test/cpp/end2end/client_crash_test.cc
@@ -31,13 +31,10 @@
*
*/
-#include <thread>
-
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/echo_duplicate.grpc.pb.h"
#include "test/cpp/util/echo.grpc.pb.h"
-#include "src/cpp/server/thread_pool.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 5e850ea30a..4b27cfea21 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -35,7 +35,6 @@
#include <thread>
#include "src/core/security/credentials.h"
-#include "src/cpp/server/thread_pool.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/echo_duplicate.grpc.pb.h"
@@ -46,6 +45,7 @@
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
+#include <grpc++/fixed_size_thread_pool.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
@@ -83,16 +83,32 @@ void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request,
}
}
+template <typename T>
+void CheckAuthContext(T* context) {
+ std::shared_ptr<const AuthContext> auth_ctx = context->auth_context();
+ std::vector<grpc::string> fake =
+ auth_ctx->FindPropertyValues("transport_security_type");
+ EXPECT_EQ(1u, fake.size());
+ EXPECT_EQ("fake", fake[0]);
+ EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty());
+ EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty());
+}
+
} // namespace
class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
public:
- TestServiceImpl() : signal_client_(false) {}
+ TestServiceImpl() : signal_client_(false), host_() {}
+ explicit TestServiceImpl(const grpc::string& host)
+ : signal_client_(false), host_(new grpc::string(host)) {}
Status Echo(ServerContext* context, const EchoRequest* request,
EchoResponse* response) GRPC_OVERRIDE {
response->set_message(request->message());
MaybeEchoDeadline(context, request, response);
+ if (host_) {
+ response->mutable_param()->set_host(*host_);
+ }
if (request->has_param() && request->param().client_cancel_after_us()) {
{
std::unique_lock<std::mutex> lock(mu_);
@@ -100,15 +116,15 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
}
while (!context->IsCancelled()) {
gpr_sleep_until(gpr_time_add(
- gpr_now(),
+ gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_micros(request->param().client_cancel_after_us())));
}
return Status::CANCELLED;
} else if (request->has_param() &&
request->param().server_cancel_after_us()) {
gpr_sleep_until(gpr_time_add(
- gpr_now(),
- gpr_time_from_micros(request->param().server_cancel_after_us())));
+ gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(request->param().server_cancel_after_us())));
return Status::CANCELLED;
} else {
EXPECT_FALSE(context->IsCancelled());
@@ -123,6 +139,9 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
context->AddTrailingMetadata((*iter).first, (*iter).second);
}
}
+ if (request->has_param() && request->param().check_auth_context()) {
+ CheckAuthContext(context);
+ }
return Status::OK;
}
@@ -191,6 +210,7 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
private:
bool signal_client_;
std::mutex mu_;
+ std::unique_ptr<grpc::string> host_;
};
class TestServiceImplDupPkg
@@ -205,7 +225,8 @@ class TestServiceImplDupPkg
class End2endTest : public ::testing::Test {
protected:
- End2endTest() : kMaxMessageSize_(8192), thread_pool_(2) {}
+ End2endTest()
+ : kMaxMessageSize_(8192), special_service_("special"), thread_pool_(2) {}
void SetUp() GRPC_OVERRIDE {
int port = grpc_pick_unused_port_or_die();
@@ -215,6 +236,7 @@ class End2endTest : public ::testing::Test {
builder.AddListeningPort(server_address_.str(),
FakeTransportSecurityServerCredentials());
builder.RegisterService(&service_);
+ builder.RegisterService("special", &special_service_);
builder.SetMaxMessageSize(
kMaxMessageSize_); // For testing max message size.
builder.RegisterService(&dup_pkg_service_);
@@ -236,8 +258,9 @@ class End2endTest : public ::testing::Test {
std::ostringstream server_address_;
const int kMaxMessageSize_;
TestServiceImpl service_;
+ TestServiceImpl special_service_;
TestServiceImplDupPkg dup_pkg_service_;
- ThreadPool thread_pool_;
+ FixedSizeThreadPool thread_pool_;
};
static void SendRpc(grpc::cpp::test::util::TestService::Stub* stub,
@@ -254,6 +277,22 @@ static void SendRpc(grpc::cpp::test::util::TestService::Stub* stub,
}
}
+TEST_F(End2endTest, SimpleRpcWithHost) {
+ ResetStub();
+
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello");
+
+ ClientContext context;
+ context.set_authority("special");
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_EQ(response.message(), request.message());
+ EXPECT_TRUE(response.has_param());
+ EXPECT_EQ(response.param().host(), "special");
+ EXPECT_TRUE(s.ok());
+}
+
TEST_F(End2endTest, SimpleRpc) {
ResetStub();
SendRpc(stub_.get(), 1);
@@ -490,7 +529,8 @@ TEST_F(End2endTest, BadCredentials) {
}
void CancelRpc(ClientContext* context, int delay_us, TestServiceImpl* service) {
- gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_micros(delay_us)));
+ gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(delay_us)));
while (!service->signal_client()) {
}
context->TryCancel();
@@ -726,6 +766,21 @@ TEST_F(End2endTest, RequestStreamServerEarlyCancelTest) {
EXPECT_EQ(s.error_code(), StatusCode::CANCELLED);
}
+TEST_F(End2endTest, ClientAuthContext) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello");
+ request.mutable_param()->set_check_auth_context(true);
+
+ ClientContext context;
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_EQ(response.message(), request.message());
+ EXPECT_TRUE(s.ok());
+
+ CheckAuthContext(&context);
+}
+
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc
index 2809ab8d3c..74b40d54d8 100644
--- a/test/cpp/end2end/mock_test.cc
+++ b/test/cpp/end2end/mock_test.cc
@@ -37,12 +37,12 @@
#include "test/core/util/test_config.h"
#include "test/cpp/util/echo_duplicate.grpc.pb.h"
#include "test/cpp/util/echo.grpc.pb.h"
-#include "src/cpp/server/thread_pool.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
+#include <grpc++/fixed_size_thread_pool.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
@@ -86,7 +86,9 @@ class MockClientReaderWriter<EchoRequest, EchoResponse> GRPC_FINAL
msg->set_message(last_message_);
return true;
}
- bool Write(const EchoRequest& msg) GRPC_OVERRIDE {
+
+ bool Write(const EchoRequest& msg,
+ const WriteOptions& options) GRPC_OVERRIDE {
gpr_log(GPR_INFO, "mock recv msg %s", msg.message().c_str());
last_message_ = msg.message();
return true;
@@ -258,7 +260,7 @@ class MockTest : public ::testing::Test {
std::unique_ptr<Server> server_;
std::ostringstream server_address_;
TestServiceImpl service_;
- ThreadPool thread_pool_;
+ FixedSizeThreadPool thread_pool_;
};
// Do one real rpc and one mocked one
diff --git a/test/cpp/end2end/server_crash_test.cc b/test/cpp/end2end/server_crash_test.cc
index 3fdae9bc07..d71345055d 100644
--- a/test/cpp/end2end/server_crash_test.cc
+++ b/test/cpp/end2end/server_crash_test.cc
@@ -31,13 +31,10 @@
*
*/
-#include <thread>
-
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/echo_duplicate.grpc.pb.h"
#include "test/cpp/util/echo.grpc.pb.h"
-#include "src/cpp/server/thread_pool.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
@@ -84,7 +81,8 @@ class ServiceImpl GRPC_FINAL
gpr_log(GPR_INFO, "recv msg %s", request.message().c_str());
response.set_message(request.message());
stream->Write(response);
- gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(1)));
+ gpr_sleep_until(
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(1)));
}
return Status::OK;
}
@@ -98,7 +96,8 @@ class ServiceImpl GRPC_FINAL
msg << "Hello " << i;
response.set_message(msg.str());
if (!writer->Write(response)) break;
- gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(1)));
+ gpr_sleep_until(
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(1)));
}
return Status::OK;
}
@@ -145,7 +144,8 @@ class CrashTest : public ::testing::Test {
TEST_F(CrashTest, ResponseStream) {
auto server = CreateServerAndClient("response");
- gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(5)));
+ gpr_sleep_until(
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(5)));
KillClient();
server->Shutdown();
GPR_ASSERT(HadOneResponseStream());
@@ -154,7 +154,8 @@ TEST_F(CrashTest, ResponseStream) {
TEST_F(CrashTest, BidiStream) {
auto server = CreateServerAndClient("bidi");
- gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(5)));
+ gpr_sleep_until(
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(5)));
KillClient();
server->Shutdown();
GPR_ASSERT(HadOneBidiStream());
diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc
index 0b43dfd106..58e8ba394d 100644
--- a/test/cpp/end2end/thread_stress_test.cc
+++ b/test/cpp/end2end/thread_stress_test.cc
@@ -38,12 +38,12 @@
#include "test/core/util/test_config.h"
#include "test/cpp/util/echo_duplicate.grpc.pb.h"
#include "test/cpp/util/echo.grpc.pb.h"
-#include "src/cpp/server/thread_pool.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
+#include <grpc++/fixed_size_thread_pool.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
@@ -96,14 +96,14 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
}
while (!context->IsCancelled()) {
gpr_sleep_until(gpr_time_add(
- gpr_now(),
+ gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_micros(request->param().client_cancel_after_us())));
}
return Status::CANCELLED;
} else if (request->has_param() &&
request->param().server_cancel_after_us()) {
gpr_sleep_until(gpr_time_add(
- gpr_now(),
+ gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_micros(request->param().server_cancel_after_us())));
return Status::CANCELLED;
} else {
@@ -206,7 +206,7 @@ class End2endTest : public ::testing::Test {
const int kMaxMessageSize_;
TestServiceImpl service_;
TestServiceImplDupPkg dup_pkg_service_;
- ThreadPool thread_pool_;
+ FixedSizeThreadPool thread_pool_;
};
static void SendRpc(grpc::cpp::test::util::TestService::Stub* stub,
diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc
index 65ce2e9c2a..96149c5e75 100644
--- a/test/cpp/interop/client.cc
+++ b/test/cpp/interop/client.cc
@@ -64,6 +64,7 @@ DEFINE_string(test_case, "large_unary",
"ping_pong : full-duplex streaming; "
"cancel_after_begin : cancel stream after starting it; "
"cancel_after_first_response: cancel on first response; "
+ "timeout_on_sleeping_server: deadline exceeds on stream; "
"service_account_creds : large_unary with service_account auth; "
"compute_engine_creds: large_unary with compute engine auth; "
"jwt_token_creds: large_unary with JWT token auth; "
@@ -101,6 +102,8 @@ int main(int argc, char** argv) {
client.DoCancelAfterBegin();
} else if (FLAGS_test_case == "cancel_after_first_response") {
client.DoCancelAfterFirstResponse();
+ } else if (FLAGS_test_case == "timeout_on_sleeping_server") {
+ client.DoTimeoutOnSleepingServer();
} else if (FLAGS_test_case == "service_account_creds") {
grpc::string json_key = GetServiceAccountJsonKey();
client.DoServiceAccountCreds(json_key, FLAGS_oauth_scope);
@@ -119,6 +122,7 @@ int main(int argc, char** argv) {
client.DoPingPong();
client.DoCancelAfterBegin();
client.DoCancelAfterFirstResponse();
+ client.DoTimeoutOnSleepingServer();
// service_account_creds and jwt_token_creds can only run with ssl.
if (FLAGS_enable_ssl) {
grpc::string json_key = GetServiceAccountJsonKey();
@@ -132,6 +136,7 @@ int main(int argc, char** argv) {
"Unsupported test case %s. Valid options are all|empty_unary|"
"large_unary|client_streaming|server_streaming|half_duplex|ping_pong|"
"cancel_after_begin|cancel_after_first_response|"
+ "timeout_on_sleeping_server|"
"service_account_creds|compute_engine_creds|jwt_token_creds",
FLAGS_test_case.c_str());
ret = 1;
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index f08f90b139..d88eff759c 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -351,5 +351,26 @@ void InteropClient::DoCancelAfterFirstResponse() {
gpr_log(GPR_INFO, "Canceling pingpong streaming done.");
}
+void InteropClient::DoTimeoutOnSleepingServer() {
+ gpr_log(GPR_INFO, "Sending Ping Pong streaming rpc with a short deadline...");
+ std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
+
+ ClientContext context;
+ std::chrono::system_clock::time_point deadline =
+ std::chrono::system_clock::now() + std::chrono::milliseconds(1);
+ context.set_deadline(deadline);
+ std::unique_ptr<ClientReaderWriter<StreamingOutputCallRequest,
+ StreamingOutputCallResponse>>
+ stream(stub->FullDuplexCall(&context));
+
+ StreamingOutputCallRequest request;
+ request.mutable_payload()->set_body(grpc::string(27182, '\0'));
+ stream->Write(request);
+
+ Status s = stream->Finish();
+ GPR_ASSERT(s.error_code() == StatusCode::DEADLINE_EXCEEDED);
+ gpr_log(GPR_INFO, "Pingpong streaming timeout done.");
+}
+
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/interop/interop_client.h b/test/cpp/interop/interop_client.h
index d9c895dfd9..d02e583d94 100644
--- a/test/cpp/interop/interop_client.h
+++ b/test/cpp/interop/interop_client.h
@@ -59,6 +59,7 @@ class InteropClient {
void DoResponseStreamingWithSlowConsumer();
void DoCancelAfterBegin();
void DoCancelAfterFirstResponse();
+ void DoTimeoutOnSleepingServer();
// Auth tests.
// username is a string containing the user email
void DoJwtTokenCreds(const grpc::string& username);
diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc
index 22b8910a24..db87872cf5 100644
--- a/test/cpp/interop/server.cc
+++ b/test/cpp/interop/server.cc
@@ -149,14 +149,12 @@ class TestServiceImpl : public TestService::Service {
StreamingOutputCallResponse response;
bool write_success = true;
while (write_success && stream->Read(&request)) {
- response.mutable_payload()->set_type(request.payload().type());
- if (request.response_parameters_size() == 0) {
- return Status(grpc::StatusCode::INTERNAL,
- "Request does not have response parameters.");
+ if (request.response_parameters_size() != 0) {
+ response.mutable_payload()->set_type(request.payload().type());
+ response.mutable_payload()->set_body(
+ grpc::string(request.response_parameters(0).size(), '\0'));
+ write_success = stream->Write(response);
}
- response.mutable_payload()->set_body(
- grpc::string(request.response_parameters(0).size(), '\0'));
- write_success = stream->Write(response);
}
if (write_success) {
return Status::OK;
diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc
index c2e750dcf7..30a78ffddf 100644
--- a/test/cpp/interop/server_helper.cc
+++ b/test/cpp/interop/server_helper.cc
@@ -58,5 +58,18 @@ std::shared_ptr<ServerCredentials> CreateInteropServerCredentials() {
}
}
+InteropContextInspector::InteropContextInspector(
+ const ::grpc::ServerContext& context)
+ : context_(context) {}
+
+std::shared_ptr<const AuthContext> InteropContextInspector::GetAuthContext()
+ const {
+ return context_.auth_context();
+}
+
+bool InteropContextInspector::IsCancelled() const {
+ return context_.IsCancelled();
+}
+
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/interop/server_helper.h b/test/cpp/interop/server_helper.h
index f98e67bb67..ce977b4705 100644
--- a/test/cpp/interop/server_helper.h
+++ b/test/cpp/interop/server_helper.h
@@ -36,6 +36,7 @@
#include <memory>
+#include <grpc++/server_context.h>
#include <grpc++/server_credentials.h>
namespace grpc {
@@ -43,6 +44,18 @@ namespace testing {
std::shared_ptr<ServerCredentials> CreateInteropServerCredentials();
+class InteropContextInspector {
+ public:
+ InteropContextInspector(const ::grpc::ServerContext& context);
+
+ // Inspector methods, able to peek inside ServerContext, follow.
+ std::shared_ptr<const AuthContext> GetAuthContext() const;
+ bool IsCancelled() const;
+
+ private:
+ const ::grpc::ServerContext& context_;
+};
+
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc
index c8cc11e6ab..5597bcd549 100644
--- a/test/cpp/qps/driver.cc
+++ b/test/cpp/qps/driver.cc
@@ -185,7 +185,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
// Let everything warmup
gpr_log(GPR_INFO, "Warming up");
- gpr_timespec start = gpr_now();
+ gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME);
gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(warmup_seconds)));
// Start a run
diff --git a/test/cpp/qps/qps_test_openloop.cc b/test/cpp/qps/qps_openloop_test.cc
index 96a9b4504c..96a9b4504c 100644
--- a/test/cpp/qps/qps_test_openloop.cc
+++ b/test/cpp/qps/qps_openloop_test.cc
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index f5251e961b..be23204608 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -45,6 +45,7 @@
#include <grpc/support/host_port.h>
#include <grpc++/async_unary_call.h>
#include <grpc++/config.h>
+#include <grpc++/fixed_size_thread_pool.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
@@ -52,7 +53,6 @@
#include <grpc++/status.h>
#include <grpc++/stream.h>
#include <gtest/gtest.h>
-#include "src/cpp/server/thread_pool.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
#include "test/cpp/qps/server.h"
diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc
index bc00de9ced..d90ff2212b 100644
--- a/test/cpp/qps/server_sync.cc
+++ b/test/cpp/qps/server_sync.cc
@@ -40,13 +40,13 @@
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc++/config.h>
+#include <grpc++/fixed_size_thread_pool.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/server_credentials.h>
#include <grpc++/status.h>
#include <grpc++/stream.h>
-#include "src/cpp/server/thread_pool.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
#include "test/cpp/qps/server.h"
#include "test/cpp/qps/timer.h"
@@ -111,7 +111,7 @@ class SynchronousServer GRPC_FINAL : public grpc::testing::Server {
}
TestServiceImpl service_;
- ThreadPool thread_pool_;
+ FixedSizeThreadPool thread_pool_;
std::unique_ptr<grpc::Server> impl_;
};
diff --git a/test/cpp/qps/timer.cc b/test/cpp/qps/timer.cc
index d1b6bc1e55..07289f699b 100644
--- a/test/cpp/qps/timer.cc
+++ b/test/cpp/qps/timer.cc
@@ -41,7 +41,7 @@
Timer::Timer() : start_(Sample()) {}
double Timer::Now() {
- auto ts = gpr_now();
+ auto ts = gpr_now(GPR_CLOCK_REALTIME);
return ts.tv_sec + 1e-9 * ts.tv_nsec;
}
diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc
index 14a8b0b089..2bc0a56970 100644
--- a/test/cpp/qps/worker.cc
+++ b/test/cpp/qps/worker.cc
@@ -57,7 +57,8 @@ static void RunServer() {
QpsWorker worker(FLAGS_driver_port, FLAGS_server_port);
while (!got_sigint) {
- gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(5)));
+ gpr_sleep_until(
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(5)));
}
}
diff --git a/test/cpp/server/thread_pool_test.cc b/test/cpp/server/fixed_size_thread_pool_test.cc
index 824d785316..d62f4e8132 100644
--- a/test/cpp/server/thread_pool_test.cc
+++ b/test/cpp/server/fixed_size_thread_pool_test.cc
@@ -35,17 +35,17 @@
#include <functional>
#include <mutex>
-#include "src/cpp/server/thread_pool.h"
+#include <grpc++/fixed_size_thread_pool.h>
#include <gtest/gtest.h>
namespace grpc {
-class ThreadPoolTest : public ::testing::Test {
+class FixedSizeThreadPoolTest : public ::testing::Test {
public:
- ThreadPoolTest() : thread_pool_(4) {}
+ FixedSizeThreadPoolTest() : thread_pool_(4) {}
protected:
- ThreadPool thread_pool_;
+ FixedSizeThreadPool thread_pool_;
};
void Callback(std::mutex* mu, std::condition_variable* cv, bool* done) {
@@ -54,7 +54,7 @@ void Callback(std::mutex* mu, std::condition_variable* cv, bool* done) {
cv->notify_all();
}
-TEST_F(ThreadPoolTest, ScheduleCallback) {
+TEST_F(FixedSizeThreadPoolTest, ScheduleCallback) {
std::mutex mu;
std::condition_variable cv;
bool done = false;
diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc
index 6cf86ea89b..00bb821ae6 100644
--- a/test/cpp/util/cli_call_test.cc
+++ b/test/cpp/util/cli_call_test.cc
@@ -34,12 +34,12 @@
#include "test/core/util/test_config.h"
#include "test/cpp/util/cli_call.h"
#include "test/cpp/util/echo.grpc.pb.h"
-#include "src/cpp/server/thread_pool.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
+#include <grpc++/fixed_size_thread_pool.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
@@ -102,7 +102,7 @@ class CliCallTest : public ::testing::Test {
std::unique_ptr<Server> server_;
std::ostringstream server_address_;
TestServiceImpl service_;
- ThreadPool thread_pool_;
+ FixedSizeThreadPool thread_pool_;
};
// Send a rpc with a normal stub and then a CliCall. Verify they match.
diff --git a/test/cpp/util/messages.proto b/test/cpp/util/messages.proto
index 062f66c091..3708972b90 100644
--- a/test/cpp/util/messages.proto
+++ b/test/cpp/util/messages.proto
@@ -37,6 +37,7 @@ message RequestParams {
optional int32 client_cancel_after_us = 2;
optional int32 server_cancel_after_us = 3;
optional bool echo_metadata = 4;
+ optional bool check_auth_context = 5;
}
message EchoRequest {
@@ -46,6 +47,7 @@ message EchoRequest {
message ResponseParams {
optional int64 request_deadline = 1;
+ optional string host = 2;
}
message EchoResponse {
diff --git a/tools/buildgen/generate_projects.py b/tools/buildgen/generate_projects.py
new file mode 100755
index 0000000000..5de06354d1
--- /dev/null
+++ b/tools/buildgen/generate_projects.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python2.7
+
+# 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.
+
+import glob
+import os
+import sys
+import tempfile
+sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..', 'run_tests'))
+
+assert sys.argv[1:], 'run generate_projects.sh instead of this directly'
+
+import jobset
+
+os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '..', '..'))
+json = sys.argv[1:]
+
+test = {} if 'TEST' in os.environ else None
+
+plugins = sorted(glob.glob('tools/buildgen/plugins/*.py'))
+
+jobs = []
+for root, dirs, files in os.walk('templates'):
+ for f in files:
+ if os.path.splitext(f)[1] == '.template':
+ out_dir = '.' + root[len('templates'):]
+ out = out_dir + '/' + os.path.splitext(f)[0]
+ if not os.path.exists(out_dir):
+ os.makedirs(out_dir)
+ cmd = ['tools/buildgen/mako_renderer.py']
+ for plugin in plugins:
+ cmd.append('-p')
+ cmd.append(plugin)
+ for js in json:
+ cmd.append('-d')
+ cmd.append(js)
+ cmd.append('-o')
+ if test is None:
+ cmd.append(out)
+ else:
+ tf = tempfile.mkstemp()
+ test[out] = tf[1]
+ os.close(tf[0])
+ cmd.append(test[out])
+ cmd.append(root + '/' + f)
+ jobs.append(jobset.JobSpec(cmd, shortname=out))
+
+jobset.run(jobs)
+
+if test is not None:
+ for s, g in test.iteritems():
+ assert(0 == os.system('diff %s %s' % (s, g)))
+ os.unlink(g)
diff --git a/tools/buildgen/generate_projects.sh b/tools/buildgen/generate_projects.sh
index 5399867746..32fc90fef5 100755
--- a/tools/buildgen/generate_projects.sh
+++ b/tools/buildgen/generate_projects.sh
@@ -45,32 +45,6 @@ fi
. tools/buildgen/generate_build_additions.sh
-global_plugins=`find ./tools/buildgen/plugins -name '*.py' |
- sort | grep -v __init__ | awk ' { printf "-p %s ", $0 } '`
-
-for dir in . ; do
- local_plugins=`find $dir/templates -name '*.py' |
- sort | grep -v __init__ | awk ' { printf "-p %s ", $0 } '`
-
- plugins="$global_plugins $local_plugins"
-
- find -L $dir/templates -type f -and -name *.template | while read file ; do
- out=${dir}/${file#$dir/templates/} # strip templates dir prefix
- out=${out%.*} # strip template extension
- echo "generating file: $out"
- json_files="build.json $gen_build_files"
- data=`for i in $json_files ; do echo $i ; done | awk ' { printf "-d %s ", $0 } '`
- if [ "x$TEST" = "xtrue" ] ; then
- actual_out=$out
- out=`mktemp /tmp/gentXXXXXX`
- fi
- mkdir -p `dirname $out` # make sure dest directory exist
- $mako_renderer $plugins $data -o $out $file
- if [ "x$TEST" = "xtrue" ] ; then
- diff -q $out $actual_out
- rm $out
- fi
- done
-done
+tools/buildgen/generate_projects.py build.json $gen_build_files
rm $gen_build_files
diff --git a/tools/distrib/python/submit.py b/tools/distrib/python/submit.py
index dd48f440ba..a3615b3640 100755
--- a/tools/distrib/python/submit.py
+++ b/tools/distrib/python/submit.py
@@ -66,6 +66,12 @@ try:
except:
pass
+# Build the Cython C files
+build_env = os.environ.copy()
+build_env['GRPC_PYTHON_BUILD_WITH_CYTHON'] = "1"
+cmd = ['python', 'setup.py', 'build_ext', '--inplace']
+subprocess.call(cmd, cwd=pkgdir, env=build_env)
+
# Make the push.
cmd = ['python', 'setup.py', 'sdist']
subprocess.call(cmd, cwd=pkgdir)
diff --git a/tools/dockerfile/grpc_java/Dockerfile b/tools/dockerfile/grpc_java/Dockerfile
index 15fce276ba..7b1fe56358 100644
--- a/tools/dockerfile/grpc_java/Dockerfile
+++ b/tools/dockerfile/grpc_java/Dockerfile
@@ -30,10 +30,8 @@
# Dockerfile for the gRPC Java dev image
FROM grpc/java_base
-RUN git clone --recursive --depth 1 https://github.com/grpc/grpc-java.git /var/local/git/grpc-java
-RUN cd /var/local/git/grpc-java/lib/netty && \
- mvn -pl codec-http2 -am -DskipTests install clean
-RUN cd /var/local/git/grpc-java && \
+RUN git clone --recursive --depth 1 https://github.com/grpc/grpc-java.git /var/local/git/grpc-java && \
+ cd /var/local/git/grpc-java && \
./gradlew :grpc-interop-testing:installDist -PskipCodegen=true
# Add a service_account directory containing the auth creds file
diff --git a/tools/dockerfile/grpc_java_android/Dockerfile b/tools/dockerfile/grpc_java_android/Dockerfile
index 2dc2202e9d..8df0707758 100644
--- a/tools/dockerfile/grpc_java_android/Dockerfile
+++ b/tools/dockerfile/grpc_java_android/Dockerfile
@@ -43,27 +43,20 @@ ENV PATH $PATH:$ANDROID_HOME/platform-tools
# Some old Docker versions consider '/' as HOME
ENV HOME /root
-# Update sdk for android 5.1 (API level 22)
-RUN echo y | android update sdk --all --filter platform-tools,build-tools-22.0.1,sys-img-armeabi-v7a-addon-google_apis-google-22,sys-img-armeabi-v7a-addon-google_apis-google-21,sys-img-armeabi-v7a-android-19,addon-google_apis-google-22,addon-google_apis-google-21,addon-google_apis-google-19,extra-android-m2repository,extra-google-m2repository --no-ui --force
+# Update sdk for android API level 19 (4.4), 21 (5.0), 22 (5.1).
+RUN echo y | android update sdk --all --filter platform-tools,build-tools-22.0.1,sys-img-armeabi-v7a-addon-google_apis-google-22,sys-img-armeabi-v7a-addon-google_apis-google-21,sys-img-armeabi-v7a-android-19,android-22,android-21,android-19,addon-google_apis-google-22,addon-google_apis-google-21,addon-google_apis-google-19,extra-android-m2repository,extra-google-m2repository --no-ui --force
-# Create an AVD with API level 22
-RUN echo no | android create avd --force -n avd-google-api-22 -t "Google Inc.:Google APIs:22" --abi google_apis/armeabi-v7a
-RUN echo no | android create avd --force -n avd-google-api-21 -t "Google Inc.:Google APIs:21" --abi google_apis/armeabi-v7a
-RUN echo no | android create avd --force -n avd-google-api-19 -t "Google Inc.:Google APIs:19" --abi default/armeabi-v7a
+# Create AVDs with API level 19,21,22
+RUN echo no | android create avd --force -n avd-google-api-22 -t "Google Inc.:Google APIs:22" --abi google_apis/armeabi-v7a && \
+ echo no | android create avd --force -n avd-google-api-21 -t "Google Inc.:Google APIs:21" --abi google_apis/armeabi-v7a && \
+ echo no | android create avd --force -n avd-google-api-19 -t "Google Inc.:Google APIs:19" --abi default/armeabi-v7a
# Pull gRPC Java and trigger download of needed Maven and Gradle artifacts.
RUN git clone --depth 1 https://github.com/grpc/grpc-java.git /var/local/git/grpc-java && \
cd /var/local/git/grpc-java && \
- ./gradlew grpc-core:install grpc-stub:install grpc-okhttp:install grpc-protobuf-nano:install && \
- rm -r "$(pwd)"
+ ./gradlew grpc-core:install grpc-stub:install grpc-okhttp:install grpc-protobuf-nano:install grpc-compiler:install
-# Pull gRPC Android integration test App
-RUN git clone --depth 1 https://github.com/madongfly/grpc-android-test.git /var/local/git/grpc-android-test
-
-# Config android sdk for gradle
-RUN cd /var/local/git/grpc-android-test && echo "sdk.dir=/usr/local/android-sdk-linux" > local.properties
-
-# Build apks to trigger download of needed Maven and Gradle artifacts.
-RUN cd /var/local/git/grpc-android-test && ./gradlew assembleDebug
-RUN cd /var/local/git/grpc-android-test && ./gradlew assembleDebugAndroidTest
+# Config android sdk for gradle and build apk to trigger download of needed Maven and Gradle artifacts.
+RUN cd /var/local/git/grpc-java/android-interop-testing && echo "sdk.dir=/usr/local/android-sdk-linux" > local.properties && \
+ ../gradlew assembleDebug
diff --git a/tools/dockerfile/grpc_java_android/README.md b/tools/dockerfile/grpc_java_android/README.md
index b4c9645e6a..5c897cd779 100644
--- a/tools/dockerfile/grpc_java_android/README.md
+++ b/tools/dockerfile/grpc_java_android/README.md
@@ -15,23 +15,23 @@ Usage
Start the emulator in a detached container, the argument is the name of the AVD you want to start:
```
-$ sudo docker run --name=grpc_android_test -d grpc/android /var/local/git/grpc-android-test/start-emulator.sh avd-api-22
+$ sudo docker run --name=grpc_android_test -d grpc/android /var/local/git/grpc-java/android-interop-testing/start-emulator.sh avd-google-api-22
```
You can use the following cammand to wait until the emulator is ready:
```
-$ sudo docker exec grpc_android_test /var/local/git/grpc-android-test/wait-for-emulator.sh
+$ sudo docker exec grpc_android_test /var/local/git/grpc-java/android-interop-testing/wait-for-emulator.sh
```
When you want to update the apk, run:
```
-$ sudo docker exec grpc_android_test /var/local/git/grpc-android-test/update-apk.sh
+$ sudo docker exec grpc_android_test bash -c "cd /var/local/git/grpc-java && git pull origin master && ./gradlew grpc-core:install grpc-stub:install grpc-okhttp:install grpc-protobuf-nano:install grpc-compiler:install && cd android-interop-testing && ../gradlew installDebug"
```
-It will pull the fresh code of gRpc Java and our integration test app from github, build and install it to the runing emulator (so you need to make sure there is a runing emulator).
+It pulls the fresh code of gRpc Java and our interop test app from github, build and install it to the runing emulator (so you need to make sure there is a runing emulator).
Trigger the integration test:
```
-$ sudo docker exec grpc_android_test /var/local/git/grpc-android-test/run-test.sh -e server_host <hostname or ip address> -e server_port 8030 -e server_host_override foo.test.google.fr -e use_tls true -e use_test_ca true
+$ sudo docker exec grpc_android_test adb -e shell am instrument -w -e server_host <hostname or ip address> -e server_port 8030 -e server_host_override foo.test.google.fr -e use_tls true -e use_test_ca true -e test_case all io.grpc.android.integrationtest/.TesterInstrumentation
```
You can also use the android/adb cammands to get more info, such as:
diff --git a/tools/dockerfile/grpc_java_base/Dockerfile b/tools/dockerfile/grpc_java_base/Dockerfile
index 55fbe94eaf..7bf79c8e41 100644
--- a/tools/dockerfile/grpc_java_base/Dockerfile
+++ b/tools/dockerfile/grpc_java_base/Dockerfile
@@ -44,20 +44,11 @@ RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true
&& \
apt-get clean && rm -r /var/cache/oracle-jdk8-installer/
-# Install maven
-RUN wget -O - http://mirror.olnevhost.net/pub/apache/maven/binaries/apache-maven-3.2.1-bin.tar.gz | \
- tar xz -C /var/local
-
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
-ENV M2_HOME /var/local/apache-maven-3.2.1
-ENV PATH $PATH:$JAVA_HOME/bin:$M2_HOME/bin
-ENV LD_LIBRARY_PATH /usr/local/lib
+ENV PATH $PATH:$JAVA_HOME/bin
-# Trigger download of as many Maven and Gradle artifacts as possible. We don't build grpc-java
-# because we don't want to install netty
+# Trigger download of as many Gradle artifacts as possible.
RUN git clone --recursive --depth 1 https://github.com/grpc/grpc-java.git && \
- cd grpc-java/lib/netty && \
- mvn -pl codec-http2 -am -DskipTests verify && \
- cd ../.. && \
- ./gradlew && \
+ cd grpc-java && \
+ ./gradlew build -PskipCodegen=true && \
rm -r "$(pwd)"
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index d782dc18f7..4bdd8babde 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -762,6 +762,8 @@ WARN_LOGFILE =
INPUT = include/grpc++/async_generic_service.h \
include/grpc++/async_unary_call.h \
+include/grpc++/auth_context.h \
+include/grpc++/auth_property_iterator.h \
include/grpc++/byte_buffer.h \
include/grpc++/channel_arguments.h \
include/grpc++/channel_interface.h \
@@ -771,6 +773,7 @@ include/grpc++/config.h \
include/grpc++/config_protobuf.h \
include/grpc++/create_channel.h \
include/grpc++/credentials.h \
+include/grpc++/fixed_size_thread_pool.h \
include/grpc++/generic_stub.h \
include/grpc++/impl/call.h \
include/grpc++/impl/client_unary_call.h \
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 575cd95753..1c73ca6294 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -762,6 +762,8 @@ WARN_LOGFILE =
INPUT = include/grpc++/async_generic_service.h \
include/grpc++/async_unary_call.h \
+include/grpc++/auth_context.h \
+include/grpc++/auth_property_iterator.h \
include/grpc++/byte_buffer.h \
include/grpc++/channel_arguments.h \
include/grpc++/channel_interface.h \
@@ -771,6 +773,7 @@ include/grpc++/config.h \
include/grpc++/config_protobuf.h \
include/grpc++/create_channel.h \
include/grpc++/credentials.h \
+include/grpc++/fixed_size_thread_pool.h \
include/grpc++/generic_stub.h \
include/grpc++/impl/call.h \
include/grpc++/impl/client_unary_call.h \
@@ -798,11 +801,15 @@ include/grpc++/stream.h \
include/grpc++/thread_pool_interface.h \
include/grpc++/time.h \
src/cpp/client/secure_credentials.h \
+src/cpp/common/secure_auth_context.h \
src/cpp/server/secure_server_credentials.h \
src/cpp/client/channel.h \
-src/cpp/server/thread_pool.h \
+src/cpp/common/create_auth_context.h \
src/cpp/client/secure_channel_arguments.cc \
src/cpp/client/secure_credentials.cc \
+src/cpp/common/auth_property_iterator.cc \
+src/cpp/common/secure_auth_context.cc \
+src/cpp/common/secure_create_auth_context.cc \
src/cpp/server/secure_server_credentials.cc \
src/cpp/client/channel.cc \
src/cpp/client/channel_arguments.cc \
@@ -818,12 +825,12 @@ src/cpp/common/rpc_method.cc \
src/cpp/proto/proto_utils.cc \
src/cpp/server/async_generic_service.cc \
src/cpp/server/create_default_thread_pool.cc \
+src/cpp/server/fixed_size_thread_pool.cc \
src/cpp/server/insecure_server_credentials.cc \
src/cpp/server/server.cc \
src/cpp/server/server_builder.cc \
src/cpp/server/server_context.cc \
src/cpp/server/server_credentials.cc \
-src/cpp/server/thread_pool.cc \
src/cpp/util/byte_buffer.cc \
src/cpp/util/slice.cc \
src/cpp/util/status.cc \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index e2701eca3a..a658f1af82 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -775,6 +775,7 @@ src/core/security/auth_filters.h \
src/core/security/base64.h \
src/core/security/credentials.h \
src/core/security/json_token.h \
+src/core/security/jwt_verifier.h \
src/core/security/secure_endpoint.h \
src/core/security/secure_transport_setup.h \
src/core/security/security_connector.h \
@@ -891,6 +892,7 @@ src/core/security/credentials_posix.c \
src/core/security/credentials_win32.c \
src/core/security/google_default_credentials.c \
src/core/security/json_token.c \
+src/core/security/jwt_verifier.c \
src/core/security/secure_endpoint.c \
src/core/security/secure_transport_setup.c \
src/core/security/security_connector.c \
@@ -983,6 +985,7 @@ src/core/surface/server.c \
src/core/surface/server_chttp2.c \
src/core/surface/server_create.c \
src/core/surface/surface_trace.c \
+src/core/surface/version.c \
src/core/transport/chttp2/alpn.c \
src/core/transport/chttp2/bin_encoder.c \
src/core/transport/chttp2/frame_data.c \
@@ -1042,6 +1045,7 @@ include/grpc/support/useful.h \
src/core/support/env.h \
src/core/support/file.h \
src/core/support/murmur_hash.h \
+src/core/support/stack_lockfree.h \
src/core/support/string.h \
src/core/support/string_win32.h \
src/core/support/thd_internal.h \
@@ -1068,6 +1072,7 @@ src/core/support/log_win32.c \
src/core/support/murmur_hash.c \
src/core/support/slice.c \
src/core/support/slice_buffer.c \
+src/core/support/stack_lockfree.c \
src/core/support/string.c \
src/core/support/string_posix.c \
src/core/support/string_win32.c \
diff --git a/tools/jenkins/docker_run_jenkins.sh b/tools/jenkins/docker_run_jenkins.sh
index 90107169ba..eb6c9144c6 100755
--- a/tools/jenkins/docker_run_jenkins.sh
+++ b/tools/jenkins/docker_run_jenkins.sh
@@ -42,4 +42,4 @@ cd /var/local/git/grpc
nvm use 0.12
rvm use ruby-2.1
tools/run_tests/prepare_travis.sh
-tools/run_tests/run_tests.py -t -c $config -l $language -x report.xml
+$arch tools/run_tests/run_tests.py -t -c $config -l $language -x report.xml
diff --git a/tools/jenkins/grpc_linuxbrew/Dockerfile b/tools/jenkins/grpc_linuxbrew/Dockerfile
new file mode 100644
index 0000000000..9b76e3cea0
--- /dev/null
+++ b/tools/jenkins/grpc_linuxbrew/Dockerfile
@@ -0,0 +1,62 @@
+# 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.
+
+# A work-in-progress Dockerfile that allows running gRPC homebrew
+# installations inside docker containers
+FROM debian:jessie
+
+# Core dependencies
+RUN apt-get update && apt-get install -y \
+ bzip2 curl git ruby wget
+
+# Install linuxbrew
+ENV PATH /home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:$PATH
+RUN git clone https://github.com/Homebrew/linuxbrew.git /home/linuxbrew/.linuxbrew
+RUN brew doctor || true
+
+# Python dependency
+RUN apt-get update && apt-get install -y python-dev
+RUN curl https://bootstrap.pypa.io/get-pip.py | python
+
+# NodeJS dependency
+RUN touch .profile
+RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
+RUN /bin/bash -l -c "nvm install 0.12"
+
+# Ruby dependency
+RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
+RUN /bin/bash -l -c "\curl -sSL https://get.rvm.io | bash -s stable"
+RUN /bin/bash -l -c "rvm install ruby-2.1"
+
+# PHP dependency
+RUN apt-get update && apt-get install -y php5 php5-dev phpunit unzip
+
+RUN /bin/bash -l -c "echo 'export PATH=/home/linuxbrew/.linuxbrew/bin:\$PATH' >> ~/.bashrc"
+
+CMD ["bash"]
diff --git a/tools/jenkins/run_distribution.sh b/tools/jenkins/run_distribution.sh
new file mode 100755
index 0000000000..10c41b4099
--- /dev/null
+++ b/tools/jenkins/run_distribution.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# 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.
+#
+# This script is invoked by Jenkins and triggers a test run of
+# linuxbrew installation of a selected language
+set -ex
+
+sha1=$(sha1sum tools/jenkins/grpc_linuxbrew/Dockerfile | cut -f1 -d\ )
+DOCKER_IMAGE_NAME=grpc_linuxbrew_$sha1
+
+docker build -t $DOCKER_IMAGE_NAME tools/jenkins/grpc_linuxbrew
+
+supported="python nodejs ruby php"
+
+if [ "$language" == "core" ]; then
+ command="curl -fsSL https://goo.gl/getgrpc | bash -"
+elif [[ "$supported" =~ "$language" ]]; then
+ command="curl -fsSL https://goo.gl/getgrpc | bash -s $language"
+else
+ echo "unsupported language $language"
+ exit 1
+fi
+
+docker run $DOCKER_IMAGE_NAME bash -l \
+ -c "nvm use 0.12; \
+ npm set unsafe-perm true; \
+ rvm use ruby-2.1; \
+ $command"
diff --git a/tools/jenkins/run_jenkins.sh b/tools/jenkins/run_jenkins.sh
index f2091e2423..8cb85cb12b 100755
--- a/tools/jenkins/run_jenkins.sh
+++ b/tools/jenkins/run_jenkins.sh
@@ -31,12 +31,24 @@
# This script is invoked by Jenkins and triggers a test run based on
# env variable settings.
#
+# Setting up rvm environment BEFORE we set -ex.
+[[ -s /etc/profile.d/rvm.sh ]] && . /etc/profile.d/rvm.sh
# To prevent cygwin bash complaining about empty lines ending with \r
# we set the igncr option. The option doesn't exist on Linux, so we fallback
# to just 'set -ex' there.
# NOTE: No empty lines should appear in this file before igncr is set!
set -ex -o igncr || set -ex
+# Grabbing the machine's architecture
+arch=`uname -m`
+
+case $platform in
+ i386)
+ arch="i386"
+ platform="linux"
+ ;;
+esac
+
if [ "$platform" == "linux" ]
then
echo "building $language on Linux"
@@ -51,11 +63,8 @@ then
# Make sure docker image has been built. Should be instantaneous if so.
docker build -t $DOCKER_IMAGE_NAME tools/jenkins/grpc_jenkins_slave
- if [ "$ghprbPullId" != "" ]
- then
- # if we are building a pull request, grab corresponding refs.
- FETCH_PULL_REQUEST_CMD="&& git fetch $GIT_URL refs/pull/$ghprbPullId/merge refs/pull/$ghprbPullId/head"
- fi
+ # Create a local branch so the child Docker script won't complain
+ git branch jenkins-docker
# Make sure the CID file is gone.
rm -f docker.cid
@@ -64,6 +73,7 @@ then
docker run \
-e "config=$config" \
-e "language=$language" \
+ -e "arch=$arch" \
-i \
-v "$git_root:/var/local/jenkins/grpc" \
--cidfile=docker.cid \
@@ -73,7 +83,8 @@ then
DOCKER_CID=`cat docker.cid`
docker kill $DOCKER_CID
docker cp $DOCKER_CID:/var/local/git/grpc/report.xml $git_root
- docker rm $DOCKER_CID
+ sleep 4
+ docker rm $DOCKER_CID || true
elif [ "$platform" == "windows" ]
then
@@ -86,7 +97,12 @@ then
/cygdrive/c/nuget/nuget.exe restore vsprojects/grpc.sln
/cygdrive/c/nuget/nuget.exe restore src/csharp/Grpc.sln
- python tools/run_tests/run_tests.py -t -l $language -x report.xml
+ python tools/run_tests/run_tests.py -t -l $language -x report.xml || true
+elif [ "$platform" == "macos" ]
+then
+ echo "building $language on MacOS"
+
+ ./tools/run_tests/run_tests.py -t -l $language -c $config -x report.xml || true
else
echo "Unknown platform $platform"
exit 1
diff --git a/tools/run_tests/build_python.sh b/tools/run_tests/build_python.sh
index d9b7644f44..ae0fb42241 100755
--- a/tools/run_tests/build_python.sh
+++ b/tools/run_tests/build_python.sh
@@ -34,9 +34,32 @@ set -ex
cd $(dirname $0)/../..
root=`pwd`
-rm -rf python2.7_virtual_environment
-virtualenv -p /usr/bin/python2.7 python2.7_virtual_environment
-source python2.7_virtual_environment/bin/activate
-pip install -r src/python/requirements.txt
-CFLAGS="-I$root/include -std=c89 -Werror" LDFLAGS=-L$root/libs/$CONFIG pip install src/python/src
-pip install src/python/interop
+
+make_virtualenv() {
+ virtualenv_name="python"$1"_virtual_environment"
+ if [ ! -d $virtualenv_name ]
+ then
+ # Build the entire virtual environment
+ virtualenv -p `which "python"$1` $virtualenv_name
+ source $virtualenv_name/bin/activate
+ pip install -r src/python/requirements.txt
+ CFLAGS="-I$root/include -std=c89" LDFLAGS=-L$root/libs/$CONFIG GRPC_PYTHON_BUILD_WITH_CYTHON=1 pip install src/python/src
+ pip install src/python/interop
+ else
+ source $virtualenv_name/bin/activate
+ # Uninstall and re-install the packages we care about. Don't use
+ # --force-reinstall or --ignore-installed to avoid propagating this
+ # unnecessarily to dependencies. Don't use --no-deps to avoid missing
+ # dependency upgrades.
+ (yes | pip uninstall grpcio) || true
+ (yes | pip uninstall interop) || true
+ (CFLAGS="-I$root/include -std=c89" LDFLAGS=-L$root/libs/$CONFIG GRPC_PYTHON_BUILD_WITH_CYTHON=1 pip install src/python/src) || (
+ # Fall back to rebuilding the entire environment
+ rm -rf $virtualenv_name
+ make_virtualenv $1
+ )
+ pip install src/python/interop
+ fi
+}
+
+make_virtualenv $1
diff --git a/tools/run_tests/build_ruby.sh b/tools/run_tests/build_ruby.sh
index de96413bc1..b6c4e32b7e 100755
--- a/tools/run_tests/build_ruby.sh
+++ b/tools/run_tests/build_ruby.sh
@@ -31,7 +31,7 @@
set -ex
-export CONFIG=${CONFIG:-opt}
+export GRPC_CONFIG=${CONFIG:-opt}
# change to grpc's ruby directory
cd $(dirname $0)/../../src/ruby
diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py
index 8694b8f6bd..46137f01f4 100755
--- a/tools/run_tests/jobset.py
+++ b/tools/run_tests/jobset.py
@@ -81,6 +81,7 @@ _CLEAR_LINE = '\x1b[2K'
_TAG_COLOR = {
'FAILED': 'red',
+ 'WARNING': 'yellow',
'TIMEOUT': 'red',
'PASSED': 'green',
'START': 'gray',
@@ -95,7 +96,7 @@ def message(tag, msg, explanatory_text=None, do_newline=False):
return
message.old_tag = tag
message.old_msg = msg
- if platform.system() == 'Windows':
+ if platform.system() == 'Windows' or not sys.stdout.isatty():
if explanatory_text:
print explanatory_text
print '%s: %s' % (tag, msg)
@@ -205,13 +206,14 @@ class Job(object):
do_newline=self._newline_on_success or self._travis)
if self._bin_hash:
update_cache.finished(self._spec.identity(), self._bin_hash)
- elif self._state == _RUNNING and time.time() - self._start > 300:
+ elif self._state == _RUNNING and time.time() - self._start > 600:
self._tempfile.seek(0)
stdout = self._tempfile.read()
+ filtered_stdout = filter(lambda x: x in string.printable, stdout.decode(errors='ignore'))
message('TIMEOUT', self._spec.shortname, stdout, do_newline=True)
self.kill()
if self._xml_test is not None:
- ET.SubElement(self._xml_test, 'system-out').text = stdout
+ ET.SubElement(self._xml_test, 'system-out').text = filtered_stdout
ET.SubElement(self._xml_test, 'error', message='Timeout')
return self._state
diff --git a/tools/run_tests/python_tests.json b/tools/run_tests/python_tests.json
index 6c969d765f..3d75d8de36 100755
--- a/tools/run_tests/python_tests.json
+++ b/tools/run_tests/python_tests.json
@@ -1,56 +1,122 @@
[
{
- "module": "grpc._adapter._c_test"
+ "module": "grpc._adapter._c_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc._adapter._low_test"
+ "module": "grpc._adapter._low_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc._adapter._intermediary_low_test"
+ "module": "grpc._adapter._intermediary_low_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc._adapter._links_test"
+ "module": "grpc._adapter._links_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc._adapter._lonely_rear_link_test"
+ "module": "grpc._adapter._lonely_rear_link_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc._adapter._blocking_invocation_inline_service_test"
+ "module": "grpc._adapter._blocking_invocation_inline_service_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc._adapter._event_invocation_synchronous_event_service_test"
+ "module": "grpc._adapter._event_invocation_synchronous_event_service_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc._adapter._future_invocation_asynchronous_event_service_test"
+ "module": "grpc._adapter._future_invocation_asynchronous_event_service_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc.early_adopter.implementations_test"
+ "module": "grpc._links._lonely_invocation_link_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc.framework.base.implementations_test"
+ "module": "grpc._links._transmission_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc.framework.face.blocking_invocation_inline_service_test"
+ "module": "grpc.early_adopter.implementations_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc.framework.face.event_invocation_synchronous_event_service_test"
+ "module": "grpc.framework.base.implementations_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc.framework.face.future_invocation_asynchronous_event_service_test"
+ "module": "grpc.framework.face.blocking_invocation_inline_service_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc.framework.foundation._later_test"
+ "module": "grpc.framework.face.event_invocation_synchronous_event_service_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "grpc.framework.foundation._logging_pool_test"
+ "module": "grpc.framework.face.future_invocation_asynchronous_event_service_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "interop._insecure_interop_test"
+ "module": "grpc.framework.foundation._later_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "module": "interop._secure_interop_test"
+ "module": "grpc.framework.foundation._logging_pool_test",
+ "pythonVersions": [
+ "2.7"
+ ]
},
{
- "file": "test/compiler/python_plugin_test.py"
+ "module": "interop._insecure_interop_test",
+ "pythonVersions": [
+ "2.7"
+ ]
+ },
+ {
+ "module": "interop._secure_interop_test",
+ "pythonVersions": [
+ "2.7"
+ ]
+ },
+ {
+ "file": "test/compiler/python_plugin_test.py",
+ "pythonVersions": [
+ "2.7"
+ ]
}
]
diff --git a/tools/run_tests/run_csharp.bat b/tools/run_tests/run_csharp.bat
index 17c622cc2d..c86136767c 100644
--- a/tools/run_tests/run_csharp.bat
+++ b/tools/run_tests/run_csharp.bat
@@ -5,7 +5,10 @@ setlocal
@rem enter this directory
cd /d %~dp0\..\..\src\csharp
-packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe -labels "%1/bin/Debug/%1.dll" || goto :error
+@rem set UUID variable to a random GUID, we will use it to put TestResults.xml to a dedicated directory, so that parallel test runs don't collide
+for /F %%i in ('powershell -Command "[guid]::NewGuid().ToString()"') do (set UUID=%%i)
+
+packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe -labels "%1/bin/Debug/%1.dll" -work test-results/%UUID% || goto :error
endlocal
diff --git a/tools/run_tests/run_python.sh b/tools/run_tests/run_python.sh
index cab08f9358..4959c0241c 100755
--- a/tools/run_tests/run_python.sh
+++ b/tools/run_tests/run_python.sh
@@ -36,5 +36,5 @@ cd $(dirname $0)/../..
root=`pwd`
export LD_LIBRARY_PATH=$root/libs/$CONFIG
export DYLD_LIBRARY_PATH=$root/libs/$CONFIG
-source python2.7_virtual_environment/bin/activate
-python2.7 -B $*
+source "python"$PYVER"_virtual_environment"/bin/activate
+"python"$PYVER -B $*
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index fd90613ad6..1f44fc34fa 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -189,27 +189,55 @@ class PythonLanguage(object):
def __init__(self):
with open('tools/run_tests/python_tests.json') as f:
self._tests = json.load(f)
+ self._build_python_versions = set([
+ python_version
+ for test in self._tests
+ for python_version in test['pythonVersions']])
+ self._has_python_versions = []
def test_specs(self, config, travis):
- modules = [config.job_spec(['tools/run_tests/run_python.sh', '-m',
- test['module']],
- None,
- environ=_FORCE_ENVIRON_FOR_WRAPPERS,
- shortname=test['module'])
- for test in self._tests if 'module' in test]
- files = [config.job_spec(['tools/run_tests/run_python.sh',
- test['file']],
- None,
- environ=_FORCE_ENVIRON_FOR_WRAPPERS,
- shortname=test['file'])
- for test in self._tests if 'file' in test]
- return files + modules
+ job_specifications = []
+ for test in self._tests:
+ command = None
+ short_name = None
+ if 'module' in test:
+ command = ['tools/run_tests/run_python.sh', '-m', test['module']]
+ short_name = test['module']
+ elif 'file' in test:
+ command = ['tools/run_tests/run_python.sh', test['file']]
+ short_name = test['file']
+ else:
+ raise ValueError('expected input to be a module or file to run '
+ 'unittests from')
+ for python_version in test['pythonVersions']:
+ if python_version in self._has_python_versions:
+ environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
+ environment['PYVER'] = python_version
+ job_specifications.append(config.job_spec(
+ command, None, environ=environment, shortname=short_name))
+ else:
+ jobset.message(
+ 'WARNING',
+ 'Could not find Python {}; skipping test'.format(python_version),
+ '{}\n'.format(command), do_newline=True)
+ return job_specifications
def make_targets(self):
return ['static_c', 'grpc_python_plugin', 'shared_c']
def build_steps(self):
- return [['tools/run_tests/build_python.sh']]
+ commands = []
+ for python_version in self._build_python_versions:
+ try:
+ with open(os.devnull, 'w') as output:
+ subprocess.check_call(['which', 'python' + python_version],
+ stdout=output, stderr=output)
+ commands.append(['tools/run_tests/build_python.sh', python_version])
+ self._has_python_versions.append(python_version)
+ except:
+ jobset.message('WARNING', 'Missing Python ' + python_version,
+ do_newline=True)
+ return commands
def supports_multi_config(self):
return False
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 6db1d43604..a92950e9e6 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -338,6 +338,18 @@
],
"headers": [],
"language": "c",
+ "name": "gpr_stack_lockfree_test",
+ "src": [
+ "test/core/support/stack_lockfree_test.c"
+ ]
+ },
+ {
+ "deps": [
+ "gpr",
+ "gpr_test_util"
+ ],
+ "headers": [],
+ "language": "c",
"name": "gpr_string_test",
"src": [
"test/core/support/string_test.c"
@@ -538,6 +550,20 @@
],
"headers": [],
"language": "c",
+ "name": "grpc_jwt_verifier_test",
+ "src": [
+ "test/core/security/jwt_verifier_test.c"
+ ]
+ },
+ {
+ "deps": [
+ "gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc_test_util"
+ ],
+ "headers": [],
+ "language": "c",
"name": "grpc_print_google_default_creds_token",
"src": [
"test/core/security/print_google_default_creds_token.c"
@@ -580,6 +606,20 @@
],
"headers": [],
"language": "c",
+ "name": "grpc_verify_jwt",
+ "src": [
+ "test/core/security/verify_jwt.c"
+ ]
+ },
+ {
+ "deps": [
+ "gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc_test_util"
+ ],
+ "headers": [],
+ "language": "c",
"name": "hpack_parser_test",
"src": [
"test/core/transport/chttp2/hpack_parser_test.c"
@@ -1031,6 +1071,19 @@
],
"headers": [],
"language": "c++",
+ "name": "auth_property_iterator_test",
+ "src": [
+ "test/cpp/common/auth_property_iterator_test.cc"
+ ]
+ },
+ {
+ "deps": [
+ "gpr",
+ "grpc",
+ "grpc++"
+ ],
+ "headers": [],
+ "language": "c++",
"name": "channel_arguments_test",
"src": [
"test/cpp/client/channel_arguments_test.cc"
@@ -1164,6 +1217,21 @@
"gpr_test_util",
"grpc",
"grpc++",
+ "grpc_test_util"
+ ],
+ "headers": [],
+ "language": "c++",
+ "name": "fixed_size_thread_pool_test",
+ "src": [
+ "test/cpp/server/fixed_size_thread_pool_test.cc"
+ ]
+ },
+ {
+ "deps": [
+ "gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc++",
"grpc++_test_util",
"grpc_test_util"
],
@@ -1409,9 +1477,9 @@
],
"headers": [],
"language": "c++",
- "name": "qps_test",
+ "name": "qps_openloop_test",
"src": [
- "test/cpp/qps/qps_test.cc"
+ "test/cpp/qps/qps_openloop_test.cc"
]
},
{
@@ -1427,9 +1495,9 @@
],
"headers": [],
"language": "c++",
- "name": "qps_test_openloop",
+ "name": "qps_test",
"src": [
- "test/cpp/qps/qps_test_openloop.cc"
+ "test/cpp/qps/qps_test.cc"
]
},
{
@@ -1458,6 +1526,19 @@
{
"deps": [
"gpr",
+ "grpc",
+ "grpc++"
+ ],
+ "headers": [],
+ "language": "c++",
+ "name": "secure_auth_context_test",
+ "src": [
+ "test/cpp/common/secure_auth_context_test.cc"
+ ]
+ },
+ {
+ "deps": [
+ "gpr",
"gpr_test_util",
"grpc",
"grpc++",
@@ -1542,21 +1623,6 @@
"gpr_test_util",
"grpc",
"grpc++",
- "grpc_test_util"
- ],
- "headers": [],
- "language": "c++",
- "name": "thread_pool_test",
- "src": [
- "test/cpp/server/thread_pool_test.cc"
- ]
- },
- {
- "deps": [
- "gpr",
- "gpr_test_util",
- "grpc",
- "grpc++",
"grpc++_test_util",
"grpc_test_util"
],
@@ -8567,6 +8633,7 @@
"src/core/support/env.h",
"src/core/support/file.h",
"src/core/support/murmur_hash.h",
+ "src/core/support/stack_lockfree.h",
"src/core/support/string.h",
"src/core/support/string_win32.h",
"src/core/support/thd_internal.h"
@@ -8628,6 +8695,8 @@
"src/core/support/murmur_hash.h",
"src/core/support/slice.c",
"src/core/support/slice_buffer.c",
+ "src/core/support/stack_lockfree.c",
+ "src/core/support/stack_lockfree.h",
"src/core/support/string.c",
"src/core/support/string.h",
"src/core/support/string_posix.c",
@@ -8743,6 +8812,7 @@
"src/core/security/base64.h",
"src/core/security/credentials.h",
"src/core/security/json_token.h",
+ "src/core/security/jwt_verifier.h",
"src/core/security/secure_endpoint.h",
"src/core/security/secure_transport_setup.h",
"src/core/security/security_connector.h",
@@ -8944,6 +9014,8 @@
"src/core/security/google_default_credentials.c",
"src/core/security/json_token.c",
"src/core/security/json_token.h",
+ "src/core/security/jwt_verifier.c",
+ "src/core/security/jwt_verifier.h",
"src/core/security/secure_endpoint.c",
"src/core/security/secure_endpoint.h",
"src/core/security/secure_transport_setup.c",
@@ -8981,6 +9053,7 @@
"src/core/surface/server_create.c",
"src/core/surface/surface_trace.c",
"src/core/surface/surface_trace.h",
+ "src/core/surface/version.c",
"src/core/transport/chttp2/alpn.c",
"src/core/transport/chttp2/alpn.h",
"src/core/transport/chttp2/bin_encoder.c",
@@ -9382,6 +9455,7 @@
"src/core/surface/server_create.c",
"src/core/surface/surface_trace.c",
"src/core/surface/surface_trace.h",
+ "src/core/surface/version.c",
"src/core/transport/chttp2/alpn.c",
"src/core/transport/chttp2/alpn.h",
"src/core/transport/chttp2/bin_encoder.c",
@@ -9461,6 +9535,8 @@
"headers": [
"include/grpc++/async_generic_service.h",
"include/grpc++/async_unary_call.h",
+ "include/grpc++/auth_context.h",
+ "include/grpc++/auth_property_iterator.h",
"include/grpc++/byte_buffer.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
@@ -9470,6 +9546,7 @@
"include/grpc++/config_protobuf.h",
"include/grpc++/create_channel.h",
"include/grpc++/credentials.h",
+ "include/grpc++/fixed_size_thread_pool.h",
"include/grpc++/generic_stub.h",
"include/grpc++/impl/call.h",
"include/grpc++/impl/client_unary_call.h",
@@ -9498,14 +9575,17 @@
"include/grpc++/time.h",
"src/cpp/client/channel.h",
"src/cpp/client/secure_credentials.h",
- "src/cpp/server/secure_server_credentials.h",
- "src/cpp/server/thread_pool.h"
+ "src/cpp/common/create_auth_context.h",
+ "src/cpp/common/secure_auth_context.h",
+ "src/cpp/server/secure_server_credentials.h"
],
"language": "c++",
"name": "grpc++",
"src": [
"include/grpc++/async_generic_service.h",
"include/grpc++/async_unary_call.h",
+ "include/grpc++/auth_context.h",
+ "include/grpc++/auth_property_iterator.h",
"include/grpc++/byte_buffer.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
@@ -9515,6 +9595,7 @@
"include/grpc++/config_protobuf.h",
"include/grpc++/create_channel.h",
"include/grpc++/credentials.h",
+ "include/grpc++/fixed_size_thread_pool.h",
"include/grpc++/generic_stub.h",
"include/grpc++/impl/call.h",
"include/grpc++/impl/client_unary_call.h",
@@ -9553,12 +9634,18 @@
"src/cpp/client/secure_channel_arguments.cc",
"src/cpp/client/secure_credentials.cc",
"src/cpp/client/secure_credentials.h",
+ "src/cpp/common/auth_property_iterator.cc",
"src/cpp/common/call.cc",
"src/cpp/common/completion_queue.cc",
+ "src/cpp/common/create_auth_context.h",
"src/cpp/common/rpc_method.cc",
+ "src/cpp/common/secure_auth_context.cc",
+ "src/cpp/common/secure_auth_context.h",
+ "src/cpp/common/secure_create_auth_context.cc",
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/async_generic_service.cc",
"src/cpp/server/create_default_thread_pool.cc",
+ "src/cpp/server/fixed_size_thread_pool.cc",
"src/cpp/server/insecure_server_credentials.cc",
"src/cpp/server/secure_server_credentials.cc",
"src/cpp/server/secure_server_credentials.h",
@@ -9566,8 +9653,6 @@
"src/cpp/server/server_builder.cc",
"src/cpp/server/server_context.cc",
"src/cpp/server/server_credentials.cc",
- "src/cpp/server/thread_pool.cc",
- "src/cpp/server/thread_pool.h",
"src/cpp/util/byte_buffer.cc",
"src/cpp/util/slice.cc",
"src/cpp/util/status.cc",
@@ -9624,6 +9709,8 @@
"headers": [
"include/grpc++/async_generic_service.h",
"include/grpc++/async_unary_call.h",
+ "include/grpc++/auth_context.h",
+ "include/grpc++/auth_property_iterator.h",
"include/grpc++/byte_buffer.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
@@ -9633,6 +9720,7 @@
"include/grpc++/config_protobuf.h",
"include/grpc++/create_channel.h",
"include/grpc++/credentials.h",
+ "include/grpc++/fixed_size_thread_pool.h",
"include/grpc++/generic_stub.h",
"include/grpc++/impl/call.h",
"include/grpc++/impl/client_unary_call.h",
@@ -9660,13 +9748,15 @@
"include/grpc++/thread_pool_interface.h",
"include/grpc++/time.h",
"src/cpp/client/channel.h",
- "src/cpp/server/thread_pool.h"
+ "src/cpp/common/create_auth_context.h"
],
"language": "c++",
"name": "grpc++_unsecure",
"src": [
"include/grpc++/async_generic_service.h",
"include/grpc++/async_unary_call.h",
+ "include/grpc++/auth_context.h",
+ "include/grpc++/auth_property_iterator.h",
"include/grpc++/byte_buffer.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
@@ -9676,6 +9766,7 @@
"include/grpc++/config_protobuf.h",
"include/grpc++/create_channel.h",
"include/grpc++/credentials.h",
+ "include/grpc++/fixed_size_thread_pool.h",
"include/grpc++/generic_stub.h",
"include/grpc++/impl/call.h",
"include/grpc++/impl/client_unary_call.h",
@@ -9713,17 +9804,18 @@
"src/cpp/client/internal_stub.cc",
"src/cpp/common/call.cc",
"src/cpp/common/completion_queue.cc",
+ "src/cpp/common/create_auth_context.h",
+ "src/cpp/common/insecure_create_auth_context.cc",
"src/cpp/common/rpc_method.cc",
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/async_generic_service.cc",
"src/cpp/server/create_default_thread_pool.cc",
+ "src/cpp/server/fixed_size_thread_pool.cc",
"src/cpp/server/insecure_server_credentials.cc",
"src/cpp/server/server.cc",
"src/cpp/server/server_builder.cc",
"src/cpp/server/server_context.cc",
"src/cpp/server/server_credentials.cc",
- "src/cpp/server/thread_pool.cc",
- "src/cpp/server/thread_pool.h",
"src/cpp/util/byte_buffer.cc",
"src/cpp/util/slice.cc",
"src/cpp/util/status.cc",
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index b46004d2b3..1d7e775971 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -197,6 +197,15 @@
{
"flaky": false,
"language": "c",
+ "name": "gpr_stack_lockfree_test",
+ "platforms": [
+ "windows",
+ "posix"
+ ]
+ },
+ {
+ "flaky": false,
+ "language": "c",
"name": "gpr_string_test",
"platforms": [
"windows",
@@ -314,6 +323,15 @@
{
"flaky": false,
"language": "c",
+ "name": "grpc_jwt_verifier_test",
+ "platforms": [
+ "windows",
+ "posix"
+ ]
+ },
+ {
+ "flaky": false,
+ "language": "c",
"name": "grpc_security_connector_test",
"platforms": [
"windows",
@@ -597,6 +615,15 @@
{
"flaky": false,
"language": "c++",
+ "name": "auth_property_iterator_test",
+ "platforms": [
+ "windows",
+ "posix"
+ ]
+ },
+ {
+ "flaky": false,
+ "language": "c++",
"name": "channel_arguments_test",
"platforms": [
"windows",
@@ -669,6 +696,15 @@
{
"flaky": false,
"language": "c++",
+ "name": "fixed_size_thread_pool_test",
+ "platforms": [
+ "windows",
+ "posix"
+ ]
+ },
+ {
+ "flaky": false,
+ "language": "c++",
"name": "generic_end2end_test",
"platforms": [
"windows",
@@ -696,7 +732,7 @@
{
"flaky": false,
"language": "c++",
- "name": "qps_test",
+ "name": "qps_openloop_test",
"platforms": [
"windows",
"posix"
@@ -705,7 +741,7 @@
{
"flaky": false,
"language": "c++",
- "name": "qps_test_openloop",
+ "name": "qps_test",
"platforms": [
"windows",
"posix"
@@ -714,7 +750,7 @@
{
"flaky": false,
"language": "c++",
- "name": "server_crash_test",
+ "name": "secure_auth_context_test",
"platforms": [
"windows",
"posix"
@@ -723,7 +759,7 @@
{
"flaky": false,
"language": "c++",
- "name": "status_test",
+ "name": "server_crash_test",
"platforms": [
"windows",
"posix"
@@ -732,7 +768,7 @@
{
"flaky": false,
"language": "c++",
- "name": "sync_streaming_ping_pong_test",
+ "name": "status_test",
"platforms": [
"windows",
"posix"
@@ -741,7 +777,7 @@
{
"flaky": false,
"language": "c++",
- "name": "sync_unary_ping_pong_test",
+ "name": "sync_streaming_ping_pong_test",
"platforms": [
"windows",
"posix"
@@ -750,7 +786,7 @@
{
"flaky": false,
"language": "c++",
- "name": "thread_pool_test",
+ "name": "sync_unary_ping_pong_test",
"platforms": [
"windows",
"posix"
diff --git a/vsprojects/Grpc.mak b/vsprojects/Grpc.mak
index dca13ef417..298678ae6f 100644
--- a/vsprojects/Grpc.mak
+++ b/vsprojects/Grpc.mak
@@ -51,13 +51,19 @@ LIBS=$(OPENSSL_LIBS) $(ZLIB_LIBS) $(GENERAL_LIBS) $(WINSOCK_LIBS)
all: buildtests
+tools:
+
+tools_c:
+
+tools_cxx:
+
$(OUT_DIR):
mkdir $(OUT_DIR)
build_libs: build_gpr build_gpr_test_util build_grpc build_grpc_test_util build_grpc_test_util_unsecure build_grpc_unsecure Debug\grpc_zookeeper.lib Debug\end2end_fixture_chttp2_fake_security.lib Debug\end2end_fixture_chttp2_fullstack.lib Debug\end2end_fixture_chttp2_simple_ssl_fullstack.lib Debug\end2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.lib Debug\end2end_fixture_chttp2_socket_pair.lib Debug\end2end_fixture_chttp2_socket_pair_one_byte_at_a_time.lib Debug\end2end_fixture_chttp2_socket_pair_with_grpc_trace.lib Debug\end2end_test_bad_hostname.lib Debug\end2end_test_cancel_after_accept.lib Debug\end2end_test_cancel_after_accept_and_writes_closed.lib Debug\end2end_test_cancel_after_invoke.lib Debug\end2end_test_cancel_before_invoke.lib Debug\end2end_test_cancel_in_a_vacuum.lib Debug\end2end_test_census_simple_request.lib Debug\end2end_test_disappearing_server.lib Debug\end2end_test_early_server_shutdown_finishes_inflight_calls.lib Debug\end2end_test_early_server_shutdown_finishes_tags.lib Debug\end2end_test_empty_batch.lib Debug\end2end_test_graceful_server_shutdown.lib Debug\end2end_test_invoke_large_request.lib Debug\end2end_test_max_concurrent_streams.lib Debug\end2end_test_max_message_length.lib Debug\end2end_test_no_op.lib Debug\end2end_test_ping_pong_streaming.lib Debug\end2end_test_registered_call.lib Debug\end2end_test_request_response_with_binary_metadata_and_payload.lib Debug\end2end_test_request_response_with_metadata_and_payload.lib Debug\end2end_test_request_response_with_payload.lib Debug\end2end_test_request_response_with_payload_and_call_creds.lib Debug\end2end_test_request_response_with_trailing_metadata_and_payload.lib Debug\end2end_test_request_with_flags.lib Debug\end2end_test_request_with_large_metadata.lib Debug\end2end_test_request_with_payload.lib Debug\end2end_test_server_finishes_request.lib Debug\end2end_test_simple_delayed_request.lib Debug\end2end_test_simple_request.lib Debug\end2end_test_simple_request_with_high_initial_sequence_number.lib Debug\end2end_certs.lib Debug\bad_client_test.lib
buildtests: buildtests_c buildtests_cxx
-buildtests_c: alarm_heap_test.exe alarm_list_test.exe alarm_test.exe alpn_test.exe bin_encoder_test.exe chttp2_status_conversion_test.exe chttp2_stream_encoder_test.exe chttp2_stream_map_test.exe fling_client.exe fling_server.exe gpr_cancellable_test.exe gpr_cmdline_test.exe gpr_env_test.exe gpr_file_test.exe gpr_histogram_test.exe gpr_host_port_test.exe gpr_log_test.exe gpr_slice_buffer_test.exe gpr_slice_test.exe gpr_string_test.exe gpr_sync_test.exe gpr_thd_test.exe gpr_time_test.exe gpr_tls_test.exe gpr_useful_test.exe grpc_auth_context_test.exe grpc_base64_test.exe grpc_byte_buffer_reader_test.exe grpc_channel_stack_test.exe grpc_completion_queue_test.exe grpc_credentials_test.exe grpc_json_token_test.exe grpc_security_connector_test.exe grpc_stream_op_test.exe hpack_parser_test.exe hpack_table_test.exe httpcli_format_request_test.exe httpcli_parser_test.exe json_rewrite.exe json_rewrite_test.exe json_test.exe lame_client_test.exe message_compress_test.exe multi_init_test.exe multiple_server_queues_test.exe murmur_hash_test.exe no_server_test.exe resolve_address_test.exe secure_endpoint_test.exe sockaddr_utils_test.exe time_averaged_stats_test.exe time_test.exe timeout_encoding_test.exe timers_test.exe transport_metadata_test.exe transport_security_test.exe uri_parser_test.exe chttp2_fake_security_bad_hostname_test.exe chttp2_fake_security_cancel_after_accept_test.exe chttp2_fake_security_cancel_after_accept_and_writes_closed_test.exe chttp2_fake_security_cancel_after_invoke_test.exe chttp2_fake_security_cancel_before_invoke_test.exe chttp2_fake_security_cancel_in_a_vacuum_test.exe chttp2_fake_security_census_simple_request_test.exe chttp2_fake_security_disappearing_server_test.exe chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_fake_security_early_server_shutdown_finishes_tags_test.exe chttp2_fake_security_empty_batch_test.exe chttp2_fake_security_graceful_server_shutdown_test.exe chttp2_fake_security_invoke_large_request_test.exe chttp2_fake_security_max_concurrent_streams_test.exe chttp2_fake_security_max_message_length_test.exe chttp2_fake_security_no_op_test.exe chttp2_fake_security_ping_pong_streaming_test.exe chttp2_fake_security_registered_call_test.exe chttp2_fake_security_request_response_with_binary_metadata_and_payload_test.exe chttp2_fake_security_request_response_with_metadata_and_payload_test.exe chttp2_fake_security_request_response_with_payload_test.exe chttp2_fake_security_request_response_with_payload_and_call_creds_test.exe chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test.exe chttp2_fake_security_request_with_flags_test.exe chttp2_fake_security_request_with_large_metadata_test.exe chttp2_fake_security_request_with_payload_test.exe chttp2_fake_security_server_finishes_request_test.exe chttp2_fake_security_simple_delayed_request_test.exe chttp2_fake_security_simple_request_test.exe chttp2_fake_security_simple_request_with_high_initial_sequence_number_test.exe chttp2_fullstack_bad_hostname_test.exe chttp2_fullstack_cancel_after_accept_test.exe chttp2_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_fullstack_cancel_after_invoke_test.exe chttp2_fullstack_cancel_before_invoke_test.exe chttp2_fullstack_cancel_in_a_vacuum_test.exe chttp2_fullstack_census_simple_request_test.exe chttp2_fullstack_disappearing_server_test.exe chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_fullstack_empty_batch_test.exe chttp2_fullstack_graceful_server_shutdown_test.exe chttp2_fullstack_invoke_large_request_test.exe chttp2_fullstack_max_concurrent_streams_test.exe chttp2_fullstack_max_message_length_test.exe chttp2_fullstack_no_op_test.exe chttp2_fullstack_ping_pong_streaming_test.exe chttp2_fullstack_registered_call_test.exe chttp2_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_fullstack_request_response_with_payload_test.exe chttp2_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_fullstack_request_with_flags_test.exe chttp2_fullstack_request_with_large_metadata_test.exe chttp2_fullstack_request_with_payload_test.exe chttp2_fullstack_server_finishes_request_test.exe chttp2_fullstack_simple_delayed_request_test.exe chttp2_fullstack_simple_request_test.exe chttp2_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_simple_ssl_fullstack_bad_hostname_test.exe chttp2_simple_ssl_fullstack_cancel_after_accept_test.exe chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_simple_ssl_fullstack_cancel_after_invoke_test.exe chttp2_simple_ssl_fullstack_cancel_before_invoke_test.exe chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test.exe chttp2_simple_ssl_fullstack_census_simple_request_test.exe chttp2_simple_ssl_fullstack_disappearing_server_test.exe chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_simple_ssl_fullstack_empty_batch_test.exe chttp2_simple_ssl_fullstack_graceful_server_shutdown_test.exe chttp2_simple_ssl_fullstack_invoke_large_request_test.exe chttp2_simple_ssl_fullstack_max_concurrent_streams_test.exe chttp2_simple_ssl_fullstack_max_message_length_test.exe chttp2_simple_ssl_fullstack_no_op_test.exe chttp2_simple_ssl_fullstack_ping_pong_streaming_test.exe chttp2_simple_ssl_fullstack_registered_call_test.exe chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_with_flags_test.exe chttp2_simple_ssl_fullstack_request_with_large_metadata_test.exe chttp2_simple_ssl_fullstack_request_with_payload_test.exe chttp2_simple_ssl_fullstack_server_finishes_request_test.exe chttp2_simple_ssl_fullstack_simple_delayed_request_test.exe chttp2_simple_ssl_fullstack_simple_request_test.exe chttp2_simple_ssl_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test.exe chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test.exe chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test.exe chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test.exe chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test.exe chttp2_simple_ssl_with_oauth2_fullstack_max_message_length_test.exe chttp2_simple_ssl_with_oauth2_fullstack_no_op_test.exe chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test.exe chttp2_simple_ssl_with_oauth2_fullstack_registered_call_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_with_flags_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_server_finishes_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_socket_pair_bad_hostname_test.exe chttp2_socket_pair_cancel_after_accept_test.exe chttp2_socket_pair_cancel_after_accept_and_writes_closed_test.exe chttp2_socket_pair_cancel_after_invoke_test.exe chttp2_socket_pair_cancel_before_invoke_test.exe chttp2_socket_pair_cancel_in_a_vacuum_test.exe chttp2_socket_pair_census_simple_request_test.exe chttp2_socket_pair_disappearing_server_test.exe chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_socket_pair_early_server_shutdown_finishes_tags_test.exe chttp2_socket_pair_empty_batch_test.exe chttp2_socket_pair_graceful_server_shutdown_test.exe chttp2_socket_pair_invoke_large_request_test.exe chttp2_socket_pair_max_concurrent_streams_test.exe chttp2_socket_pair_max_message_length_test.exe chttp2_socket_pair_no_op_test.exe chttp2_socket_pair_ping_pong_streaming_test.exe chttp2_socket_pair_registered_call_test.exe chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test.exe chttp2_socket_pair_request_response_with_metadata_and_payload_test.exe chttp2_socket_pair_request_response_with_payload_test.exe chttp2_socket_pair_request_response_with_payload_and_call_creds_test.exe chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test.exe chttp2_socket_pair_request_with_flags_test.exe chttp2_socket_pair_request_with_large_metadata_test.exe chttp2_socket_pair_request_with_payload_test.exe chttp2_socket_pair_server_finishes_request_test.exe chttp2_socket_pair_simple_delayed_request_test.exe chttp2_socket_pair_simple_request_test.exe chttp2_socket_pair_simple_request_with_high_initial_sequence_number_test.exe chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test.exe chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test.exe chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test.exe chttp2_socket_pair_one_byte_at_a_time_empty_batch_test.exe chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test.exe chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test.exe chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test.exe chttp2_socket_pair_one_byte_at_a_time_max_message_length_test.exe chttp2_socket_pair_one_byte_at_a_time_no_op_test.exe chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test.exe chttp2_socket_pair_one_byte_at_a_time_registered_call_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_and_call_creds_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_flags_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_server_finishes_request_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_test.exe chttp2_socket_pair_with_grpc_trace_bad_hostname_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_accept_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_accept_and_writes_closed_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_invoke_test.exe chttp2_socket_pair_with_grpc_trace_cancel_before_invoke_test.exe chttp2_socket_pair_with_grpc_trace_cancel_in_a_vacuum_test.exe chttp2_socket_pair_with_grpc_trace_census_simple_request_test.exe chttp2_socket_pair_with_grpc_trace_disappearing_server_test.exe chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_tags_test.exe chttp2_socket_pair_with_grpc_trace_empty_batch_test.exe chttp2_socket_pair_with_grpc_trace_graceful_server_shutdown_test.exe chttp2_socket_pair_with_grpc_trace_invoke_large_request_test.exe chttp2_socket_pair_with_grpc_trace_max_concurrent_streams_test.exe chttp2_socket_pair_with_grpc_trace_max_message_length_test.exe chttp2_socket_pair_with_grpc_trace_no_op_test.exe chttp2_socket_pair_with_grpc_trace_ping_pong_streaming_test.exe chttp2_socket_pair_with_grpc_trace_registered_call_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_binary_metadata_and_payload_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_metadata_and_payload_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_payload_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_payload_and_call_creds_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_trailing_metadata_and_payload_test.exe chttp2_socket_pair_with_grpc_trace_request_with_flags_test.exe chttp2_socket_pair_with_grpc_trace_request_with_large_metadata_test.exe chttp2_socket_pair_with_grpc_trace_request_with_payload_test.exe chttp2_socket_pair_with_grpc_trace_server_finishes_request_test.exe chttp2_socket_pair_with_grpc_trace_simple_delayed_request_test.exe chttp2_socket_pair_with_grpc_trace_simple_request_test.exe chttp2_socket_pair_with_grpc_trace_simple_request_with_high_initial_sequence_number_test.exe chttp2_fullstack_bad_hostname_unsecure_test.exe chttp2_fullstack_cancel_after_accept_unsecure_test.exe chttp2_fullstack_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_fullstack_cancel_after_invoke_unsecure_test.exe chttp2_fullstack_cancel_before_invoke_unsecure_test.exe chttp2_fullstack_cancel_in_a_vacuum_unsecure_test.exe chttp2_fullstack_census_simple_request_unsecure_test.exe chttp2_fullstack_disappearing_server_unsecure_test.exe chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_fullstack_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_fullstack_empty_batch_unsecure_test.exe chttp2_fullstack_graceful_server_shutdown_unsecure_test.exe chttp2_fullstack_invoke_large_request_unsecure_test.exe chttp2_fullstack_max_concurrent_streams_unsecure_test.exe chttp2_fullstack_max_message_length_unsecure_test.exe chttp2_fullstack_no_op_unsecure_test.exe chttp2_fullstack_ping_pong_streaming_unsecure_test.exe chttp2_fullstack_registered_call_unsecure_test.exe chttp2_fullstack_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_response_with_payload_unsecure_test.exe chttp2_fullstack_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_with_flags_unsecure_test.exe chttp2_fullstack_request_with_large_metadata_unsecure_test.exe chttp2_fullstack_request_with_payload_unsecure_test.exe chttp2_fullstack_server_finishes_request_unsecure_test.exe chttp2_fullstack_simple_delayed_request_unsecure_test.exe chttp2_fullstack_simple_request_unsecure_test.exe chttp2_fullstack_simple_request_with_high_initial_sequence_number_unsecure_test.exe chttp2_socket_pair_bad_hostname_unsecure_test.exe chttp2_socket_pair_cancel_after_accept_unsecure_test.exe chttp2_socket_pair_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_socket_pair_cancel_after_invoke_unsecure_test.exe chttp2_socket_pair_cancel_before_invoke_unsecure_test.exe chttp2_socket_pair_cancel_in_a_vacuum_unsecure_test.exe chttp2_socket_pair_census_simple_request_unsecure_test.exe chttp2_socket_pair_disappearing_server_unsecure_test.exe chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_socket_pair_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_socket_pair_empty_batch_unsecure_test.exe chttp2_socket_pair_graceful_server_shutdown_unsecure_test.exe chttp2_socket_pair_invoke_large_request_unsecure_test.exe chttp2_socket_pair_max_concurrent_streams_unsecure_test.exe chttp2_socket_pair_max_message_length_unsecure_test.exe chttp2_socket_pair_no_op_unsecure_test.exe chttp2_socket_pair_ping_pong_streaming_unsecure_test.exe chttp2_socket_pair_registered_call_unsecure_test.exe chttp2_socket_pair_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_with_flags_unsecure_test.exe chttp2_socket_pair_request_with_large_metadata_unsecure_test.exe chttp2_socket_pair_request_with_payload_unsecure_test.exe chttp2_socket_pair_server_finishes_request_unsecure_test.exe chttp2_socket_pair_simple_delayed_request_unsecure_test.exe chttp2_socket_pair_simple_request_unsecure_test.exe chttp2_socket_pair_simple_request_with_high_initial_sequence_number_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_bad_hostname_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_census_simple_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_disappearing_server_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_empty_batch_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_max_message_length_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_no_op_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_registered_call_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_flags_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_server_finishes_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_bad_hostname_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_accept_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_invoke_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_cancel_before_invoke_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_cancel_in_a_vacuum_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_census_simple_request_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_disappearing_server_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_empty_batch_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_graceful_server_shutdown_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_invoke_large_request_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_max_concurrent_streams_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_max_message_length_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_no_op_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_ping_pong_streaming_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_registered_call_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_payload_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_with_flags_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_with_large_metadata_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_with_payload_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_server_finishes_request_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_simple_delayed_request_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_simple_request_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_simple_request_with_high_initial_sequence_number_unsecure_test.exe connection_prefix_bad_client_test.exe initial_settings_frame_bad_client_test.exe
+buildtests_c: alarm_heap_test.exe alarm_list_test.exe alarm_test.exe alpn_test.exe bin_encoder_test.exe chttp2_status_conversion_test.exe chttp2_stream_encoder_test.exe chttp2_stream_map_test.exe fling_client.exe fling_server.exe gpr_cancellable_test.exe gpr_cmdline_test.exe gpr_env_test.exe gpr_file_test.exe gpr_histogram_test.exe gpr_host_port_test.exe gpr_log_test.exe gpr_slice_buffer_test.exe gpr_slice_test.exe gpr_stack_lockfree_test.exe gpr_string_test.exe gpr_sync_test.exe gpr_thd_test.exe gpr_time_test.exe gpr_tls_test.exe gpr_useful_test.exe grpc_auth_context_test.exe grpc_base64_test.exe grpc_byte_buffer_reader_test.exe grpc_channel_stack_test.exe grpc_completion_queue_test.exe grpc_credentials_test.exe grpc_json_token_test.exe grpc_jwt_verifier_test.exe grpc_security_connector_test.exe grpc_stream_op_test.exe hpack_parser_test.exe hpack_table_test.exe httpcli_format_request_test.exe httpcli_parser_test.exe json_rewrite.exe json_rewrite_test.exe json_test.exe lame_client_test.exe message_compress_test.exe multi_init_test.exe multiple_server_queues_test.exe murmur_hash_test.exe no_server_test.exe resolve_address_test.exe secure_endpoint_test.exe sockaddr_utils_test.exe time_averaged_stats_test.exe time_test.exe timeout_encoding_test.exe timers_test.exe transport_metadata_test.exe transport_security_test.exe uri_parser_test.exe chttp2_fake_security_bad_hostname_test.exe chttp2_fake_security_cancel_after_accept_test.exe chttp2_fake_security_cancel_after_accept_and_writes_closed_test.exe chttp2_fake_security_cancel_after_invoke_test.exe chttp2_fake_security_cancel_before_invoke_test.exe chttp2_fake_security_cancel_in_a_vacuum_test.exe chttp2_fake_security_census_simple_request_test.exe chttp2_fake_security_disappearing_server_test.exe chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_fake_security_early_server_shutdown_finishes_tags_test.exe chttp2_fake_security_empty_batch_test.exe chttp2_fake_security_graceful_server_shutdown_test.exe chttp2_fake_security_invoke_large_request_test.exe chttp2_fake_security_max_concurrent_streams_test.exe chttp2_fake_security_max_message_length_test.exe chttp2_fake_security_no_op_test.exe chttp2_fake_security_ping_pong_streaming_test.exe chttp2_fake_security_registered_call_test.exe chttp2_fake_security_request_response_with_binary_metadata_and_payload_test.exe chttp2_fake_security_request_response_with_metadata_and_payload_test.exe chttp2_fake_security_request_response_with_payload_test.exe chttp2_fake_security_request_response_with_payload_and_call_creds_test.exe chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test.exe chttp2_fake_security_request_with_flags_test.exe chttp2_fake_security_request_with_large_metadata_test.exe chttp2_fake_security_request_with_payload_test.exe chttp2_fake_security_server_finishes_request_test.exe chttp2_fake_security_simple_delayed_request_test.exe chttp2_fake_security_simple_request_test.exe chttp2_fake_security_simple_request_with_high_initial_sequence_number_test.exe chttp2_fullstack_bad_hostname_test.exe chttp2_fullstack_cancel_after_accept_test.exe chttp2_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_fullstack_cancel_after_invoke_test.exe chttp2_fullstack_cancel_before_invoke_test.exe chttp2_fullstack_cancel_in_a_vacuum_test.exe chttp2_fullstack_census_simple_request_test.exe chttp2_fullstack_disappearing_server_test.exe chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_fullstack_empty_batch_test.exe chttp2_fullstack_graceful_server_shutdown_test.exe chttp2_fullstack_invoke_large_request_test.exe chttp2_fullstack_max_concurrent_streams_test.exe chttp2_fullstack_max_message_length_test.exe chttp2_fullstack_no_op_test.exe chttp2_fullstack_ping_pong_streaming_test.exe chttp2_fullstack_registered_call_test.exe chttp2_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_fullstack_request_response_with_payload_test.exe chttp2_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_fullstack_request_with_flags_test.exe chttp2_fullstack_request_with_large_metadata_test.exe chttp2_fullstack_request_with_payload_test.exe chttp2_fullstack_server_finishes_request_test.exe chttp2_fullstack_simple_delayed_request_test.exe chttp2_fullstack_simple_request_test.exe chttp2_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_simple_ssl_fullstack_bad_hostname_test.exe chttp2_simple_ssl_fullstack_cancel_after_accept_test.exe chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_simple_ssl_fullstack_cancel_after_invoke_test.exe chttp2_simple_ssl_fullstack_cancel_before_invoke_test.exe chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test.exe chttp2_simple_ssl_fullstack_census_simple_request_test.exe chttp2_simple_ssl_fullstack_disappearing_server_test.exe chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_simple_ssl_fullstack_empty_batch_test.exe chttp2_simple_ssl_fullstack_graceful_server_shutdown_test.exe chttp2_simple_ssl_fullstack_invoke_large_request_test.exe chttp2_simple_ssl_fullstack_max_concurrent_streams_test.exe chttp2_simple_ssl_fullstack_max_message_length_test.exe chttp2_simple_ssl_fullstack_no_op_test.exe chttp2_simple_ssl_fullstack_ping_pong_streaming_test.exe chttp2_simple_ssl_fullstack_registered_call_test.exe chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_with_flags_test.exe chttp2_simple_ssl_fullstack_request_with_large_metadata_test.exe chttp2_simple_ssl_fullstack_request_with_payload_test.exe chttp2_simple_ssl_fullstack_server_finishes_request_test.exe chttp2_simple_ssl_fullstack_simple_delayed_request_test.exe chttp2_simple_ssl_fullstack_simple_request_test.exe chttp2_simple_ssl_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test.exe chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test.exe chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test.exe chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test.exe chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test.exe chttp2_simple_ssl_with_oauth2_fullstack_max_message_length_test.exe chttp2_simple_ssl_with_oauth2_fullstack_no_op_test.exe chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test.exe chttp2_simple_ssl_with_oauth2_fullstack_registered_call_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_with_flags_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_server_finishes_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_socket_pair_bad_hostname_test.exe chttp2_socket_pair_cancel_after_accept_test.exe chttp2_socket_pair_cancel_after_accept_and_writes_closed_test.exe chttp2_socket_pair_cancel_after_invoke_test.exe chttp2_socket_pair_cancel_before_invoke_test.exe chttp2_socket_pair_cancel_in_a_vacuum_test.exe chttp2_socket_pair_census_simple_request_test.exe chttp2_socket_pair_disappearing_server_test.exe chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_socket_pair_early_server_shutdown_finishes_tags_test.exe chttp2_socket_pair_empty_batch_test.exe chttp2_socket_pair_graceful_server_shutdown_test.exe chttp2_socket_pair_invoke_large_request_test.exe chttp2_socket_pair_max_concurrent_streams_test.exe chttp2_socket_pair_max_message_length_test.exe chttp2_socket_pair_no_op_test.exe chttp2_socket_pair_ping_pong_streaming_test.exe chttp2_socket_pair_registered_call_test.exe chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test.exe chttp2_socket_pair_request_response_with_metadata_and_payload_test.exe chttp2_socket_pair_request_response_with_payload_test.exe chttp2_socket_pair_request_response_with_payload_and_call_creds_test.exe chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test.exe chttp2_socket_pair_request_with_flags_test.exe chttp2_socket_pair_request_with_large_metadata_test.exe chttp2_socket_pair_request_with_payload_test.exe chttp2_socket_pair_server_finishes_request_test.exe chttp2_socket_pair_simple_delayed_request_test.exe chttp2_socket_pair_simple_request_test.exe chttp2_socket_pair_simple_request_with_high_initial_sequence_number_test.exe chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test.exe chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test.exe chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test.exe chttp2_socket_pair_one_byte_at_a_time_empty_batch_test.exe chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test.exe chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test.exe chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test.exe chttp2_socket_pair_one_byte_at_a_time_max_message_length_test.exe chttp2_socket_pair_one_byte_at_a_time_no_op_test.exe chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test.exe chttp2_socket_pair_one_byte_at_a_time_registered_call_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_and_call_creds_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_flags_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_server_finishes_request_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_test.exe chttp2_socket_pair_with_grpc_trace_bad_hostname_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_accept_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_accept_and_writes_closed_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_invoke_test.exe chttp2_socket_pair_with_grpc_trace_cancel_before_invoke_test.exe chttp2_socket_pair_with_grpc_trace_cancel_in_a_vacuum_test.exe chttp2_socket_pair_with_grpc_trace_census_simple_request_test.exe chttp2_socket_pair_with_grpc_trace_disappearing_server_test.exe chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_tags_test.exe chttp2_socket_pair_with_grpc_trace_empty_batch_test.exe chttp2_socket_pair_with_grpc_trace_graceful_server_shutdown_test.exe chttp2_socket_pair_with_grpc_trace_invoke_large_request_test.exe chttp2_socket_pair_with_grpc_trace_max_concurrent_streams_test.exe chttp2_socket_pair_with_grpc_trace_max_message_length_test.exe chttp2_socket_pair_with_grpc_trace_no_op_test.exe chttp2_socket_pair_with_grpc_trace_ping_pong_streaming_test.exe chttp2_socket_pair_with_grpc_trace_registered_call_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_binary_metadata_and_payload_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_metadata_and_payload_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_payload_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_payload_and_call_creds_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_trailing_metadata_and_payload_test.exe chttp2_socket_pair_with_grpc_trace_request_with_flags_test.exe chttp2_socket_pair_with_grpc_trace_request_with_large_metadata_test.exe chttp2_socket_pair_with_grpc_trace_request_with_payload_test.exe chttp2_socket_pair_with_grpc_trace_server_finishes_request_test.exe chttp2_socket_pair_with_grpc_trace_simple_delayed_request_test.exe chttp2_socket_pair_with_grpc_trace_simple_request_test.exe chttp2_socket_pair_with_grpc_trace_simple_request_with_high_initial_sequence_number_test.exe chttp2_fullstack_bad_hostname_unsecure_test.exe chttp2_fullstack_cancel_after_accept_unsecure_test.exe chttp2_fullstack_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_fullstack_cancel_after_invoke_unsecure_test.exe chttp2_fullstack_cancel_before_invoke_unsecure_test.exe chttp2_fullstack_cancel_in_a_vacuum_unsecure_test.exe chttp2_fullstack_census_simple_request_unsecure_test.exe chttp2_fullstack_disappearing_server_unsecure_test.exe chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_fullstack_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_fullstack_empty_batch_unsecure_test.exe chttp2_fullstack_graceful_server_shutdown_unsecure_test.exe chttp2_fullstack_invoke_large_request_unsecure_test.exe chttp2_fullstack_max_concurrent_streams_unsecure_test.exe chttp2_fullstack_max_message_length_unsecure_test.exe chttp2_fullstack_no_op_unsecure_test.exe chttp2_fullstack_ping_pong_streaming_unsecure_test.exe chttp2_fullstack_registered_call_unsecure_test.exe chttp2_fullstack_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_response_with_payload_unsecure_test.exe chttp2_fullstack_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_with_flags_unsecure_test.exe chttp2_fullstack_request_with_large_metadata_unsecure_test.exe chttp2_fullstack_request_with_payload_unsecure_test.exe chttp2_fullstack_server_finishes_request_unsecure_test.exe chttp2_fullstack_simple_delayed_request_unsecure_test.exe chttp2_fullstack_simple_request_unsecure_test.exe chttp2_fullstack_simple_request_with_high_initial_sequence_number_unsecure_test.exe chttp2_socket_pair_bad_hostname_unsecure_test.exe chttp2_socket_pair_cancel_after_accept_unsecure_test.exe chttp2_socket_pair_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_socket_pair_cancel_after_invoke_unsecure_test.exe chttp2_socket_pair_cancel_before_invoke_unsecure_test.exe chttp2_socket_pair_cancel_in_a_vacuum_unsecure_test.exe chttp2_socket_pair_census_simple_request_unsecure_test.exe chttp2_socket_pair_disappearing_server_unsecure_test.exe chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_socket_pair_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_socket_pair_empty_batch_unsecure_test.exe chttp2_socket_pair_graceful_server_shutdown_unsecure_test.exe chttp2_socket_pair_invoke_large_request_unsecure_test.exe chttp2_socket_pair_max_concurrent_streams_unsecure_test.exe chttp2_socket_pair_max_message_length_unsecure_test.exe chttp2_socket_pair_no_op_unsecure_test.exe chttp2_socket_pair_ping_pong_streaming_unsecure_test.exe chttp2_socket_pair_registered_call_unsecure_test.exe chttp2_socket_pair_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_with_flags_unsecure_test.exe chttp2_socket_pair_request_with_large_metadata_unsecure_test.exe chttp2_socket_pair_request_with_payload_unsecure_test.exe chttp2_socket_pair_server_finishes_request_unsecure_test.exe chttp2_socket_pair_simple_delayed_request_unsecure_test.exe chttp2_socket_pair_simple_request_unsecure_test.exe chttp2_socket_pair_simple_request_with_high_initial_sequence_number_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_bad_hostname_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_census_simple_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_disappearing_server_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_empty_batch_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_max_message_length_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_no_op_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_registered_call_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_flags_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_server_finishes_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_bad_hostname_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_accept_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_cancel_after_invoke_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_cancel_before_invoke_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_cancel_in_a_vacuum_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_census_simple_request_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_disappearing_server_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_empty_batch_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_graceful_server_shutdown_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_invoke_large_request_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_max_concurrent_streams_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_max_message_length_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_no_op_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_ping_pong_streaming_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_registered_call_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_payload_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_with_flags_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_with_large_metadata_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_request_with_payload_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_server_finishes_request_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_simple_delayed_request_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_simple_request_unsecure_test.exe chttp2_socket_pair_with_grpc_trace_simple_request_with_high_initial_sequence_number_unsecure_test.exe connection_prefix_bad_client_test.exe initial_settings_frame_bad_client_test.exe
echo All tests built.
buildtests_cxx: interop_client.exe interop_server.exe
@@ -203,6 +209,13 @@ gpr_slice_test.exe: build_libs $(OUT_DIR)
gpr_slice_test: gpr_slice_test.exe
echo Running gpr_slice_test
$(OUT_DIR)\gpr_slice_test.exe
+gpr_stack_lockfree_test.exe: build_libs $(OUT_DIR)
+ echo Building gpr_stack_lockfree_test
+ $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\support\stack_lockfree_test.c
+ $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\gpr_stack_lockfree_test.exe" Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\stack_lockfree_test.obj
+gpr_stack_lockfree_test: gpr_stack_lockfree_test.exe
+ echo Running gpr_stack_lockfree_test
+ $(OUT_DIR)\gpr_stack_lockfree_test.exe
gpr_string_test.exe: build_libs $(OUT_DIR)
echo Building gpr_string_test
$(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\support\string_test.c
@@ -308,6 +321,13 @@ grpc_json_token_test.exe: build_libs $(OUT_DIR)
grpc_json_token_test: grpc_json_token_test.exe
echo Running grpc_json_token_test
$(OUT_DIR)\grpc_json_token_test.exe
+grpc_jwt_verifier_test.exe: build_libs $(OUT_DIR)
+ echo Building grpc_jwt_verifier_test
+ $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\security\jwt_verifier_test.c
+ $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\grpc_jwt_verifier_test.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\jwt_verifier_test.obj
+grpc_jwt_verifier_test: grpc_jwt_verifier_test.exe
+ echo Running grpc_jwt_verifier_test
+ $(OUT_DIR)\grpc_jwt_verifier_test.exe
grpc_print_google_default_creds_token.exe: build_libs $(OUT_DIR)
echo Building grpc_print_google_default_creds_token
$(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\security\print_google_default_creds_token.c
@@ -329,6 +349,13 @@ grpc_stream_op_test.exe: build_libs $(OUT_DIR)
grpc_stream_op_test: grpc_stream_op_test.exe
echo Running grpc_stream_op_test
$(OUT_DIR)\grpc_stream_op_test.exe
+grpc_verify_jwt.exe: build_libs $(OUT_DIR)
+ echo Building grpc_verify_jwt
+ $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\security\verify_jwt.c
+ $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\grpc_verify_jwt.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\verify_jwt.obj
+grpc_verify_jwt: grpc_verify_jwt.exe
+ echo Running grpc_verify_jwt
+ $(OUT_DIR)\grpc_verify_jwt.exe
hpack_parser_test.exe: build_libs $(OUT_DIR)
echo Building hpack_parser_test
$(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\transport\chttp2\hpack_parser_test.c
diff --git a/vsprojects/README.md b/vsprojects/README.md
index 14178daaa7..dade9e500e 100644
--- a/vsprojects/README.md
+++ b/vsprojects/README.md
@@ -12,7 +12,7 @@ download nuget.exe from the web and manually restore the NuGet packages.
```
> REM Run from this directory.
> REM No need to do this if you have NuGet visual studio extension.
-> nuget restore
+> nuget restore grpc.sln
```
After that, you can build the solution using one of these options:
diff --git a/vsprojects/gpr/gpr.vcxproj b/vsprojects/gpr/gpr.vcxproj
index 3e6bb2036e..32a08a2321 100644
--- a/vsprojects/gpr/gpr.vcxproj
+++ b/vsprojects/gpr/gpr.vcxproj
@@ -179,6 +179,7 @@
<ClInclude Include="..\..\src\core\support\env.h" />
<ClInclude Include="..\..\src\core\support\file.h" />
<ClInclude Include="..\..\src\core\support\murmur_hash.h" />
+ <ClInclude Include="..\..\src\core\support\stack_lockfree.h" />
<ClInclude Include="..\..\src\core\support\string.h" />
<ClInclude Include="..\..\src\core\support\string_win32.h" />
<ClInclude Include="..\..\src\core\support\thd_internal.h" />
@@ -230,6 +231,8 @@
</ClCompile>
<ClCompile Include="..\..\src\core\support\slice_buffer.c">
</ClCompile>
+ <ClCompile Include="..\..\src\core\support\stack_lockfree.c">
+ </ClCompile>
<ClCompile Include="..\..\src\core\support\string.c">
</ClCompile>
<ClCompile Include="..\..\src\core\support\string_posix.c">
diff --git a/vsprojects/gpr/gpr.vcxproj.filters b/vsprojects/gpr/gpr.vcxproj.filters
index a270902236..ace549fa45 100644
--- a/vsprojects/gpr/gpr.vcxproj.filters
+++ b/vsprojects/gpr/gpr.vcxproj.filters
@@ -70,6 +70,9 @@
<ClCompile Include="..\..\src\core\support\slice_buffer.c">
<Filter>src\core\support</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\core\support\stack_lockfree.c">
+ <Filter>src\core\support</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\core\support\string.c">
<Filter>src\core\support</Filter>
</ClCompile>
@@ -209,6 +212,9 @@
<ClInclude Include="..\..\src\core\support\murmur_hash.h">
<Filter>src\core\support</Filter>
</ClInclude>
+ <ClInclude Include="..\..\src\core\support\stack_lockfree.h">
+ <Filter>src\core\support</Filter>
+ </ClInclude>
<ClInclude Include="..\..\src\core\support\string.h">
<Filter>src\core\support</Filter>
</ClInclude>
diff --git a/vsprojects/grpc++/grpc++.vcxproj b/vsprojects/grpc++/grpc++.vcxproj
index f69d50ffb8..2d13bf046b 100644
--- a/vsprojects/grpc++/grpc++.vcxproj
+++ b/vsprojects/grpc++/grpc++.vcxproj
@@ -148,6 +148,8 @@
<ItemGroup>
<ClInclude Include="..\..\include\grpc++\async_generic_service.h" />
<ClInclude Include="..\..\include\grpc++\async_unary_call.h" />
+ <ClInclude Include="..\..\include\grpc++\auth_context.h" />
+ <ClInclude Include="..\..\include\grpc++\auth_property_iterator.h" />
<ClInclude Include="..\..\include\grpc++\byte_buffer.h" />
<ClInclude Include="..\..\include\grpc++\channel_arguments.h" />
<ClInclude Include="..\..\include\grpc++\channel_interface.h" />
@@ -157,6 +159,7 @@
<ClInclude Include="..\..\include\grpc++\config_protobuf.h" />
<ClInclude Include="..\..\include\grpc++\create_channel.h" />
<ClInclude Include="..\..\include\grpc++\credentials.h" />
+ <ClInclude Include="..\..\include\grpc++\fixed_size_thread_pool.h" />
<ClInclude Include="..\..\include\grpc++\generic_stub.h" />
<ClInclude Include="..\..\include\grpc++\impl\call.h" />
<ClInclude Include="..\..\include\grpc++\impl\client_unary_call.h" />
@@ -186,15 +189,22 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\cpp\client\secure_credentials.h" />
+ <ClInclude Include="..\..\src\cpp\common\secure_auth_context.h" />
<ClInclude Include="..\..\src\cpp\server\secure_server_credentials.h" />
<ClInclude Include="..\..\src\cpp\client\channel.h" />
- <ClInclude Include="..\..\src\cpp\server\thread_pool.h" />
+ <ClInclude Include="..\..\src\cpp\common\create_auth_context.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\cpp\client\secure_channel_arguments.cc">
</ClCompile>
<ClCompile Include="..\..\src\cpp\client\secure_credentials.cc">
</ClCompile>
+ <ClCompile Include="..\..\src\cpp\common\auth_property_iterator.cc">
+ </ClCompile>
+ <ClCompile Include="..\..\src\cpp\common\secure_auth_context.cc">
+ </ClCompile>
+ <ClCompile Include="..\..\src\cpp\common\secure_create_auth_context.cc">
+ </ClCompile>
<ClCompile Include="..\..\src\cpp\server\secure_server_credentials.cc">
</ClCompile>
<ClCompile Include="..\..\src\cpp\client\channel.cc">
@@ -225,6 +235,8 @@
</ClCompile>
<ClCompile Include="..\..\src\cpp\server\create_default_thread_pool.cc">
</ClCompile>
+ <ClCompile Include="..\..\src\cpp\server\fixed_size_thread_pool.cc">
+ </ClCompile>
<ClCompile Include="..\..\src\cpp\server\insecure_server_credentials.cc">
</ClCompile>
<ClCompile Include="..\..\src\cpp\server\server.cc">
@@ -235,8 +247,6 @@
</ClCompile>
<ClCompile Include="..\..\src\cpp\server\server_credentials.cc">
</ClCompile>
- <ClCompile Include="..\..\src\cpp\server\thread_pool.cc">
- </ClCompile>
<ClCompile Include="..\..\src\cpp\util\byte_buffer.cc">
</ClCompile>
<ClCompile Include="..\..\src\cpp\util\slice.cc">
diff --git a/vsprojects/grpc++/grpc++.vcxproj.filters b/vsprojects/grpc++/grpc++.vcxproj.filters
index aa4b50e33f..c5d8db57ae 100644
--- a/vsprojects/grpc++/grpc++.vcxproj.filters
+++ b/vsprojects/grpc++/grpc++.vcxproj.filters
@@ -7,6 +7,15 @@
<ClCompile Include="..\..\src\cpp\client\secure_credentials.cc">
<Filter>src\cpp\client</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\cpp\common\auth_property_iterator.cc">
+ <Filter>src\cpp\common</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\cpp\common\secure_auth_context.cc">
+ <Filter>src\cpp\common</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\cpp\common\secure_create_auth_context.cc">
+ <Filter>src\cpp\common</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\cpp\server\secure_server_credentials.cc">
<Filter>src\cpp\server</Filter>
</ClCompile>
@@ -52,6 +61,9 @@
<ClCompile Include="..\..\src\cpp\server\create_default_thread_pool.cc">
<Filter>src\cpp\server</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\cpp\server\fixed_size_thread_pool.cc">
+ <Filter>src\cpp\server</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\cpp\server\insecure_server_credentials.cc">
<Filter>src\cpp\server</Filter>
</ClCompile>
@@ -67,9 +79,6 @@
<ClCompile Include="..\..\src\cpp\server\server_credentials.cc">
<Filter>src\cpp\server</Filter>
</ClCompile>
- <ClCompile Include="..\..\src\cpp\server\thread_pool.cc">
- <Filter>src\cpp\server</Filter>
- </ClCompile>
<ClCompile Include="..\..\src\cpp\util\byte_buffer.cc">
<Filter>src\cpp\util</Filter>
</ClCompile>
@@ -90,6 +99,12 @@
<ClInclude Include="..\..\include\grpc++\async_unary_call.h">
<Filter>include\grpc++</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\grpc++\auth_context.h">
+ <Filter>include\grpc++</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\grpc++\auth_property_iterator.h">
+ <Filter>include\grpc++</Filter>
+ </ClInclude>
<ClInclude Include="..\..\include\grpc++\byte_buffer.h">
<Filter>include\grpc++</Filter>
</ClInclude>
@@ -117,6 +132,9 @@
<ClInclude Include="..\..\include\grpc++\credentials.h">
<Filter>include\grpc++</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\grpc++\fixed_size_thread_pool.h">
+ <Filter>include\grpc++</Filter>
+ </ClInclude>
<ClInclude Include="..\..\include\grpc++\generic_stub.h">
<Filter>include\grpc++</Filter>
</ClInclude>
@@ -200,14 +218,17 @@
<ClInclude Include="..\..\src\cpp\client\secure_credentials.h">
<Filter>src\cpp\client</Filter>
</ClInclude>
+ <ClInclude Include="..\..\src\cpp\common\secure_auth_context.h">
+ <Filter>src\cpp\common</Filter>
+ </ClInclude>
<ClInclude Include="..\..\src\cpp\server\secure_server_credentials.h">
<Filter>src\cpp\server</Filter>
</ClInclude>
<ClInclude Include="..\..\src\cpp\client\channel.h">
<Filter>src\cpp\client</Filter>
</ClInclude>
- <ClInclude Include="..\..\src\cpp\server\thread_pool.h">
- <Filter>src\cpp\server</Filter>
+ <ClInclude Include="..\..\src\cpp\common\create_auth_context.h">
+ <Filter>src\cpp\common</Filter>
</ClInclude>
</ItemGroup>
diff --git a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj
index 639f904cce..f03715b353 100644
--- a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj
+++ b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj
@@ -148,6 +148,8 @@
<ItemGroup>
<ClInclude Include="..\..\include\grpc++\async_generic_service.h" />
<ClInclude Include="..\..\include\grpc++\async_unary_call.h" />
+ <ClInclude Include="..\..\include\grpc++\auth_context.h" />
+ <ClInclude Include="..\..\include\grpc++\auth_property_iterator.h" />
<ClInclude Include="..\..\include\grpc++\byte_buffer.h" />
<ClInclude Include="..\..\include\grpc++\channel_arguments.h" />
<ClInclude Include="..\..\include\grpc++\channel_interface.h" />
@@ -157,6 +159,7 @@
<ClInclude Include="..\..\include\grpc++\config_protobuf.h" />
<ClInclude Include="..\..\include\grpc++\create_channel.h" />
<ClInclude Include="..\..\include\grpc++\credentials.h" />
+ <ClInclude Include="..\..\include\grpc++\fixed_size_thread_pool.h" />
<ClInclude Include="..\..\include\grpc++\generic_stub.h" />
<ClInclude Include="..\..\include\grpc++\impl\call.h" />
<ClInclude Include="..\..\include\grpc++\impl\client_unary_call.h" />
@@ -186,9 +189,11 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\cpp\client\channel.h" />
- <ClInclude Include="..\..\src\cpp\server\thread_pool.h" />
+ <ClInclude Include="..\..\src\cpp\common\create_auth_context.h" />
</ItemGroup>
<ItemGroup>
+ <ClCompile Include="..\..\src\cpp\common\insecure_create_auth_context.cc">
+ </ClCompile>
<ClCompile Include="..\..\src\cpp\client\channel.cc">
</ClCompile>
<ClCompile Include="..\..\src\cpp\client\channel_arguments.cc">
@@ -217,6 +222,8 @@
</ClCompile>
<ClCompile Include="..\..\src\cpp\server\create_default_thread_pool.cc">
</ClCompile>
+ <ClCompile Include="..\..\src\cpp\server\fixed_size_thread_pool.cc">
+ </ClCompile>
<ClCompile Include="..\..\src\cpp\server\insecure_server_credentials.cc">
</ClCompile>
<ClCompile Include="..\..\src\cpp\server\server.cc">
@@ -227,8 +234,6 @@
</ClCompile>
<ClCompile Include="..\..\src\cpp\server\server_credentials.cc">
</ClCompile>
- <ClCompile Include="..\..\src\cpp\server\thread_pool.cc">
- </ClCompile>
<ClCompile Include="..\..\src\cpp\util\byte_buffer.cc">
</ClCompile>
<ClCompile Include="..\..\src\cpp\util\slice.cc">
diff --git a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
index 974dc3e27a..8f7f3bcd5e 100644
--- a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
+++ b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
+ <ClCompile Include="..\..\src\cpp\common\insecure_create_auth_context.cc">
+ <Filter>src\cpp\common</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\cpp\client\channel.cc">
<Filter>src\cpp\client</Filter>
</ClCompile>
@@ -43,6 +46,9 @@
<ClCompile Include="..\..\src\cpp\server\create_default_thread_pool.cc">
<Filter>src\cpp\server</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\cpp\server\fixed_size_thread_pool.cc">
+ <Filter>src\cpp\server</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\cpp\server\insecure_server_credentials.cc">
<Filter>src\cpp\server</Filter>
</ClCompile>
@@ -58,9 +64,6 @@
<ClCompile Include="..\..\src\cpp\server\server_credentials.cc">
<Filter>src\cpp\server</Filter>
</ClCompile>
- <ClCompile Include="..\..\src\cpp\server\thread_pool.cc">
- <Filter>src\cpp\server</Filter>
- </ClCompile>
<ClCompile Include="..\..\src\cpp\util\byte_buffer.cc">
<Filter>src\cpp\util</Filter>
</ClCompile>
@@ -81,6 +84,12 @@
<ClInclude Include="..\..\include\grpc++\async_unary_call.h">
<Filter>include\grpc++</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\grpc++\auth_context.h">
+ <Filter>include\grpc++</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\grpc++\auth_property_iterator.h">
+ <Filter>include\grpc++</Filter>
+ </ClInclude>
<ClInclude Include="..\..\include\grpc++\byte_buffer.h">
<Filter>include\grpc++</Filter>
</ClInclude>
@@ -108,6 +117,9 @@
<ClInclude Include="..\..\include\grpc++\credentials.h">
<Filter>include\grpc++</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\grpc++\fixed_size_thread_pool.h">
+ <Filter>include\grpc++</Filter>
+ </ClInclude>
<ClInclude Include="..\..\include\grpc++\generic_stub.h">
<Filter>include\grpc++</Filter>
</ClInclude>
@@ -191,8 +203,8 @@
<ClInclude Include="..\..\src\cpp\client\channel.h">
<Filter>src\cpp\client</Filter>
</ClInclude>
- <ClInclude Include="..\..\src\cpp\server\thread_pool.h">
- <Filter>src\cpp\server</Filter>
+ <ClInclude Include="..\..\src\cpp\common\create_auth_context.h">
+ <Filter>src\cpp\common</Filter>
</ClInclude>
</ItemGroup>
diff --git a/vsprojects/grpc/grpc.vcxproj b/vsprojects/grpc/grpc.vcxproj
index 14ddf95f81..16744b181b 100644
--- a/vsprojects/grpc/grpc.vcxproj
+++ b/vsprojects/grpc/grpc.vcxproj
@@ -164,6 +164,7 @@
<ClInclude Include="..\..\src\core\security\base64.h" />
<ClInclude Include="..\..\src\core\security\credentials.h" />
<ClInclude Include="..\..\src\core\security\json_token.h" />
+ <ClInclude Include="..\..\src\core\security\jwt_verifier.h" />
<ClInclude Include="..\..\src\core\security\secure_endpoint.h" />
<ClInclude Include="..\..\src\core\security\secure_transport_setup.h" />
<ClInclude Include="..\..\src\core\security\security_connector.h" />
@@ -294,6 +295,8 @@
</ClCompile>
<ClCompile Include="..\..\src\core\security\json_token.c">
</ClCompile>
+ <ClCompile Include="..\..\src\core\security\jwt_verifier.c">
+ </ClCompile>
<ClCompile Include="..\..\src\core\security\secure_endpoint.c">
</ClCompile>
<ClCompile Include="..\..\src\core\security\secure_transport_setup.c">
@@ -478,6 +481,8 @@
</ClCompile>
<ClCompile Include="..\..\src\core\surface\surface_trace.c">
</ClCompile>
+ <ClCompile Include="..\..\src\core\surface\version.c">
+ </ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\alpn.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\bin_encoder.c">
diff --git a/vsprojects/grpc/grpc.vcxproj.filters b/vsprojects/grpc/grpc.vcxproj.filters
index 591fe1bb03..de9f20521c 100644
--- a/vsprojects/grpc/grpc.vcxproj.filters
+++ b/vsprojects/grpc/grpc.vcxproj.filters
@@ -37,6 +37,9 @@
<ClCompile Include="..\..\src\core\security\json_token.c">
<Filter>src\core\security</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\core\security\jwt_verifier.c">
+ <Filter>src\core\security</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\core\security\secure_endpoint.c">
<Filter>src\core\security</Filter>
</ClCompile>
@@ -313,6 +316,9 @@
<ClCompile Include="..\..\src\core\surface\surface_trace.c">
<Filter>src\core\surface</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\core\surface\version.c">
+ <Filter>src\core\surface</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\alpn.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
@@ -446,6 +452,9 @@
<ClInclude Include="..\..\src\core\security\json_token.h">
<Filter>src\core\security</Filter>
</ClInclude>
+ <ClInclude Include="..\..\src\core\security\jwt_verifier.h">
+ <Filter>src\core\security</Filter>
+ </ClInclude>
<ClInclude Include="..\..\src\core\security\secure_endpoint.h">
<Filter>src\core\security</Filter>
</ClInclude>
diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj
index 4ead6f8d98..02c791f995 100644
--- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj
@@ -416,6 +416,8 @@
</ClCompile>
<ClCompile Include="..\..\src\core\surface\surface_trace.c">
</ClCompile>
+ <ClCompile Include="..\..\src\core\surface\version.c">
+ </ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\alpn.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\bin_encoder.c">
diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 45ca1f7c33..333a71f564 100644
--- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -247,6 +247,9 @@
<ClCompile Include="..\..\src\core\surface\surface_trace.c">
<Filter>src\core\surface</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\core\surface\version.c">
+ <Filter>src\core\surface</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\alpn.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
diff --git a/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec b/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec
index 211d747e2d..d2ac440dab 100644
--- a/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec
+++ b/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec
@@ -2,14 +2,14 @@
<package>
<metadata>
<id>grpc.native.csharp_ext</id>
- <version>0.9.1</version>
+ <version>0.10.0</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>http://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Native extension needed by gRPC C# library. This is not the package you are looking for, it is only meant to be used as a dependency.</description>
- <releaseNotes>Release of gRPC C core 0.9.1 libraries.</releaseNotes>
+ <releaseNotes>Release of gRPC C core 0.10.0 libraries.</releaseNotes>
<copyright>Copyright 2015</copyright>
<title>gRPC C# Native Extension</title>
<summary>Native library required by gRPC C#</summary>