aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/node_generator.cc15
-rw-r--r--src/compiler/ruby_generator_helpers-inl.h4
-rw-r--r--src/core/ext/census/base_resources.c71
-rw-r--r--src/core/ext/census/base_resources.h (renamed from src/python/grpcio/grpc/_cython/imports.generated.c)10
-rw-r--r--src/core/ext/census/gen/census.pb.c55
-rw-r--r--src/core/ext/census/gen/census.pb.h135
-rw-r--r--src/core/ext/census/grpc_filter.c18
-rw-r--r--src/core/ext/census/initialize.c20
-rw-r--r--src/core/ext/census/placeholders.c45
-rw-r--r--src/core/ext/census/resource.c312
-rw-r--r--src/core/ext/census/resource.h (renamed from src/python/grpcio/grpc/_cython/loader.c)39
-rw-r--r--src/core/ext/client_config/channel_connectivity.c2
-rw-r--r--src/core/ext/client_config/client_channel.c8
-rw-r--r--src/core/ext/client_config/lb_policy.h11
-rw-r--r--src/core/ext/client_config/subchannel.c25
-rw-r--r--src/core/ext/client_config/subchannel.h4
-rw-r--r--src/core/ext/client_config/subchannel_call_holder.c38
-rw-r--r--src/core/ext/lb_policy/grpclb/grpclb.c1042
-rw-r--r--src/core/ext/lb_policy/grpclb/grpclb.h (renamed from src/python/grpcio/grpc/_cython/imports.generated.h)22
-rw-r--r--src/core/ext/lb_policy/grpclb/load_balancer_api.c141
-rw-r--r--src/core/ext/lb_policy/grpclb/load_balancer_api.h36
-rw-r--r--src/core/ext/load_reporting/load_reporting.c60
-rw-r--r--src/core/ext/load_reporting/load_reporting.h61
-rw-r--r--src/core/ext/load_reporting/load_reporting_filter.c160
-rw-r--r--src/core/ext/load_reporting/load_reporting_filter.h1
-rw-r--r--src/core/ext/transport/chttp2/client/insecure/channel_create.c43
-rw-r--r--src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c2
-rw-r--r--src/core/ext/transport/chttp2/client/secure/secure_channel_create.c55
-rw-r--r--src/core/ext/transport/chttp2/server/insecure/server_chttp2.c74
-rw-r--r--src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c2
-rw-r--r--src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c70
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c38
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.h4
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_encoder.c6
-rw-r--r--src/core/ext/transport/chttp2/transport/parsing.c6
-rw-r--r--src/core/ext/transport/chttp2/transport/writing.c6
-rw-r--r--src/core/ext/transport/cronet/transport/cronet_transport.c1303
-rw-r--r--src/core/lib/channel/channel_args.h2
-rw-r--r--src/core/lib/channel/channel_stack.c29
-rw-r--r--src/core/lib/channel/channel_stack.h44
-rw-r--r--src/core/lib/channel/channel_stack_builder.h8
-rw-r--r--src/core/lib/channel/compress_filter.c10
-rw-r--r--src/core/lib/channel/connected_channel.c14
-rw-r--r--src/core/lib/channel/context.h11
-rw-r--r--src/core/lib/channel/handshaker.c203
-rw-r--r--src/core/lib/channel/handshaker.h150
-rw-r--r--src/core/lib/channel/http_client_filter.c9
-rw-r--r--src/core/lib/channel/http_server_filter.c9
-rw-r--r--src/core/lib/http/httpcli_security_connector.c8
-rw-r--r--src/core/lib/iomgr/error.h2
-rw-r--r--src/core/lib/iomgr/ev_epoll_linux.c1
-rw-r--r--src/core/lib/iomgr/ev_poll_posix.c30
-rw-r--r--src/core/lib/iomgr/network_status_tracker.c9
-rw-r--r--src/core/lib/iomgr/tcp_posix.c2
-rw-r--r--src/core/lib/iomgr/tcp_server.h4
-rw-r--r--src/core/lib/iomgr/tcp_server_posix.c38
-rw-r--r--src/core/lib/iomgr/tcp_server_windows.c3
-rw-r--r--src/core/lib/iomgr/udp_server.c40
-rw-r--r--src/core/lib/json/json_reader.c14
-rw-r--r--src/core/lib/security/context/security_context.h8
-rw-r--r--src/core/lib/security/transport/client_auth_filter.c9
-rw-r--r--src/core/lib/security/transport/handshake.c14
-rw-r--r--src/core/lib/security/transport/handshake.h7
-rw-r--r--src/core/lib/security/transport/secure_endpoint.c4
-rw-r--r--src/core/lib/security/transport/security_connector.c59
-rw-r--r--src/core/lib/security/transport/security_connector.h13
-rw-r--r--src/core/lib/security/transport/server_auth_filter.c10
-rw-r--r--src/core/lib/support/log.c19
-rw-r--r--src/core/lib/support/log_linux.c1
-rw-r--r--src/core/lib/support/slice.c11
-rw-r--r--src/core/lib/surface/call.c76
-rw-r--r--src/core/lib/surface/channel.h8
-rw-r--r--src/core/lib/surface/channel_init.h8
-rw-r--r--src/core/lib/surface/lame_client.c9
-rw-r--r--src/core/lib/surface/server.c18
-rw-r--r--src/core/lib/transport/byte_stream.h6
-rw-r--r--src/core/lib/transport/metadata.h8
-rw-r--r--src/core/lib/transport/metadata_batch.c3
-rw-r--r--src/core/lib/transport/metadata_batch.h12
-rw-r--r--src/core/lib/transport/static_metadata.c33
-rw-r--r--src/core/lib/transport/static_metadata.h189
-rw-r--r--src/core/lib/transport/timeout_encoding.c (renamed from src/core/ext/transport/chttp2/transport/timeout_encoding.c)6
-rw-r--r--src/core/lib/transport/timeout_encoding.h (renamed from src/core/ext/transport/chttp2/transport/timeout_encoding.h)14
-rw-r--r--src/core/lib/transport/transport.h12
-rw-r--r--src/core/plugin_registry/grpc_plugin_registry.c4
-rw-r--r--src/core/plugin_registry/grpc_unsecure_plugin_registry.c4
-rw-r--r--src/cpp/common/channel_filter.cc112
-rw-r--r--src/cpp/common/channel_filter.h386
-rw-r--r--src/cpp/ext/proto_server_reflection.h18
-rw-r--r--src/cpp/ext/reflection.pb.cc137
-rw-r--r--src/cpp/server/server_context.cc15
-rw-r--r--src/cpp/util/byte_buffer.cc25
-rw-r--r--src/csharp/.nuget/packages.config6
-rw-r--r--src/csharp/Grpc.Auth/Grpc.Auth.csproj31
-rw-r--r--src/csharp/Grpc.Auth/Grpc.Auth.nuspec2
-rw-r--r--src/csharp/Grpc.Auth/packages.config4
-rw-r--r--src/csharp/Grpc.Auth/project.json10
-rw-r--r--src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs2
-rw-r--r--src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj4
-rw-r--r--src/csharp/Grpc.Core.Tests/NUnitMain.cs2
-rw-r--r--src/csharp/Grpc.Core.Tests/SanityTest.cs7
-rw-r--r--src/csharp/Grpc.Core.Tests/packages.config7
-rw-r--r--src/csharp/Grpc.Core.Tests/project.json26
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.csproj4
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.nuspec14
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.targets24
-rw-r--r--src/csharp/Grpc.Core/GrpcEnvironment.cs3
-rw-r--r--src/csharp/Grpc.Core/Internal/NativeExtension.cs31
-rw-r--r--src/csharp/Grpc.Core/Internal/NativeMethods.cs622
-rw-r--r--src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs33
-rw-r--r--src/csharp/Grpc.Core/NativeDeps.Linux.targets2
-rw-r--r--src/csharp/Grpc.Core/NativeDeps.Mac.targets2
-rw-r--r--src/csharp/Grpc.Core/NativeDeps.Windows.targets2
-rw-r--r--src/csharp/Grpc.Core/packages.config2
-rw-r--r--src/csharp/Grpc.Core/project.json18
-rw-r--r--src/csharp/Grpc.Examples.MathClient/packages.config3
-rw-r--r--src/csharp/Grpc.Examples.MathClient/project.json21
-rw-r--r--src/csharp/Grpc.Examples.MathServer/packages.config3
-rw-r--r--src/csharp/Grpc.Examples.MathServer/project.json21
-rw-r--r--src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj4
-rw-r--r--src/csharp/Grpc.Examples.Tests/NUnitMain.cs2
-rw-r--r--src/csharp/Grpc.Examples.Tests/packages.config2
-rw-r--r--src/csharp/Grpc.Examples.Tests/project.json21
-rw-r--r--src/csharp/Grpc.Examples/Grpc.Examples.csproj4
-rw-r--r--src/csharp/Grpc.Examples/packages.config2
-rw-r--r--src/csharp/Grpc.Examples/project.json10
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs2
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/project.json21
-rw-r--r--src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj4
-rw-r--r--src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec2
-rw-r--r--src/csharp/Grpc.HealthCheck/packages.config2
-rw-r--r--src/csharp/Grpc.HealthCheck/project.json2
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj31
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Client/packages.config4
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Client/project.json21
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj1
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config15
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/packages.config3
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json21
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj31
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Server/packages.config4
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Server/project.json21
-rw-r--r--src/csharp/Grpc.IntegrationTesting.StressClient/packages.config3
-rw-r--r--src/csharp/Grpc.IntegrationTesting.StressClient/project.json21
-rw-r--r--src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs2
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj28
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropClient.cs63
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropServer.cs32
-rw-r--r--src/csharp/Grpc.IntegrationTesting/NUnitMain.cs2
-rw-r--r--src/csharp/Grpc.IntegrationTesting/QpsWorker.cs30
-rw-r--r--src/csharp/Grpc.IntegrationTesting/StressTestClient.cs51
-rw-r--r--src/csharp/Grpc.IntegrationTesting/packages.config8
-rw-r--r--src/csharp/Grpc.IntegrationTesting/project.json25
-rw-r--r--src/csharp/build_packages.bat8
-rw-r--r--src/node/ext/call_credentials.cc30
-rw-r--r--src/node/health_check/package.json8
-rw-r--r--src/node/src/credentials.js9
-rw-r--r--src/node/test/credentials_test.js5
-rwxr-xr-xsrc/node/tools/bin/protoc.js6
-rw-r--r--src/objective-c/!ProtoCompiler-gRPCPlugin.podspec8
-rw-r--r--src/objective-c/!ProtoCompiler.podspec13
-rw-r--r--src/objective-c/BoringSSL.podspec471
-rw-r--r--src/objective-c/GRPCClient/GRPCCall+ChannelArg.h5
-rw-r--r--src/objective-c/GRPCClient/GRPCCall+ChannelArg.m11
-rw-r--r--src/objective-c/GRPCClient/GRPCCall+Tests.h6
-rw-r--r--src/objective-c/GRPCClient/GRPCCall+Tests.m3
-rw-r--r--src/objective-c/GRPCClient/private/GRPCChannel.h4
-rw-r--r--src/objective-c/GRPCClient/private/GRPCChannel.m16
-rw-r--r--src/objective-c/GRPCClient/private/GRPCHost.h5
-rw-r--r--src/objective-c/GRPCClient/private/GRPCHost.m12
-rw-r--r--src/objective-c/ProtoRPC/ProtoRPC.m6
-rw-r--r--src/objective-c/README.md2
-rw-r--r--src/objective-c/examples/RemoteTestClient/RemoteTest.podspec2
-rw-r--r--src/objective-c/examples/RemoteTestClient/empty.proto44
-rw-r--r--src/objective-c/examples/RemoteTestClient/test.proto4
-rw-r--r--src/objective-c/examples/Sample/Podfile2
-rw-r--r--src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj13
-rw-r--r--src/objective-c/examples/Sample/Sample/Info.plist2
-rw-r--r--src/objective-c/examples/Sample/Sample/ViewController.m6
-rw-r--r--src/objective-c/examples/SwiftSample/Info.plist2
-rw-r--r--src/objective-c/examples/SwiftSample/Podfile2
-rw-r--r--src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj19
-rw-r--r--src/objective-c/examples/SwiftSample/ViewController.swift8
-rw-r--r--src/objective-c/tests/CoreCronetEnd2EndTests/Info.plist24
-rw-r--r--src/objective-c/tests/GRPCClientTests.m9
-rw-r--r--src/objective-c/tests/InteropTests.h7
-rw-r--r--src/objective-c/tests/InteropTests.m73
-rw-r--r--src/objective-c/tests/InteropTestsLocalCleartext.m8
-rw-r--r--src/objective-c/tests/InteropTestsLocalSSL.m8
-rw-r--r--src/objective-c/tests/InteropTestsRemote.m4
-rw-r--r--src/objective-c/tests/InteropTestsRemoteWithCronet/Info.plist24
-rw-r--r--src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m (renamed from src/objective-c/examples/SwiftSample/Bridging-Header.h)25
-rw-r--r--src/objective-c/tests/Podfile33
-rw-r--r--src/objective-c/tests/RemoteTestClient/RemoteTest.podspec2
-rw-r--r--src/objective-c/tests/Tests.xcodeproj/project.pbxproj543
-rw-r--r--src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme6
-rw-r--r--src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/CoreCronetEnd2EndTests.xcscheme99
-rw-r--r--src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemoteWithCronet.xcscheme104
-rwxr-xr-xsrc/objective-c/tests/build_example_test.sh27
-rwxr-xr-xsrc/objective-c/tests/build_one_example.sh4
-rwxr-xr-xsrc/objective-c/tests/build_tests.sh26
-rwxr-xr-xsrc/objective-c/tests/run_tests.sh14
-rw-r--r--src/php/README.md43
-rwxr-xr-xsrc/php/bin/determine_extension_dir.sh6
-rw-r--r--src/php/composer.json6
-rw-r--r--src/php/ext/grpc/call.c541
-rw-r--r--src/php/ext/grpc/call.h31
-rw-r--r--src/php/ext/grpc/call_credentials.c91
-rwxr-xr-xsrc/php/ext/grpc/call_credentials.h24
-rw-r--r--src/php/ext/grpc/channel.c164
-rwxr-xr-xsrc/php/ext/grpc/channel.h27
-rw-r--r--src/php/ext/grpc/channel_credentials.c75
-rwxr-xr-xsrc/php/ext/grpc/channel_credentials.h24
-rw-r--r--src/php/ext/grpc/package.xml156
-rw-r--r--src/php/ext/grpc/php7_wrapper.h217
-rw-r--r--src/php/ext/grpc/php_grpc.c54
-rw-r--r--src/php/ext/grpc/php_grpc.h6
-rw-r--r--src/php/ext/grpc/server.c111
-rwxr-xr-xsrc/php/ext/grpc/server.h23
-rw-r--r--src/php/ext/grpc/server_credentials.c55
-rwxr-xr-xsrc/php/ext/grpc/server_credentials.h24
-rw-r--r--src/php/ext/grpc/timeval.c128
-rwxr-xr-xsrc/php/ext/grpc/timeval.h24
-rw-r--r--[-rwxr-xr-x]src/php/lib/Grpc/BaseStub.php4
-rw-r--r--src/php/lib/Grpc/BidiStreamingCall.php1
-rw-r--r--src/php/lib/Grpc/ClientStreamingCall.php1
-rw-r--r--src/php/lib/Grpc/ServerStreamingCall.php1
-rw-r--r--src/php/lib/Grpc/UnaryCall.php1
-rwxr-xr-xsrc/php/tests/interop/interop_client.php10
-rw-r--r--src/php/tests/unit_tests/CallCredentialsTest.php3
-rw-r--r--[-rwxr-xr-x]src/php/tests/unit_tests/CallTest.php49
-rw-r--r--src/php/tests/unit_tests/ChannelCredentialsTest.php25
-rw-r--r--src/php/tests/unit_tests/ChannelTest.php107
-rw-r--r--[-rwxr-xr-x]src/php/tests/unit_tests/EndToEndTest.php3
-rw-r--r--[-rwxr-xr-x]src/php/tests/unit_tests/SecureEndToEndTest.php0
-rw-r--r--src/php/tests/unit_tests/ServerTest.php85
-rw-r--r--[-rwxr-xr-x]src/php/tests/unit_tests/TimevalTest.php53
-rw-r--r--src/proto/census/census.proto119
-rw-r--r--src/python/grpcio/.gitignore1
-rw-r--r--src/python/grpcio/_unixccompiler_patch.py4
-rw-r--r--src/python/grpcio/commands.py67
-rw-r--r--src/python/grpcio/grpc/__init__.py4
-rw-r--r--src/python/grpcio/grpc/_channel.py4
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi2
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi2
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi2
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi14
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi89
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi12
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi2
-rw-r--r--src/python/grpcio/grpc/_cython/cygrpc.pyx9
-rw-r--r--src/python/grpcio/grpc/_cython/loader.h61
-rw-r--r--src/python/grpcio/grpc/beta/_client_adaptations.py10
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py6
-rw-r--r--src/python/grpcio_health_checking/MANIFEST.in3
-rw-r--r--src/python/grpcio_health_checking/grpc/__init__.py (renamed from src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py)2
-rw-r--r--src/python/grpcio_health_checking/grpc/health/__init__.py (renamed from src/python/grpcio_health_checking/grpc_health/__init__.py)0
-rw-r--r--src/python/grpcio_health_checking/grpc/health/v1/__init__.py (renamed from src/python/grpcio_health_checking/grpc_health/health/__init__.py)0
-rw-r--r--src/python/grpcio_health_checking/grpc/health/v1/health.py (renamed from src/python/grpcio_health_checking/grpc_health/health/v1/health.py)19
-rw-r--r--[-rwxr-xr-x]src/python/grpcio_health_checking/grpc_version.py (renamed from src/ruby/tools/bin/grpc_tools_ruby_protoc.rb)13
-rw-r--r--src/python/grpcio_health_checking/health_commands.py29
-rw-r--r--src/python/grpcio_health_checking/setup.py24
-rw-r--r--src/python/grpcio_tests/commands.py2
-rw-r--r--src/python/grpcio_tests/setup.py4
-rw-r--r--src/python/grpcio_tests/tests/health_check/_health_servicer_test.py58
-rw-r--r--src/python/grpcio_tests/tests/interop/_insecure_interop_test.py14
-rw-r--r--src/python/grpcio_tests/tests/interop/_secure_interop_test.py24
-rw-r--r--src/python/grpcio_tests/tests/interop/client.py56
-rw-r--r--src/python/grpcio_tests/tests/interop/methods.py270
-rw-r--r--src/python/grpcio_tests/tests/interop/server.py12
-rw-r--r--src/python/grpcio_tests/tests/stress/client.py21
-rw-r--r--src/python/grpcio_tests/tests/stress/metrics_server.py2
-rw-r--r--src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py10
-rw-r--r--src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py6
-rw-r--r--src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py4
-rw-r--r--src/python/grpcio_tests/tests/unit/_thread_pool.py48
-rw-r--r--src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py6
-rw-r--r--src/ruby/.rubocop.yml4
-rwxr-xr-xsrc/ruby/bin/math_client.rb2
-rw-r--r--[-rwxr-xr-x]src/ruby/bin/math_pb.rb (renamed from src/ruby/bin/math.rb)0
-rwxr-xr-xsrc/ruby/bin/math_server.rb2
-rw-r--r--[-rwxr-xr-x]src/ruby/bin/math_services_pb.rb (renamed from src/ruby/bin/math_services.rb)2
-rw-r--r--src/ruby/ext/grpc/rb_channel.c25
-rw-r--r--src/ruby/ext/grpc/rb_completion_queue.h3
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.c24
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.h36
-rw-r--r--src/ruby/lib/grpc/generic/active_call.rb68
-rw-r--r--src/ruby/lib/grpc/generic/bidi_call.rb110
-rw-r--r--src/ruby/lib/grpc/generic/client_stub.rb24
-rw-r--r--src/ruby/lib/grpc/generic/rpc_desc.rb9
-rw-r--r--src/ruby/lib/grpc/generic/rpc_server.rb35
-rw-r--r--src/ruby/pb/grpc/health/checker.rb2
-rw-r--r--src/ruby/pb/grpc/health/v1/health_pb.rb (renamed from src/ruby/pb/grpc/health/v1/health.rb)0
-rw-r--r--src/ruby/pb/grpc/health/v1/health_services_pb.rb (renamed from src/ruby/pb/grpc/health/v1/health_services.rb)2
-rw-r--r--src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb (renamed from src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services.rb)4
-rw-r--r--src/ruby/pb/grpc/testing/metrics_pb.rb (renamed from src/ruby/pb/grpc/testing/metrics.rb)2
-rw-r--r--src/ruby/pb/grpc/testing/metrics_services_pb.rb (renamed from src/ruby/pb/grpc/testing/metrics_services.rb)4
-rw-r--r--src/ruby/pb/src/proto/grpc/testing/empty_pb.rb (renamed from src/ruby/pb/src/proto/grpc/testing/empty.rb)0
-rw-r--r--src/ruby/pb/src/proto/grpc/testing/messages_pb.rb (renamed from src/ruby/pb/src/proto/grpc/testing/messages.rb)0
-rw-r--r--src/ruby/pb/src/proto/grpc/testing/test_pb.rb (renamed from src/ruby/pb/src/proto/grpc/testing/test.rb)4
-rw-r--r--src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb (renamed from src/ruby/pb/src/proto/grpc/testing/test_services.rb)2
-rwxr-xr-xsrc/ruby/pb/test/client.rb6
-rwxr-xr-xsrc/ruby/pb/test/server.rb6
-rw-r--r--src/ruby/qps/client.rb2
-rw-r--r--src/ruby/qps/server.rb6
-rw-r--r--src/ruby/qps/src/proto/grpc/testing/control_pb.rb (renamed from src/ruby/qps/src/proto/grpc/testing/control.rb)6
-rw-r--r--src/ruby/qps/src/proto/grpc/testing/messages_pb.rb (renamed from src/ruby/qps/src/proto/grpc/testing/messages.rb)0
-rw-r--r--src/ruby/qps/src/proto/grpc/testing/payloads_pb.rb (renamed from src/ruby/qps/src/proto/grpc/testing/payloads.rb)0
-rw-r--r--src/ruby/qps/src/proto/grpc/testing/services_pb.rb (renamed from src/ruby/qps/src/proto/grpc/testing/services.rb)4
-rw-r--r--src/ruby/qps/src/proto/grpc/testing/services_services_pb.rb (renamed from src/ruby/qps/src/proto/grpc/testing/services_services.rb)2
-rw-r--r--src/ruby/qps/src/proto/grpc/testing/stats_pb.rb (renamed from src/ruby/qps/src/proto/grpc/testing/stats.rb)0
-rwxr-xr-xsrc/ruby/qps/worker.rb2
-rw-r--r--src/ruby/spec/generic/active_call_spec.rb278
-rw-r--r--src/ruby/spec/generic/rpc_desc_spec.rb14
-rw-r--r--src/ruby/spec/pb/duplicate/codegen_spec.rb4
-rw-r--r--src/ruby/spec/pb/health/checker_spec.rb8
-rw-r--r--src/ruby/stress/metrics_server.rb4
-rwxr-xr-xsrc/ruby/tools/bin/grpc_tools_ruby_protoc48
-rwxr-xr-xsrc/ruby/tools/bin/grpc_tools_ruby_protoc_plugin (renamed from src/ruby/tools/bin/grpc_tools_ruby_protoc_plugin.rb)0
-rw-r--r--src/ruby/tools/grpc-tools.gemspec2
320 files changed, 8796 insertions, 4183 deletions
diff --git a/src/compiler/node_generator.cc b/src/compiler/node_generator.cc
index c3852020a3..d7af125c3a 100644
--- a/src/compiler/node_generator.cc
+++ b/src/compiler/node_generator.cc
@@ -114,8 +114,8 @@ map<grpc::string, const Descriptor *> GetAllMessages(
const MethodDescriptor *method = service->method(method_num);
const Descriptor *input_type = method->input_type();
const Descriptor *output_type = method->output_type();
- message_types[input_type->name()] = input_type;
- message_types[output_type->name()] = output_type;
+ message_types[input_type->full_name()] = input_type;
+ message_types[output_type->full_name()] = output_type;
}
}
return message_types;
@@ -127,7 +127,7 @@ grpc::string MessageIdentifierName(const grpc::string &name) {
grpc::string NodeObjectPath(const Descriptor *descriptor) {
grpc::string module_alias = ModuleAlias(descriptor->file()->name());
- grpc::string name = descriptor->name();
+ grpc::string name = descriptor->full_name();
grpc_generator::StripPrefix(&name, descriptor->file()->package() + ".");
return module_alias + "." + name;
}
@@ -135,8 +135,9 @@ grpc::string NodeObjectPath(const Descriptor *descriptor) {
// Prints out the message serializer and deserializer functions
void PrintMessageTransformer(const Descriptor *descriptor, Printer *out) {
map<grpc::string, grpc::string> template_vars;
- template_vars["identifier_name"] = MessageIdentifierName(descriptor->name());
- template_vars["name"] = descriptor->name();
+ grpc::string full_name = descriptor->full_name();
+ template_vars["identifier_name"] = MessageIdentifierName(full_name);
+ template_vars["name"] = full_name;
template_vars["node_name"] = NodeObjectPath(descriptor);
// Print the serializer
out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n");
@@ -169,9 +170,9 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
vars["service_name"] = method->service()->full_name();
vars["name"] = method->name();
vars["input_type"] = NodeObjectPath(input_type);
- vars["input_type_id"] = MessageIdentifierName(input_type->name());
+ vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
vars["output_type"] = NodeObjectPath(output_type);
- vars["output_type_id"] = MessageIdentifierName(output_type->name());
+ vars["output_type_id"] = MessageIdentifierName(output_type->full_name());
vars["client_stream"] = method->client_streaming() ? "true" : "false";
vars["server_stream"] = method->server_streaming() ? "true" : "false";
out->Print("{\n");
diff --git a/src/compiler/ruby_generator_helpers-inl.h b/src/compiler/ruby_generator_helpers-inl.h
index ff6939ed9f..aa3c22fea6 100644
--- a/src/compiler/ruby_generator_helpers-inl.h
+++ b/src/compiler/ruby_generator_helpers-inl.h
@@ -48,7 +48,7 @@ inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file,
file->name().find_last_of(".proto") == file->name().size() - 1) {
*file_name_or_error =
file->name().substr(0, file->name().size() - proto_suffix_length) +
- "_services.rb";
+ "_services_pb.rb";
return true;
} else {
*file_name_or_error = "Invalid proto file name: must end with .proto";
@@ -58,7 +58,7 @@ inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file,
inline grpc::string MessagesRequireName(
const grpc::protobuf::FileDescriptor *file) {
- return Replace(file->name(), ".proto", "");
+ return Replace(file->name(), ".proto", "_pb");
}
// Get leading or trailing comments in a string. Comment lines start with "# ".
diff --git a/src/core/ext/census/base_resources.c b/src/core/ext/census/base_resources.c
new file mode 100644
index 0000000000..f9aa4bb994
--- /dev/null
+++ b/src/core/ext/census/base_resources.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/ext/census/base_resources.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/census.h>
+#include <grpc/support/log.h>
+
+#include "src/core/ext/census/resource.h"
+
+// Add base RPC resource definitions for use by RPC runtime.
+//
+// TODO(aveitch): All of these are currently hardwired definitions encoded in
+// the code in this file. These should be converted to use an external
+// configuration mechanism, in which these resources are defined in a text
+// file, which is compiled to .pb format and read by still-to-be-written
+// configuration functions.
+
+// Define all base resources. This should be called by census initialization.
+void define_base_resources() {
+ google_census_Resource_BasicUnit numerator =
+ google_census_Resource_BasicUnit_SECS;
+ resource r = {"client_rpc_latency", // name
+ "Client RPC latency in seconds", // description
+ 0, // prefix
+ 1, // n_numerators
+ &numerator, // numerators
+ 0, // n_denominators
+ NULL}; // denominators
+ define_resource(&r);
+ r = (resource){"server_rpc_latency", // name
+ "Server RPC latency in seconds", // description
+ 0, // prefix
+ 1, // n_numerators
+ &numerator, // numerators
+ 0, // n_denominators
+ NULL}; // denominators
+ define_resource(&r);
+}
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/core/ext/census/base_resources.h
index c0080b5a47..e5a7696db4 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.c
+++ b/src/core/ext/census/base_resources.h
@@ -1,5 +1,4 @@
/*
- *
* Copyright 2016, Google Inc.
* All rights reserved.
*
@@ -31,7 +30,10 @@
*
*/
-/* TODO(atash) remove cruft */
-#include <grpc/support/port_platform.h>
+#ifndef GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H
+#define GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H
+
+/* Define all base resources. This should be called by census initialization. */
+void define_base_resources();
-#include "imports.generated.h"
+#endif /* GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H */
diff --git a/src/core/ext/census/gen/census.pb.c b/src/core/ext/census/gen/census.pb.c
index d614636c90..647f0635b7 100644
--- a/src/core/ext/census/gen/census.pb.c
+++ b/src/core/ext/census/gen/census.pb.c
@@ -53,29 +53,24 @@ const pb_field_t google_census_Timestamp_fields[3] = {
PB_LAST_FIELD
};
-const pb_field_t google_census_Metric_fields[5] = {
- PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_Metric, name, name, 0),
- PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, google_census_Metric, description, name, 0),
- PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Metric, unit, description, &google_census_Metric_MeasurementUnit_fields),
- PB_FIELD( 4, INT32 , OPTIONAL, STATIC , OTHER, google_census_Metric, id, unit, 0),
+const pb_field_t google_census_Resource_fields[4] = {
+ PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_Resource, name, name, 0),
+ PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, google_census_Resource, description, name, 0),
+ PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Resource, unit, description, &google_census_Resource_MeasurementUnit_fields),
PB_LAST_FIELD
};
-const pb_field_t google_census_Metric_BasicUnit_fields[2] = {
- PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, google_census_Metric_BasicUnit, type, type, 0),
+const pb_field_t google_census_Resource_MeasurementUnit_fields[4] = {
+ PB_FIELD( 1, INT32 , OPTIONAL, STATIC , FIRST, google_census_Resource_MeasurementUnit, prefix, prefix, 0),
+ PB_FIELD( 2, UENUM , REPEATED, CALLBACK, OTHER, google_census_Resource_MeasurementUnit, numerator, prefix, 0),
+ PB_FIELD( 3, UENUM , REPEATED, CALLBACK, OTHER, google_census_Resource_MeasurementUnit, denominator, numerator, 0),
PB_LAST_FIELD
};
-const pb_field_t google_census_Metric_MeasurementUnit_fields[4] = {
- PB_FIELD( 1, INT32 , OPTIONAL, STATIC , FIRST, google_census_Metric_MeasurementUnit, prefix, prefix, 0),
- PB_FIELD( 2, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Metric_MeasurementUnit, numerator, prefix, &google_census_Metric_BasicUnit_fields),
- PB_FIELD( 3, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Metric_MeasurementUnit, denominator, numerator, &google_census_Metric_BasicUnit_fields),
- PB_LAST_FIELD
-};
-
-const pb_field_t google_census_AggregationDescriptor_fields[3] = {
- PB_ONEOF_FIELD(options, 1, MESSAGE , ONEOF, STATIC , FIRST, google_census_AggregationDescriptor, bucket_boundaries, bucket_boundaries, &google_census_AggregationDescriptor_BucketBoundaries_fields),
- PB_ONEOF_FIELD(options, 2, MESSAGE , ONEOF, STATIC , FIRST, google_census_AggregationDescriptor, interval_boundaries, interval_boundaries, &google_census_AggregationDescriptor_IntervalBoundaries_fields),
+const pb_field_t google_census_AggregationDescriptor_fields[4] = {
+ PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, google_census_AggregationDescriptor, type, type, 0),
+ PB_ONEOF_FIELD(options, 2, MESSAGE , ONEOF, STATIC , OTHER, google_census_AggregationDescriptor, bucket_boundaries, type, &google_census_AggregationDescriptor_BucketBoundaries_fields),
+ PB_ONEOF_FIELD(options, 3, MESSAGE , ONEOF, STATIC , OTHER, google_census_AggregationDescriptor, interval_boundaries, type, &google_census_AggregationDescriptor_IntervalBoundaries_fields),
PB_LAST_FIELD
};
@@ -124,25 +119,27 @@ const pb_field_t google_census_Tag_fields[3] = {
const pb_field_t google_census_View_fields[6] = {
PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_View, name, name, 0),
PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, google_census_View, description, name, 0),
- PB_FIELD( 3, INT32 , OPTIONAL, STATIC , OTHER, google_census_View, metric_id, description, 0),
- PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_View, aggregation, metric_id, &google_census_AggregationDescriptor_fields),
+ PB_FIELD( 3, STRING , OPTIONAL, CALLBACK, OTHER, google_census_View, resource_name, description, 0),
+ PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_View, aggregation, resource_name, &google_census_AggregationDescriptor_fields),
PB_FIELD( 5, STRING , REPEATED, CALLBACK, OTHER, google_census_View, tag_key, aggregation, 0),
PB_LAST_FIELD
};
-const pb_field_t google_census_Aggregation_fields[6] = {
+const pb_field_t google_census_Aggregation_fields[7] = {
PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_Aggregation, name, name, 0),
PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, google_census_Aggregation, description, name, 0),
- PB_ONEOF_FIELD(data, 3, MESSAGE , ONEOF, STATIC , OTHER, google_census_Aggregation, distribution, description, &google_census_Distribution_fields),
- PB_ONEOF_FIELD(data, 4, MESSAGE , ONEOF, STATIC , OTHER, google_census_Aggregation, interval_stats, description, &google_census_IntervalStats_fields),
- PB_FIELD( 5, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Aggregation, tag, data.interval_stats, &google_census_Tag_fields),
+ PB_ONEOF_FIELD(data, 3, UINT64 , ONEOF, STATIC , OTHER, google_census_Aggregation, count, description, 0),
+ PB_ONEOF_FIELD(data, 4, MESSAGE , ONEOF, STATIC , OTHER, google_census_Aggregation, distribution, description, &google_census_Distribution_fields),
+ PB_ONEOF_FIELD(data, 5, MESSAGE , ONEOF, STATIC , OTHER, google_census_Aggregation, interval_stats, description, &google_census_IntervalStats_fields),
+ PB_FIELD( 6, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Aggregation, tag, data.interval_stats, &google_census_Tag_fields),
PB_LAST_FIELD
};
-const pb_field_t google_census_ViewAggregations_fields[4] = {
- PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, google_census_ViewAggregations, aggregation, aggregation, &google_census_Aggregation_fields),
- PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_ViewAggregations, start, aggregation, &google_census_Timestamp_fields),
- PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_ViewAggregations, end, start, &google_census_Timestamp_fields),
+const pb_field_t google_census_Metric_fields[5] = {
+ PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_Metric, view_name, view_name, 0),
+ PB_FIELD( 2, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Metric, aggregation, view_name, &google_census_Aggregation_fields),
+ PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Metric, start, aggregation, &google_census_Timestamp_fields),
+ PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Metric, end, start, &google_census_Timestamp_fields),
PB_LAST_FIELD
};
@@ -156,7 +153,7 @@ const pb_field_t google_census_ViewAggregations_fields[4] = {
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors.
*/
-PB_STATIC_ASSERT((pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Aggregation, tag) < 65536 && pb_membersize(google_census_ViewAggregations, aggregation) < 65536 && pb_membersize(google_census_ViewAggregations, start) < 65536 && pb_membersize(google_census_ViewAggregations, end) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Metric_google_census_Metric_BasicUnit_google_census_Metric_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_ViewAggregations)
+PB_STATIC_ASSERT((pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Aggregation, tag) < 65536 && pb_membersize(google_census_Metric, aggregation) < 65536 && pb_membersize(google_census_Metric, start) < 65536 && pb_membersize(google_census_Metric, end) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Resource_google_census_Resource_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_Metric)
#endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
@@ -167,7 +164,7 @@ PB_STATIC_ASSERT((pb_membersize(google_census_Metric, unit) < 65536 && pb_member
* numbers or field sizes that are larger than what can fit in the default
* 8 bit descriptors.
*/
-PB_STATIC_ASSERT((pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Aggregation, tag) < 256 && pb_membersize(google_census_ViewAggregations, aggregation) < 256 && pb_membersize(google_census_ViewAggregations, start) < 256 && pb_membersize(google_census_ViewAggregations, end) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Metric_google_census_Metric_BasicUnit_google_census_Metric_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_ViewAggregations)
+PB_STATIC_ASSERT((pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Aggregation, tag) < 256 && pb_membersize(google_census_Metric, aggregation) < 256 && pb_membersize(google_census_Metric, start) < 256 && pb_membersize(google_census_Metric, end) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Resource_google_census_Resource_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_Metric)
#endif
diff --git a/src/core/ext/census/gen/census.pb.h b/src/core/ext/census/gen/census.pb.h
index d040fe29e7..dae583f33d 100644
--- a/src/core/ext/census/gen/census.pb.h
+++ b/src/core/ext/census/gen/census.pb.h
@@ -45,14 +45,21 @@ extern "C" {
#endif
/* Enum definitions */
-typedef enum _google_census_Metric_BasicUnit_Measure {
- google_census_Metric_BasicUnit_Measure_UNKNOWN = 0,
- google_census_Metric_BasicUnit_Measure_BITS = 1,
- google_census_Metric_BasicUnit_Measure_BYTES = 2,
- google_census_Metric_BasicUnit_Measure_SECS = 3,
- google_census_Metric_BasicUnit_Measure_CORES = 4,
- google_census_Metric_BasicUnit_Measure_MAX_UNITS = 5
-} google_census_Metric_BasicUnit_Measure;
+typedef enum _google_census_Resource_BasicUnit {
+ google_census_Resource_BasicUnit_UNKNOWN = 0,
+ google_census_Resource_BasicUnit_BITS = 1,
+ google_census_Resource_BasicUnit_BYTES = 2,
+ google_census_Resource_BasicUnit_SECS = 3,
+ google_census_Resource_BasicUnit_CORES = 4,
+ google_census_Resource_BasicUnit_MAX_UNITS = 5
+} google_census_Resource_BasicUnit;
+
+typedef enum _google_census_AggregationDescriptor_AggregationType {
+ google_census_AggregationDescriptor_AggregationType_UNKNOWN = 0,
+ google_census_AggregationDescriptor_AggregationType_COUNT = 1,
+ google_census_AggregationDescriptor_AggregationType_DISTRIBUTION = 2,
+ google_census_AggregationDescriptor_AggregationType_INTERVAL = 3
+} google_census_AggregationDescriptor_AggregationType;
/* Struct definitions */
typedef struct _google_census_AggregationDescriptor_BucketBoundaries {
@@ -68,6 +75,8 @@ typedef struct _google_census_IntervalStats {
} google_census_IntervalStats;
typedef struct _google_census_AggregationDescriptor {
+ bool has_type;
+ google_census_AggregationDescriptor_AggregationType type;
pb_size_t which_options;
union {
google_census_AggregationDescriptor_BucketBoundaries bucket_boundaries;
@@ -89,17 +98,12 @@ typedef struct _google_census_Duration {
int32_t nanos;
} google_census_Duration;
-typedef struct _google_census_Metric_BasicUnit {
- bool has_type;
- google_census_Metric_BasicUnit_Measure type;
-} google_census_Metric_BasicUnit;
-
-typedef struct _google_census_Metric_MeasurementUnit {
+typedef struct _google_census_Resource_MeasurementUnit {
bool has_prefix;
int32_t prefix;
pb_callback_t numerator;
pb_callback_t denominator;
-} google_census_Metric_MeasurementUnit;
+} google_census_Resource_MeasurementUnit;
typedef struct _google_census_Tag {
bool has_key;
@@ -135,37 +139,36 @@ typedef struct _google_census_IntervalStats_Window {
} google_census_IntervalStats_Window;
typedef struct _google_census_Metric {
+ pb_callback_t view_name;
+ pb_callback_t aggregation;
+ bool has_start;
+ google_census_Timestamp start;
+ bool has_end;
+ google_census_Timestamp end;
+} google_census_Metric;
+
+typedef struct _google_census_Resource {
pb_callback_t name;
pb_callback_t description;
bool has_unit;
- google_census_Metric_MeasurementUnit unit;
- bool has_id;
- int32_t id;
-} google_census_Metric;
+ google_census_Resource_MeasurementUnit unit;
+} google_census_Resource;
typedef struct _google_census_View {
pb_callback_t name;
pb_callback_t description;
- bool has_metric_id;
- int32_t metric_id;
+ pb_callback_t resource_name;
bool has_aggregation;
google_census_AggregationDescriptor aggregation;
pb_callback_t tag_key;
} google_census_View;
-typedef struct _google_census_ViewAggregations {
- pb_callback_t aggregation;
- bool has_start;
- google_census_Timestamp start;
- bool has_end;
- google_census_Timestamp end;
-} google_census_ViewAggregations;
-
typedef struct _google_census_Aggregation {
pb_callback_t name;
pb_callback_t description;
pb_size_t which_data;
union {
+ uint64_t count;
google_census_Distribution distribution;
google_census_IntervalStats interval_stats;
} data;
@@ -177,10 +180,9 @@ typedef struct _google_census_Aggregation {
/* Initializer values for message structs */
#define google_census_Duration_init_default {false, 0, false, 0}
#define google_census_Timestamp_init_default {false, 0, false, 0}
-#define google_census_Metric_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Metric_MeasurementUnit_init_default, false, 0}
-#define google_census_Metric_BasicUnit_init_default {false, (google_census_Metric_BasicUnit_Measure)0}
-#define google_census_Metric_MeasurementUnit_init_default {false, 0, {{NULL}, NULL}, {{NULL}, NULL}}
-#define google_census_AggregationDescriptor_init_default {0, {google_census_AggregationDescriptor_BucketBoundaries_init_default}}
+#define google_census_Resource_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Resource_MeasurementUnit_init_default}
+#define google_census_Resource_MeasurementUnit_init_default {false, 0, {{NULL}, NULL}, {{NULL}, NULL}}
+#define google_census_AggregationDescriptor_init_default {false, (google_census_AggregationDescriptor_AggregationType)0, 0, {google_census_AggregationDescriptor_BucketBoundaries_init_default}}
#define google_census_AggregationDescriptor_BucketBoundaries_init_default {{{NULL}, NULL}}
#define google_census_AggregationDescriptor_IntervalBoundaries_init_default {{{NULL}, NULL}}
#define google_census_Distribution_init_default {false, 0, false, 0, false, google_census_Distribution_Range_init_default, {{NULL}, NULL}}
@@ -188,15 +190,14 @@ typedef struct _google_census_Aggregation {
#define google_census_IntervalStats_init_default {{{NULL}, NULL}}
#define google_census_IntervalStats_Window_init_default {false, google_census_Duration_init_default, false, 0, false, 0}
#define google_census_Tag_init_default {false, "", false, ""}
-#define google_census_View_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, 0, false, google_census_AggregationDescriptor_init_default, {{NULL}, NULL}}
-#define google_census_Aggregation_init_default {{{NULL}, NULL}, {{NULL}, NULL}, 0, {google_census_Distribution_init_default}, {{NULL}, NULL}}
-#define google_census_ViewAggregations_init_default {{{NULL}, NULL}, false, google_census_Timestamp_init_default, false, google_census_Timestamp_init_default}
+#define google_census_View_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, google_census_AggregationDescriptor_init_default, {{NULL}, NULL}}
+#define google_census_Aggregation_init_default {{{NULL}, NULL}, {{NULL}, NULL}, 0, {0}, {{NULL}, NULL}}
+#define google_census_Metric_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Timestamp_init_default, false, google_census_Timestamp_init_default}
#define google_census_Duration_init_zero {false, 0, false, 0}
#define google_census_Timestamp_init_zero {false, 0, false, 0}
-#define google_census_Metric_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Metric_MeasurementUnit_init_zero, false, 0}
-#define google_census_Metric_BasicUnit_init_zero {false, (google_census_Metric_BasicUnit_Measure)0}
-#define google_census_Metric_MeasurementUnit_init_zero {false, 0, {{NULL}, NULL}, {{NULL}, NULL}}
-#define google_census_AggregationDescriptor_init_zero {0, {google_census_AggregationDescriptor_BucketBoundaries_init_zero}}
+#define google_census_Resource_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Resource_MeasurementUnit_init_zero}
+#define google_census_Resource_MeasurementUnit_init_zero {false, 0, {{NULL}, NULL}, {{NULL}, NULL}}
+#define google_census_AggregationDescriptor_init_zero {false, (google_census_AggregationDescriptor_AggregationType)0, 0, {google_census_AggregationDescriptor_BucketBoundaries_init_zero}}
#define google_census_AggregationDescriptor_BucketBoundaries_init_zero {{{NULL}, NULL}}
#define google_census_AggregationDescriptor_IntervalBoundaries_init_zero {{{NULL}, NULL}}
#define google_census_Distribution_init_zero {false, 0, false, 0, false, google_census_Distribution_Range_init_zero, {{NULL}, NULL}}
@@ -204,25 +205,25 @@ typedef struct _google_census_Aggregation {
#define google_census_IntervalStats_init_zero {{{NULL}, NULL}}
#define google_census_IntervalStats_Window_init_zero {false, google_census_Duration_init_zero, false, 0, false, 0}
#define google_census_Tag_init_zero {false, "", false, ""}
-#define google_census_View_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, 0, false, google_census_AggregationDescriptor_init_zero, {{NULL}, NULL}}
-#define google_census_Aggregation_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, 0, {google_census_Distribution_init_zero}, {{NULL}, NULL}}
-#define google_census_ViewAggregations_init_zero {{{NULL}, NULL}, false, google_census_Timestamp_init_zero, false, google_census_Timestamp_init_zero}
+#define google_census_View_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, google_census_AggregationDescriptor_init_zero, {{NULL}, NULL}}
+#define google_census_Aggregation_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, 0, {0}, {{NULL}, NULL}}
+#define google_census_Metric_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Timestamp_init_zero, false, google_census_Timestamp_init_zero}
/* Field tags (for use in manual encoding/decoding) */
#define google_census_AggregationDescriptor_BucketBoundaries_bounds_tag 1
#define google_census_AggregationDescriptor_IntervalBoundaries_window_size_tag 1
#define google_census_IntervalStats_window_tag 1
-#define google_census_AggregationDescriptor_bucket_boundaries_tag 1
+#define google_census_AggregationDescriptor_bucket_boundaries_tag 2
-#define google_census_AggregationDescriptor_interval_boundaries_tag 2
+#define google_census_AggregationDescriptor_interval_boundaries_tag 3
+#define google_census_AggregationDescriptor_type_tag 1
#define google_census_Distribution_Range_min_tag 1
#define google_census_Distribution_Range_max_tag 2
#define google_census_Duration_seconds_tag 1
#define google_census_Duration_nanos_tag 2
-#define google_census_Metric_BasicUnit_type_tag 1
-#define google_census_Metric_MeasurementUnit_prefix_tag 1
-#define google_census_Metric_MeasurementUnit_numerator_tag 2
-#define google_census_Metric_MeasurementUnit_denominator_tag 3
+#define google_census_Resource_MeasurementUnit_prefix_tag 1
+#define google_census_Resource_MeasurementUnit_numerator_tag 2
+#define google_census_Resource_MeasurementUnit_denominator_tag 3
#define google_census_Tag_key_tag 1
#define google_census_Tag_value_tag 2
#define google_census_Timestamp_seconds_tag 1
@@ -234,32 +235,33 @@ typedef struct _google_census_Aggregation {
#define google_census_IntervalStats_Window_window_size_tag 1
#define google_census_IntervalStats_Window_count_tag 2
#define google_census_IntervalStats_Window_mean_tag 3
-#define google_census_Metric_name_tag 1
-#define google_census_Metric_description_tag 2
-#define google_census_Metric_unit_tag 3
-#define google_census_Metric_id_tag 4
+#define google_census_Metric_view_name_tag 1
+#define google_census_Metric_aggregation_tag 2
+#define google_census_Metric_start_tag 3
+#define google_census_Metric_end_tag 4
+#define google_census_Resource_name_tag 1
+#define google_census_Resource_description_tag 2
+#define google_census_Resource_unit_tag 3
#define google_census_View_name_tag 1
#define google_census_View_description_tag 2
-#define google_census_View_metric_id_tag 3
+#define google_census_View_resource_name_tag 3
#define google_census_View_aggregation_tag 4
#define google_census_View_tag_key_tag 5
-#define google_census_ViewAggregations_aggregation_tag 1
-#define google_census_ViewAggregations_start_tag 2
-#define google_census_ViewAggregations_end_tag 3
-#define google_census_Aggregation_distribution_tag 3
+#define google_census_Aggregation_count_tag 3
+
+#define google_census_Aggregation_distribution_tag 4
-#define google_census_Aggregation_interval_stats_tag 4
+#define google_census_Aggregation_interval_stats_tag 5
#define google_census_Aggregation_name_tag 1
#define google_census_Aggregation_description_tag 2
-#define google_census_Aggregation_tag_tag 5
+#define google_census_Aggregation_tag_tag 6
/* Struct field encoding specification for nanopb */
extern const pb_field_t google_census_Duration_fields[3];
extern const pb_field_t google_census_Timestamp_fields[3];
-extern const pb_field_t google_census_Metric_fields[5];
-extern const pb_field_t google_census_Metric_BasicUnit_fields[2];
-extern const pb_field_t google_census_Metric_MeasurementUnit_fields[4];
-extern const pb_field_t google_census_AggregationDescriptor_fields[3];
+extern const pb_field_t google_census_Resource_fields[4];
+extern const pb_field_t google_census_Resource_MeasurementUnit_fields[4];
+extern const pb_field_t google_census_AggregationDescriptor_fields[4];
extern const pb_field_t google_census_AggregationDescriptor_BucketBoundaries_fields[2];
extern const pb_field_t google_census_AggregationDescriptor_IntervalBoundaries_fields[2];
extern const pb_field_t google_census_Distribution_fields[5];
@@ -268,13 +270,12 @@ extern const pb_field_t google_census_IntervalStats_fields[2];
extern const pb_field_t google_census_IntervalStats_Window_fields[4];
extern const pb_field_t google_census_Tag_fields[3];
extern const pb_field_t google_census_View_fields[6];
-extern const pb_field_t google_census_Aggregation_fields[6];
-extern const pb_field_t google_census_ViewAggregations_fields[4];
+extern const pb_field_t google_census_Aggregation_fields[7];
+extern const pb_field_t google_census_Metric_fields[5];
/* Maximum encoded size of messages (where known) */
#define google_census_Duration_size 22
#define google_census_Timestamp_size 22
-#define google_census_Metric_BasicUnit_size 2
#define google_census_Distribution_Range_size 18
#define google_census_IntervalStats_Window_size 44
#define google_census_Tag_size 516
diff --git a/src/core/ext/census/grpc_filter.c b/src/core/ext/census/grpc_filter.c
index f51d850e01..9dacc17eb4 100644
--- a/src/core/ext/census/grpc_filter.c
+++ b/src/core/ext/census/grpc_filter.c
@@ -127,38 +127,40 @@ static void server_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_call_next_op(exec_ctx, elem, op);
}
-static void client_init_call_elem(grpc_exec_ctx *exec_ctx,
- grpc_call_element *elem,
- grpc_call_element_args *args) {
+static grpc_error *client_init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
call_data *d = elem->call_data;
GPR_ASSERT(d != NULL);
memset(d, 0, sizeof(*d));
d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
+ return GRPC_ERROR_NONE;
}
static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- const grpc_call_stats *stats,
+ const grpc_call_final_info *final_info,
void *ignored) {
call_data *d = elem->call_data;
GPR_ASSERT(d != NULL);
/* TODO(hongyu): record rpc client stats and census_rpc_end_op here */
}
-static void server_init_call_elem(grpc_exec_ctx *exec_ctx,
- grpc_call_element *elem,
- grpc_call_element_args *args) {
+static grpc_error *server_init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
call_data *d = elem->call_data;
GPR_ASSERT(d != NULL);
memset(d, 0, sizeof(*d));
d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
/* TODO(hongyu): call census_tracing_start_op here. */
grpc_closure_init(&d->finish_recv, server_on_done_recv, elem);
+ return GRPC_ERROR_NONE;
}
static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- const grpc_call_stats *stats,
+ const grpc_call_final_info *final_info,
void *ignored) {
call_data *d = elem->call_data;
GPR_ASSERT(d != NULL);
diff --git a/src/core/ext/census/initialize.c b/src/core/ext/census/initialize.c
index 896276e44a..55cbbe8e95 100644
--- a/src/core/ext/census/initialize.c
+++ b/src/core/ext/census/initialize.c
@@ -32,19 +32,31 @@
*/
#include <grpc/census.h>
+#include "src/core/ext/census/base_resources.h"
+#include "src/core/ext/census/resource.h"
static int features_enabled = CENSUS_FEATURE_NONE;
int census_initialize(int features) {
if (features_enabled != CENSUS_FEATURE_NONE) {
// Must have been a previous call to census_initialize; return error
- return 1;
+ return -1;
}
- features_enabled = features;
- return 0;
+ features_enabled = features & CENSUS_FEATURE_ALL;
+ if (features & CENSUS_FEATURE_STATS) {
+ initialize_resources();
+ define_base_resources();
+ }
+
+ return features_enabled;
}
-void census_shutdown(void) { features_enabled = CENSUS_FEATURE_NONE; }
+void census_shutdown(void) {
+ if (features_enabled & CENSUS_FEATURE_STATS) {
+ shutdown_resources();
+ }
+ features_enabled = CENSUS_FEATURE_NONE;
+}
int census_supported(void) {
/* TODO(aveitch): improve this as we implement features... */
diff --git a/src/core/ext/census/placeholders.c b/src/core/ext/census/placeholders.c
index fe23d13971..9f99c5bdcf 100644
--- a/src/core/ext/census/placeholders.c
+++ b/src/core/ext/census/placeholders.c
@@ -62,48 +62,3 @@ int census_trace_scan_start(int consume) {
(void)consume;
abort();
}
-
-const census_aggregation *census_view_aggregrations(const census_view *view) {
- (void)view;
- abort();
-}
-
-census_view *census_view_create(uint32_t metric_id, const census_context *tags,
- const census_aggregation *aggregations,
- size_t naggregations) {
- (void)metric_id;
- (void)tags;
- (void)aggregations;
- (void)naggregations;
- abort();
-}
-
-const census_context *census_view_tags(const census_view *view) {
- (void)view;
- abort();
-}
-
-void census_view_delete(census_view *view) {
- (void)view;
- abort();
-}
-
-const census_view_data *census_view_get_data(const census_view *view) {
- (void)view;
- abort();
-}
-
-size_t census_view_metric(const census_view *view) {
- (void)view;
- abort();
-}
-
-size_t census_view_naggregations(const census_view *view) {
- (void)view;
- abort();
-}
-
-void census_view_reset(census_view *view) {
- (void)view;
- abort();
-}
diff --git a/src/core/ext/census/resource.c b/src/core/ext/census/resource.c
new file mode 100644
index 0000000000..ed44f004f9
--- /dev/null
+++ b/src/core/ext/census/resource.c
@@ -0,0 +1,312 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/ext/census/resource.h"
+#include "third_party/nanopb/pb_decode.h"
+
+#include <grpc/census.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+
+#include <stdbool.h>
+#include <string.h>
+
+// Protect local resource data structures.
+static gpr_mu resource_lock;
+
+// Deleteing and creating resources are relatively rare events, and should not
+// be done in the critical path of performance sensitive code. We record
+// current resource id's used in a simple array, and just search it each time
+// we need to assign a new id, or look up a resource.
+static resource **resources = NULL;
+
+// Number of entries in *resources
+static size_t n_resources = 0;
+
+// Number of defined resources
+static size_t n_defined_resources = 0;
+
+void initialize_resources(void) {
+ gpr_mu_init(&resource_lock);
+ gpr_mu_lock(&resource_lock);
+ GPR_ASSERT(resources == NULL && n_resources == 0 && n_defined_resources == 0);
+ gpr_mu_unlock(&resource_lock);
+}
+
+// Delete a resource given it's ID. The ID must be a valid resource ID. Must be
+// called with resource_lock held.
+static void delete_resource_locked(size_t rid) {
+ GPR_ASSERT(resources[rid] != NULL);
+ gpr_free(resources[rid]->name);
+ gpr_free(resources[rid]->description);
+ gpr_free(resources[rid]->numerators);
+ gpr_free(resources[rid]->denominators);
+ gpr_free(resources[rid]);
+ resources[rid] = NULL;
+ n_defined_resources--;
+}
+
+void shutdown_resources(void) {
+ gpr_mu_lock(&resource_lock);
+ for (size_t i = 0; i < n_resources; i++) {
+ if (resources[i] != NULL) {
+ delete_resource_locked(i);
+ }
+ }
+ GPR_ASSERT(n_defined_resources == 0);
+ gpr_free(resources);
+ resources = NULL;
+ n_resources = 0;
+ gpr_mu_unlock(&resource_lock);
+}
+
+// Check the contents of string fields in a resource proto.
+static bool validate_string(pb_istream_t *stream, const pb_field_t *field,
+ void **arg) {
+ resource *vresource = (resource *)*arg;
+ switch (field->tag) {
+ case google_census_Resource_name_tag:
+ // Name must have at least one character
+ if (stream->bytes_left == 0) {
+ gpr_log(GPR_INFO, "Zero-length Resource name.");
+ return false;
+ }
+ vresource->name = gpr_malloc(stream->bytes_left + 1);
+ vresource->name[stream->bytes_left] = '\0';
+ if (!pb_read(stream, (uint8_t *)vresource->name, stream->bytes_left)) {
+ return false;
+ }
+ // Can't have same name as an existing resource.
+ for (size_t i = 0; i < n_resources; i++) {
+ resource *compare = resources[i];
+ if (compare == vresource || compare == NULL) continue;
+ if (strcmp(compare->name, vresource->name) == 0) {
+ gpr_log(GPR_INFO, "Duplicate Resource name %s.", vresource->name);
+ return false;
+ }
+ }
+ break;
+ case google_census_Resource_description_tag:
+ if (stream->bytes_left == 0) {
+ return true;
+ }
+ vresource->description = gpr_malloc(stream->bytes_left + 1);
+ vresource->description[stream->bytes_left] = '\0';
+ if (!pb_read(stream, (uint8_t *)vresource->description,
+ stream->bytes_left)) {
+ return false;
+ }
+ break;
+ default:
+ // No other string fields in Resource. Print warning and skip.
+ gpr_log(GPR_INFO, "Unknown string field type in Resource protobuf.");
+ if (!pb_read(stream, NULL, stream->bytes_left)) {
+ return false;
+ }
+ break;
+ }
+ return true;
+}
+
+// Decode numerators/denominators in a stream. The `count` and `bup`
+// (BasicUnit pointer) are pointers to the approriate fields in a resource
+// struct.
+static bool validate_units_helper(pb_istream_t *stream, int *count,
+ google_census_Resource_BasicUnit **bup) {
+ while (stream->bytes_left) {
+ (*count)++;
+ // Have to allocate a new array of values. Normal case is 0 or 1, so
+ // this should normally not be an issue.
+ google_census_Resource_BasicUnit *new_bup =
+ gpr_malloc((size_t)*count * sizeof(google_census_Resource_BasicUnit));
+ if (*count != 1) {
+ memcpy(new_bup, *bup,
+ (size_t)(*count - 1) * sizeof(google_census_Resource_BasicUnit));
+ gpr_free(*bup);
+ }
+ *bup = new_bup;
+ uint64_t value;
+ if (!pb_decode_varint(stream, &value)) {
+ return false;
+ }
+ *(*bup + *count - 1) = (google_census_Resource_BasicUnit)value;
+ }
+ return true;
+}
+
+// Validate units field of a Resource proto.
+static bool validate_units(pb_istream_t *stream, const pb_field_t *field,
+ void **arg) {
+ resource *vresource = (resource *)(*arg);
+ switch (field->tag) {
+ case google_census_Resource_MeasurementUnit_numerator_tag:
+ return validate_units_helper(stream, &vresource->n_numerators,
+ &vresource->numerators);
+ break;
+ case google_census_Resource_MeasurementUnit_denominator_tag:
+ return validate_units_helper(stream, &vresource->n_denominators,
+ &vresource->denominators);
+ break;
+ default:
+ gpr_log(GPR_ERROR, "Unknown field type.");
+ return false;
+ break;
+ }
+ return true;
+}
+
+// Validate the contents of a Resource proto. `id` is the intended resource id.
+static bool validate_resource_pb(const uint8_t *resource_pb,
+ size_t resource_pb_size, size_t id) {
+ GPR_ASSERT(id < n_resources);
+ if (resource_pb == NULL) {
+ return false;
+ }
+ google_census_Resource vresource;
+ vresource.name.funcs.decode = &validate_string;
+ vresource.name.arg = resources[id];
+ vresource.description.funcs.decode = &validate_string;
+ vresource.description.arg = resources[id];
+ vresource.unit.numerator.funcs.decode = &validate_units;
+ vresource.unit.numerator.arg = resources[id];
+ vresource.unit.denominator.funcs.decode = &validate_units;
+ vresource.unit.denominator.arg = resources[id];
+
+ pb_istream_t stream =
+ pb_istream_from_buffer((uint8_t *)resource_pb, resource_pb_size);
+ if (!pb_decode(&stream, google_census_Resource_fields, &vresource)) {
+ return false;
+ }
+ // A Resource must have a name, a unit, with at least one numerator.
+ return (resources[id]->name != NULL && vresource.has_unit &&
+ resources[id]->n_numerators > 0);
+}
+
+// Allocate a blank resource, and return associated ID. Must be called with
+// resource_lock held.
+size_t allocate_resource(void) {
+ // use next_id to optimize expected placement of next new resource.
+ static size_t next_id = 0;
+ size_t id = n_resources; // resource ID - initialize to invalid value.
+ // Expand resources if needed.
+ if (n_resources == n_defined_resources) {
+ size_t new_n_resources = n_resources ? n_resources * 2 : 2;
+ resource **new_resources = gpr_malloc(new_n_resources * sizeof(resource *));
+ memcpy(new_resources, resources, n_resources * sizeof(resource *));
+ memset(new_resources + n_resources, 0,
+ (new_n_resources - n_resources) * sizeof(resource *));
+ gpr_free(resources);
+ resources = new_resources;
+ n_resources = new_n_resources;
+ id = n_defined_resources;
+ } else {
+ GPR_ASSERT(n_defined_resources < n_resources);
+ // Find a free id.
+ for (size_t base = 0; base < n_resources; base++) {
+ id = (next_id + base) % n_resources;
+ if (resources[id] == NULL) break;
+ }
+ }
+ GPR_ASSERT(id < n_resources && resources[id] == NULL);
+ resources[id] = gpr_malloc(sizeof(resource));
+ memset(resources[id], 0, sizeof(resource));
+ n_defined_resources++;
+ next_id = (id + 1) % n_resources;
+ return id;
+}
+
+int32_t census_define_resource(const uint8_t *resource_pb,
+ size_t resource_pb_size) {
+ if (resource_pb == NULL) {
+ return -1;
+ }
+ gpr_mu_lock(&resource_lock);
+ size_t id = allocate_resource();
+ // Validate pb, extract name.
+ if (!validate_resource_pb(resource_pb, resource_pb_size, id)) {
+ delete_resource_locked(id);
+ gpr_mu_unlock(&resource_lock);
+ return -1;
+ }
+ gpr_mu_unlock(&resource_lock);
+ return (int32_t)id;
+}
+
+void census_delete_resource(int32_t rid) {
+ gpr_mu_lock(&resource_lock);
+ if (rid >= 0 && (size_t)rid < n_resources && resources[rid] != NULL) {
+ delete_resource_locked((size_t)rid);
+ }
+ gpr_mu_unlock(&resource_lock);
+}
+
+int32_t census_resource_id(const char *name) {
+ gpr_mu_lock(&resource_lock);
+ for (int32_t id = 0; (size_t)id < n_resources; id++) {
+ if (resources[id] != NULL && strcmp(resources[id]->name, name) == 0) {
+ gpr_mu_unlock(&resource_lock);
+ return id;
+ }
+ }
+ gpr_mu_unlock(&resource_lock);
+ return -1;
+}
+
+int32_t define_resource(const resource *base) {
+ GPR_ASSERT(base != NULL && base->name != NULL && base->n_numerators > 0 &&
+ base->numerators != NULL);
+ gpr_mu_lock(&resource_lock);
+ size_t id = allocate_resource();
+ size_t len = strlen(base->name) + 1;
+ resources[id]->name = gpr_malloc(len);
+ memcpy(resources[id]->name, base->name, len);
+ if (base->description) {
+ len = strlen(base->description) + 1;
+ resources[id]->description = gpr_malloc(len);
+ memcpy(resources[id]->description, base->description, len);
+ }
+ resources[id]->prefix = base->prefix;
+ resources[id]->n_numerators = base->n_numerators;
+ len = (size_t)base->n_numerators * sizeof(*base->numerators);
+ resources[id]->numerators = gpr_malloc(len);
+ memcpy(resources[id]->numerators, base->numerators, len);
+ resources[id]->n_denominators = base->n_denominators;
+ if (base->n_denominators != 0) {
+ len = (size_t)base->n_denominators * sizeof(*base->denominators);
+ resources[id]->denominators = gpr_malloc(len);
+ memcpy(resources[id]->denominators, base->denominators, len);
+ }
+ gpr_mu_unlock(&resource_lock);
+ return (int32_t)id;
+}
diff --git a/src/python/grpcio/grpc/_cython/loader.c b/src/core/ext/census/resource.h
index 34bd897549..591bff07da 100644
--- a/src/python/grpcio/grpc/_cython/loader.c
+++ b/src/core/ext/census/resource.h
@@ -31,22 +31,33 @@
*
*/
-#include <Python.h>
-#include "loader.h"
+/* Census-internal resource definition and manipluation functions. */
+#ifndef GRPC_CORE_EXT_CENSUS_RESOURCE_H
+#define GRPC_CORE_EXT_CENSUS_RESOURCE_H
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cpluslus */
+#include <grpc/grpc.h>
+#include "src/core/ext/census/gen/census.pb.h"
-int pygrpc_load_core(char *path) { return 1; }
+/* Internal representation of a resource. */
+typedef struct {
+ char *name;
+ char *description;
+ int32_t prefix;
+ int n_numerators;
+ google_census_Resource_BasicUnit *numerators;
+ int n_denominators;
+ google_census_Resource_BasicUnit *denominators;
+} resource;
-// Cython doesn't have Py_AtExit bindings, so we call the C_API directly
-int pygrpc_initialize_core(void) {
- grpc_init();
- return Py_AtExit(grpc_shutdown) < 0 ? 0 : 1;
-}
+/* Initialize and shutdown the resources subsystem. */
+void initialize_resources(void);
+void shutdown_resources(void);
-#ifdef __cplusplus
-}
-#endif /* __cpluslus */
+/* Add a new resource, given a proposed resource structure. Returns the
+ resource ID, or -ve on failure.
+ TODO(aveitch): this function exists to support addition of the base
+ resources. It should be removed when we have the ability to add resources
+ from configuration files. */
+int32_t define_resource(const resource *base);
+#endif /* GRPC_CORE_EXT_CENSUS_RESOURCE_H */
diff --git a/src/core/ext/client_config/channel_connectivity.c b/src/core/ext/client_config/channel_connectivity.c
index c1220e3a8c..ce3c13a4ee 100644
--- a/src/core/ext/client_config/channel_connectivity.c
+++ b/src/core/ext/client_config/channel_connectivity.c
@@ -59,7 +59,7 @@ grpc_connectivity_state grpc_channel_check_connectivity_state(
}
gpr_log(GPR_ERROR,
"grpc_channel_check_connectivity_state called on something that is "
- "not a (u)client channel, but '%s'",
+ "not a client channel, but '%s'",
client_channel_elem->filter->name);
grpc_exec_ctx_finish(&exec_ctx);
return GRPC_CHANNEL_SHUTDOWN;
diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c
index a096435c98..2c0c4abffc 100644
--- a/src/core/ext/client_config/client_channel.c
+++ b/src/core/ext/client_config/client_channel.c
@@ -436,15 +436,17 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
}
/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem,
args->call_stack);
+ return GRPC_ERROR_NONE;
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- const grpc_call_stats *stats,
+ const grpc_call_final_info *final_info,
void *and_free_memory) {
grpc_subchannel_call_holder_destroy(exec_ctx, elem->call_data);
gpr_free(and_free_memory);
diff --git a/src/core/ext/client_config/lb_policy.h b/src/core/ext/client_config/lb_policy.h
index 3cfd041d3a..a2f5446fc6 100644
--- a/src/core/ext/client_config/lb_policy.h
+++ b/src/core/ext/client_config/lb_policy.h
@@ -73,7 +73,7 @@ struct grpc_lb_policy_vtable {
void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_closure *closure);
- /** try to enter a READY connectivity state */
+ /** Try to enter a READY connectivity state */
void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
/** check the current connectivity of the lb_policy */
@@ -82,7 +82,9 @@ struct grpc_lb_policy_vtable {
grpc_error **connectivity_error);
/** call notify when the connectivity state of a channel changes from *state.
- Updates *state with the new state of the policy */
+ Updates *state with the new state of the policy. Calling with a NULL \a
+ state cancels the subscription.
+ */
void (*notify_on_state_change)(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy,
grpc_connectivity_state *state,
@@ -125,7 +127,7 @@ void grpc_lb_policy_init(grpc_lb_policy *policy,
/** Given initial metadata in \a initial_metadata, find an appropriate
target for this rpc, and 'return' it by calling \a on_complete after setting
\a target.
- Picking can be asynchronous. Any IO should be done under \a pollset. */
+ Picking can be asynchronous. Any IO should be done under \a pollent. */
int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_polling_entity *pollent,
grpc_metadata_batch *initial_metadata,
@@ -147,8 +149,11 @@ void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx,
uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq);
+/** Try to enter a READY connectivity state */
void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+/* Call notify when the connectivity state of a channel changes from \a *state.
+ * Updates \a *state with the new state of the policy */
void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy,
grpc_connectivity_state *state,
diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c
index d089cd4399..df35904b85 100644
--- a/src/core/ext/client_config/subchannel.c
+++ b/src/core/ext/client_config/subchannel.c
@@ -702,19 +702,26 @@ grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
return GET_CONNECTED_SUBCHANNEL(c, acq);
}
-grpc_subchannel_call *grpc_connected_subchannel_create_call(
+grpc_error *grpc_connected_subchannel_create_call(
grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
- grpc_polling_entity *pollent) {
+ grpc_polling_entity *pollent, grpc_subchannel_call **call) {
grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
- grpc_subchannel_call *call =
- gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
- grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call);
- call->connection = con;
+ *call = gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
+ grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
+ (*call)->connection = con; // Ref is added below.
+ grpc_error *error =
+ grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, *call,
+ NULL, NULL, callstk);
+ if (error != GRPC_ERROR_NONE) {
+ const char *error_string = grpc_error_string(error);
+ gpr_log(GPR_ERROR, "error: %s", error_string);
+ grpc_error_free_string(error_string);
+ gpr_free(*call);
+ return error;
+ }
GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call");
- grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, call,
- NULL, NULL, callstk);
grpc_call_stack_set_pollset_or_pollset_set(exec_ctx, callstk, pollent);
- return call;
+ return GRPC_ERROR_NONE;
}
grpc_call_stack *grpc_subchannel_call_get_call_stack(
diff --git a/src/core/ext/client_config/subchannel.h b/src/core/ext/client_config/subchannel.h
index b6d39f5dc5..ae1d96e640 100644
--- a/src/core/ext/client_config/subchannel.h
+++ b/src/core/ext/client_config/subchannel.h
@@ -108,9 +108,9 @@ void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
/** construct a subchannel call */
-grpc_subchannel_call *grpc_connected_subchannel_create_call(
+grpc_error *grpc_connected_subchannel_create_call(
grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel,
- grpc_polling_entity *pollent);
+ grpc_polling_entity *pollent, grpc_subchannel_call **subchannel_call);
/** process a transport level op */
void grpc_connected_subchannel_process_transport_op(
diff --git a/src/core/ext/client_config/subchannel_call_holder.c b/src/core/ext/client_config/subchannel_call_holder.c
index b96a0ad093..be6d054af4 100644
--- a/src/core/ext/client_config/subchannel_call_holder.c
+++ b/src/core/ext/client_config/subchannel_call_holder.c
@@ -84,6 +84,11 @@ void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx,
gpr_free(holder->waiting_ops);
}
+// The logic here is fairly complicated, due to (a) the fact that we
+// need to handle the case where we receive the send op before the
+// initial metadata op, and (b) the need for efficiency, especially in
+// the streaming case.
+// TODO(ctiller): Explain this more thoroughly.
void grpc_subchannel_call_holder_perform_op(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call_holder *holder,
grpc_transport_stream_op *op) {
@@ -121,7 +126,8 @@ retry:
}
/* if this is a cancellation, then we can raise our cancelled flag */
if (op->cancel_error != GRPC_ERROR_NONE) {
- if (!gpr_atm_rel_cas(&holder->subchannel_call, 0, 1)) {
+ if (!gpr_atm_rel_cas(&holder->subchannel_call, 0,
+ (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
goto retry;
} else {
switch (holder->creation_phase) {
@@ -158,10 +164,17 @@ retry:
/* if we've got a subchannel, then let's ask it to create a call */
if (holder->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
holder->connected_subchannel != NULL) {
- gpr_atm_rel_store(
- &holder->subchannel_call,
- (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
- exec_ctx, holder->connected_subchannel, holder->pollent));
+ grpc_subchannel_call *subchannel_call = NULL;
+ grpc_error *error = grpc_connected_subchannel_create_call(
+ exec_ctx, holder->connected_subchannel, holder->pollent,
+ &subchannel_call);
+ if (error != GRPC_ERROR_NONE) {
+ subchannel_call = CANCELLED_CALL;
+ fail_locked(exec_ctx, holder, GRPC_ERROR_REF(error));
+ grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
+ }
+ gpr_atm_rel_store(&holder->subchannel_call,
+ (gpr_atm)(uintptr_t)subchannel_call);
retry_waiting_locked(exec_ctx, holder);
goto retry;
}
@@ -189,10 +202,17 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_ERROR_CREATE_REFERENCING(
"Cancelled before creating subchannel", &error, 1));
} else {
- gpr_atm_rel_store(
- &holder->subchannel_call,
- (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
- exec_ctx, holder->connected_subchannel, holder->pollent));
+ grpc_subchannel_call *subchannel_call = NULL;
+ grpc_error *new_error = grpc_connected_subchannel_create_call(
+ exec_ctx, holder->connected_subchannel, holder->pollent,
+ &subchannel_call);
+ if (new_error != GRPC_ERROR_NONE) {
+ new_error = grpc_error_add_child(new_error, error);
+ subchannel_call = CANCELLED_CALL;
+ fail_locked(exec_ctx, holder, new_error);
+ }
+ gpr_atm_rel_store(&holder->subchannel_call,
+ (gpr_atm)(uintptr_t)subchannel_call);
retry_waiting_locked(exec_ctx, holder);
}
gpr_mu_unlock(&holder->mu);
diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c
new file mode 100644
index 0000000000..af913d8a9d
--- /dev/null
+++ b/src/core/ext/lb_policy/grpclb/grpclb.c
@@ -0,0 +1,1042 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/** Implementation of the gRPC LB policy.
+ *
+ * This policy takes as input a set of resolved addresses {a1..an} for which the
+ * LB set was set (it's the resolver's responsibility to ensure this). That is
+ * to say, {a1..an} represent a collection of LB servers.
+ *
+ * An internal channel (\a glb_lb_policy.lb_channel) is created over {a1..an}.
+ * This channel behaves just like a regular channel. In particular, the
+ * constructed URI over the addresses a1..an will use the default pick first
+ * policy to select from this list of LB server backends.
+ *
+ * The first time the policy gets a request for a pick, a ping, or to exit the
+ * idle state, \a query_for_backends() is called. It creates an instance of \a
+ * lb_client_data, an internal struct meant to contain the data associated with
+ * the internal communication with the LB server. This instance is created via
+ * \a lb_client_data_create(). There, the call over lb_channel to pick-first
+ * from {a1..an} is created, the \a LoadBalancingRequest message is assembled
+ * and all necessary callbacks for the progress of the internal call configured.
+ *
+ * Back in \a query_for_backends(), the internal *streaming* call to the LB
+ * server (whichever address from {a1..an} pick-first chose) is kicked off.
+ * It'll progress over the callbacks configured in \a lb_client_data_create()
+ * (see the field docstrings of \a lb_client_data for more details).
+ *
+ * If the call fails with UNIMPLEMENTED, the original call will also fail.
+ * There's a misconfiguration somewhere: at least one of {a1..an} isn't a LB
+ * server, which contradicts the LB bit being set. If the internal call times
+ * out, the usual behavior of pick-first applies, continuing to pick from the
+ * list {a1..an}.
+ *
+ * Upon sucesss, a \a LoadBalancingResponse is expected in \a res_recv_cb. An
+ * invalid one results in the termination of the streaming call. A new streaming
+ * call should be created if possible, failing the original call otherwise.
+ * For a valid \a LoadBalancingResponse, the server list of actual backends is
+ * extracted. A Round Robin policy will be created from this list. There are two
+ * possible scenarios:
+ *
+ * 1. This is the first server list received. There was no previous instance of
+ * the Round Robin policy. \a rr_handover() will instantiate the RR policy
+ * and perform all the pending operations over it.
+ * 2. There's already a RR policy instance active. We need to introduce the new
+ * one build from the new serverlist, but taking care not to disrupt the
+ * operations in progress over the old RR instance. This is done by
+ * decreasing the reference count on the old policy. The moment no more
+ * references are held on the old RR policy, it'll be destroyed and \a
+ * rr_connectivity_changed notified with a \a GRPC_CHANNEL_SHUTDOWN state.
+ * At this point we can transition to a new RR instance safely, which is done
+ * once again via \a rr_handover().
+ *
+ *
+ * Once a RR policy instance is in place (and getting updated as described),
+ * calls to for a pick, a ping or a cancellation will be serviced right away by
+ * forwarding them to the RR instance. Any time there's no RR policy available
+ * (ie, right after the creation of the gRPCLB policy, if an empty serverlist
+ * is received, etc), pick/ping requests are added to a list of pending
+ * picks/pings to be flushed and serviced as part of \a rr_handover() the moment
+ * the RR policy instance becomes available.
+ *
+ * \see https://github.com/grpc/grpc/blob/master/doc/load-balancing.md for the
+ * high level design and details. */
+
+/* TODO(dgq):
+ * - Implement LB service forwarding (point 2c. in the doc's diagram).
+ */
+
+#include <string.h>
+
+#include <grpc/byte_buffer_reader.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/client_config/client_channel_factory.h"
+#include "src/core/ext/client_config/lb_policy_registry.h"
+#include "src/core/ext/client_config/parse_address.h"
+#include "src/core/ext/lb_policy/grpclb/grpclb.h"
+#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/channel.h"
+
+int grpc_lb_glb_trace = 0;
+
+typedef struct wrapped_rr_closure_arg {
+ /* the original closure. Usually a on_complete/notify cb for pick() and ping()
+ * calls against the internal RR instance, respectively. */
+ grpc_closure *wrapped_closure;
+
+ /* The RR instance related to the closure */
+ grpc_lb_policy *rr_policy;
+
+ /* when not NULL, represents a pending_{pick,ping} node to be freed upon
+ * closure execution */
+ void *owning_pending_node; /* to be freed if not NULL */
+} wrapped_rr_closure_arg;
+
+/* The \a on_complete closure passed as part of the pick requires keeping a
+ * reference to its associated round robin instance. We wrap this closure in
+ * order to unref the round robin instance upon its invocation */
+static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ wrapped_rr_closure_arg *wc_arg = arg;
+ if (wc_arg->rr_policy != NULL) {
+ if (grpc_lb_glb_trace) {
+ gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
+ (intptr_t)wc_arg->rr_policy);
+ }
+ GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
+ }
+ GPR_ASSERT(wc_arg->wrapped_closure != NULL);
+ grpc_exec_ctx_sched(exec_ctx, wc_arg->wrapped_closure, error, NULL);
+ gpr_free(wc_arg->owning_pending_node);
+}
+
+/* Linked list of pending pick requests. It stores all information needed to
+ * eventually call (Round Robin's) pick() on them. They mainly stay pending
+ * waiting for the RR policy to be created/updated.
+ *
+ * One particularity is the wrapping of the user-provided \a on_complete closure
+ * (in \a wrapped_on_complete and \a wrapped_on_complete_arg). This is needed in
+ * order to correctly unref the RR policy instance upon completion of the pick.
+ * See \a wrapped_rr_closure for details. */
+typedef struct pending_pick {
+ struct pending_pick *next;
+
+ /* polling entity for the pick()'s async notification */
+ grpc_polling_entity *pollent;
+
+ /* the initial metadata for the pick. See grpc_lb_policy_pick() */
+ grpc_metadata_batch *initial_metadata;
+
+ /* bitmask passed to pick() and used for selective cancelling. See
+ * grpc_lb_policy_cancel_picks() */
+ uint32_t initial_metadata_flags;
+
+ /* output argument where to store the pick()ed connected subchannel, or NULL
+ * upon error. */
+ grpc_connected_subchannel **target;
+
+ /* a closure wrapping the original on_complete one to be invoked once the
+ * pick() has completed (regardless of success) */
+ grpc_closure wrapped_on_complete;
+
+ /* args for wrapped_on_complete */
+ wrapped_rr_closure_arg wrapped_on_complete_arg;
+} pending_pick;
+
+static void add_pending_pick(pending_pick **root, grpc_polling_entity *pollent,
+ grpc_metadata_batch *initial_metadata,
+ uint32_t initial_metadata_flags,
+ grpc_connected_subchannel **target,
+ grpc_closure *on_complete) {
+ pending_pick *pp = gpr_malloc(sizeof(*pp));
+ memset(pp, 0, sizeof(pending_pick));
+ memset(&pp->wrapped_on_complete_arg, 0, sizeof(wrapped_rr_closure_arg));
+ pp->next = *root;
+ pp->pollent = pollent;
+ pp->target = target;
+ pp->initial_metadata = initial_metadata;
+ pp->initial_metadata_flags = initial_metadata_flags;
+ pp->wrapped_on_complete_arg.wrapped_closure = on_complete;
+ grpc_closure_init(&pp->wrapped_on_complete, wrapped_rr_closure,
+ &pp->wrapped_on_complete_arg);
+ *root = pp;
+}
+
+/* Same as the \a pending_pick struct but for ping operations */
+typedef struct pending_ping {
+ struct pending_ping *next;
+
+ /* a closure wrapping the original on_complete one to be invoked once the
+ * ping() has completed (regardless of success) */
+ grpc_closure wrapped_notify;
+
+ /* args for wrapped_notify */
+ wrapped_rr_closure_arg wrapped_notify_arg;
+} pending_ping;
+
+static void add_pending_ping(pending_ping **root, grpc_closure *notify) {
+ pending_ping *pping = gpr_malloc(sizeof(*pping));
+ memset(pping, 0, sizeof(pending_ping));
+ memset(&pping->wrapped_notify_arg, 0, sizeof(wrapped_rr_closure_arg));
+ pping->next = *root;
+ grpc_closure_init(&pping->wrapped_notify, wrapped_rr_closure,
+ &pping->wrapped_notify_arg);
+ pping->wrapped_notify_arg.wrapped_closure = notify;
+ *root = pping;
+}
+
+/*
+ * glb_lb_policy
+ */
+typedef struct rr_connectivity_data rr_connectivity_data;
+struct lb_client_data;
+static const grpc_lb_policy_vtable glb_lb_policy_vtable;
+typedef struct glb_lb_policy {
+ /** base policy: must be first */
+ grpc_lb_policy base;
+
+ /** mutex protecting remaining members */
+ gpr_mu mu;
+
+ grpc_client_channel_factory *cc_factory;
+
+ /** for communicating with the LB server */
+ grpc_channel *lb_channel;
+
+ /** the RR policy to use of the backend servers returned by the LB server */
+ grpc_lb_policy *rr_policy;
+
+ bool started_picking;
+
+ /** our connectivity state tracker */
+ grpc_connectivity_state_tracker state_tracker;
+
+ /** stores the deserialized response from the LB. May be NULL until one such
+ * response has arrived. */
+ grpc_grpclb_serverlist *serverlist;
+
+ /** list of picks that are waiting on RR's policy connectivity */
+ pending_pick *pending_picks;
+
+ /** list of pings that are waiting on RR's policy connectivity */
+ pending_ping *pending_pings;
+
+ /** client data associated with the LB server communication */
+ struct lb_client_data *lb_client;
+
+ /** for tracking of the RR connectivity */
+ rr_connectivity_data *rr_connectivity;
+
+ /* a wrapped (see \a wrapped_rr_closure) on-complete closure for readily
+ * available RR picks */
+ grpc_closure wrapped_on_complete;
+
+ /* arguments for the wrapped_on_complete closure */
+ wrapped_rr_closure_arg wc_arg;
+} glb_lb_policy;
+
+/* Keeps track and reacts to changes in connectivity of the RR instance */
+struct rr_connectivity_data {
+ grpc_closure on_change;
+ grpc_connectivity_state state;
+ glb_lb_policy *glb_policy;
+};
+
+static grpc_lb_policy *create_rr(grpc_exec_ctx *exec_ctx,
+ const grpc_grpclb_serverlist *serverlist,
+ glb_lb_policy *glb_policy) {
+ /* TODO(dgq): support mixed ip version */
+ GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0);
+ char **host_ports = gpr_malloc(sizeof(char *) * serverlist->num_servers);
+ for (size_t i = 0; i < serverlist->num_servers; ++i) {
+ gpr_join_host_port(&host_ports[i], serverlist->servers[i]->ip_address,
+ serverlist->servers[i]->port);
+ }
+
+ size_t uri_path_len;
+ char *concat_ipports = gpr_strjoin_sep(
+ (const char **)host_ports, serverlist->num_servers, ",", &uri_path_len);
+
+ grpc_lb_policy_args args;
+ args.client_channel_factory = glb_policy->cc_factory;
+ args.addresses = gpr_malloc(sizeof(grpc_resolved_addresses));
+ args.addresses->naddrs = serverlist->num_servers;
+ args.addresses->addrs =
+ gpr_malloc(sizeof(grpc_resolved_address) * args.addresses->naddrs);
+ size_t out_addrs_idx = 0;
+ for (size_t i = 0; i < serverlist->num_servers; ++i) {
+ grpc_uri uri;
+ struct sockaddr_storage sa;
+ size_t sa_len;
+ uri.path = host_ports[i];
+ if (parse_ipv4(&uri, &sa, &sa_len)) { /* TODO(dgq): add support for ipv6 */
+ memcpy(args.addresses->addrs[out_addrs_idx].addr, &sa, sa_len);
+ args.addresses->addrs[out_addrs_idx].len = sa_len;
+ ++out_addrs_idx;
+ } else {
+ gpr_log(GPR_ERROR, "Invalid LB service address '%s', ignoring.",
+ host_ports[i]);
+ }
+ }
+
+ grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
+
+ gpr_free(concat_ipports);
+ for (size_t i = 0; i < serverlist->num_servers; i++) {
+ gpr_free(host_ports[i]);
+ }
+ gpr_free(host_ports);
+ gpr_free(args.addresses->addrs);
+ gpr_free(args.addresses);
+ return rr;
+}
+
+static void rr_handover(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
+ grpc_error *error) {
+ GRPC_ERROR_REF(error);
+ glb_policy->rr_policy =
+ create_rr(exec_ctx, glb_policy->serverlist, glb_policy);
+
+ if (grpc_lb_glb_trace) {
+ gpr_log(GPR_INFO, "Created RR policy (0x%" PRIxPTR ")",
+ (intptr_t)glb_policy->rr_policy);
+ }
+ GPR_ASSERT(glb_policy->rr_policy != NULL);
+ glb_policy->rr_connectivity->state = grpc_lb_policy_check_connectivity(
+ exec_ctx, glb_policy->rr_policy, &error);
+ grpc_lb_policy_notify_on_state_change(
+ exec_ctx, glb_policy->rr_policy, &glb_policy->rr_connectivity->state,
+ &glb_policy->rr_connectivity->on_change);
+ grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker,
+ glb_policy->rr_connectivity->state, error,
+ "rr_handover");
+ grpc_lb_policy_exit_idle(exec_ctx, glb_policy->rr_policy);
+
+ /* flush pending ops */
+ pending_pick *pp;
+ while ((pp = glb_policy->pending_picks)) {
+ glb_policy->pending_picks = pp->next;
+ GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick");
+ pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy;
+ if (grpc_lb_glb_trace) {
+ gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "",
+ (intptr_t)glb_policy->rr_policy);
+ }
+ grpc_lb_policy_pick(exec_ctx, glb_policy->rr_policy, pp->pollent,
+ pp->initial_metadata, pp->initial_metadata_flags,
+ pp->target, &pp->wrapped_on_complete);
+ pp->wrapped_on_complete_arg.owning_pending_node = pp;
+ }
+
+ pending_ping *pping;
+ while ((pping = glb_policy->pending_pings)) {
+ glb_policy->pending_pings = pping->next;
+ GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping");
+ pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy;
+ if (grpc_lb_glb_trace) {
+ gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "",
+ (intptr_t)glb_policy->rr_policy);
+ }
+ grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy,
+ &pping->wrapped_notify);
+ pping->wrapped_notify_arg.owning_pending_node = pping;
+ }
+ GRPC_ERROR_UNREF(error);
+}
+
+static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ rr_connectivity_data *rr_conn_data = arg;
+ glb_lb_policy *glb_policy = rr_conn_data->glb_policy;
+ if (rr_conn_data->state == GRPC_CHANNEL_SHUTDOWN) {
+ if (glb_policy->serverlist != NULL) {
+ /* a RR policy is shutting down but there's a serverlist available ->
+ * perform a handover */
+ rr_handover(exec_ctx, glb_policy, error);
+ } else {
+ /* shutting down and no new serverlist available. Bail out. */
+ gpr_free(rr_conn_data);
+ }
+ } else {
+ if (error == GRPC_ERROR_NONE) {
+ /* RR not shutting down. Mimic the RR's policy state */
+ grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker,
+ rr_conn_data->state, error,
+ "rr_connectivity_changed");
+ /* resubscribe */
+ grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
+ &rr_conn_data->state,
+ &rr_conn_data->on_change);
+ } else { /* error */
+ gpr_free(rr_conn_data);
+ }
+ }
+ GRPC_ERROR_UNREF(error);
+}
+
+static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy_factory *factory,
+ grpc_lb_policy_args *args) {
+ glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
+ memset(glb_policy, 0, sizeof(*glb_policy));
+
+ /* All input addresses in args->addresses come from a resolver that claims
+ * they are LB services. It's the resolver's responsibility to make sure this
+ * policy is only instantiated and used in that case.
+ *
+ * Create a client channel over them to communicate with a LB service */
+ glb_policy->cc_factory = args->client_channel_factory;
+ GPR_ASSERT(glb_policy->cc_factory != NULL);
+ if (args->addresses->naddrs == 0) {
+ return NULL;
+ }
+
+ /* construct a target from the args->addresses, in the form
+ * ipvX://ip1:port1,ip2:port2,...
+ * TODO(dgq): support mixed ip version */
+ char **addr_strs = gpr_malloc(sizeof(char *) * args->addresses->naddrs);
+ addr_strs[0] =
+ grpc_sockaddr_to_uri((const struct sockaddr *)&args->addresses->addrs[0]);
+ for (size_t i = 1; i < args->addresses->naddrs; i++) {
+ GPR_ASSERT(grpc_sockaddr_to_string(
+ &addr_strs[i],
+ (const struct sockaddr *)&args->addresses->addrs[i],
+ true) == 0);
+ }
+ size_t uri_path_len;
+ char *target_uri_str = gpr_strjoin_sep(
+ (const char **)addr_strs, args->addresses->naddrs, ",", &uri_path_len);
+
+ /* will pick using pick_first */
+ glb_policy->lb_channel = grpc_client_channel_factory_create_channel(
+ exec_ctx, glb_policy->cc_factory, target_uri_str,
+ GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, NULL);
+
+ gpr_free(target_uri_str);
+ for (size_t i = 0; i < args->addresses->naddrs; i++) {
+ gpr_free(addr_strs[i]);
+ }
+ gpr_free(addr_strs);
+
+ if (glb_policy->lb_channel == NULL) {
+ gpr_free(glb_policy);
+ return NULL;
+ }
+
+ rr_connectivity_data *rr_connectivity =
+ gpr_malloc(sizeof(rr_connectivity_data));
+ memset(rr_connectivity, 0, sizeof(rr_connectivity_data));
+ grpc_closure_init(&rr_connectivity->on_change, rr_connectivity_changed,
+ rr_connectivity);
+ rr_connectivity->glb_policy = glb_policy;
+ glb_policy->rr_connectivity = rr_connectivity;
+
+ grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable);
+ gpr_mu_init(&glb_policy->mu);
+ grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
+ "grpclb");
+ return &glb_policy->base;
+}
+
+static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+ glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
+ GPR_ASSERT(glb_policy->pending_picks == NULL);
+ GPR_ASSERT(glb_policy->pending_pings == NULL);
+ grpc_channel_destroy(glb_policy->lb_channel);
+ glb_policy->lb_channel = NULL;
+ grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker);
+ if (glb_policy->serverlist != NULL) {
+ grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
+ }
+ gpr_mu_destroy(&glb_policy->mu);
+ gpr_free(glb_policy);
+}
+
+static void lb_client_data_destroy(struct lb_client_data *lb_client);
+static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+ glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
+ gpr_mu_lock(&glb_policy->mu);
+
+ pending_pick *pp = glb_policy->pending_picks;
+ glb_policy->pending_picks = NULL;
+ pending_ping *pping = glb_policy->pending_pings;
+ glb_policy->pending_pings = NULL;
+ gpr_mu_unlock(&glb_policy->mu);
+
+ while (pp != NULL) {
+ pending_pick *next = pp->next;
+ *pp->target = NULL;
+ grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete, GRPC_ERROR_NONE,
+ NULL);
+ gpr_free(pp);
+ pp = next;
+ }
+
+ while (pping != NULL) {
+ pending_ping *next = pping->next;
+ grpc_exec_ctx_sched(exec_ctx, &pping->wrapped_notify, GRPC_ERROR_NONE,
+ NULL);
+ pping = next;
+ }
+
+ if (glb_policy->rr_policy) {
+ /* unsubscribe */
+ grpc_lb_policy_notify_on_state_change(
+ exec_ctx, glb_policy->rr_policy, NULL,
+ &glb_policy->rr_connectivity->on_change);
+ GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown");
+ }
+
+ lb_client_data_destroy(glb_policy->lb_client);
+ glb_policy->lb_client = NULL;
+
+ grpc_connectivity_state_set(
+ exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_SHUTDOWN,
+ GRPC_ERROR_CREATE("Channel Shutdown"), "glb_shutdown");
+}
+
+static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ grpc_connected_subchannel **target) {
+ glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
+ gpr_mu_lock(&glb_policy->mu);
+ pending_pick *pp = glb_policy->pending_picks;
+ glb_policy->pending_picks = NULL;
+ while (pp != NULL) {
+ pending_pick *next = pp->next;
+ if (pp->target == target) {
+ grpc_polling_entity_del_from_pollset_set(
+ exec_ctx, pp->pollent, glb_policy->base.interested_parties);
+ *target = NULL;
+ grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete,
+ GRPC_ERROR_CANCELLED, NULL);
+ gpr_free(pp);
+ } else {
+ pp->next = glb_policy->pending_picks;
+ glb_policy->pending_picks = pp;
+ }
+ pp = next;
+ }
+ gpr_mu_unlock(&glb_policy->mu);
+}
+
+static grpc_call *lb_client_data_get_call(struct lb_client_data *lb_client);
+static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ uint32_t initial_metadata_flags_mask,
+ uint32_t initial_metadata_flags_eq) {
+ glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
+ gpr_mu_lock(&glb_policy->mu);
+ if (glb_policy->lb_client != NULL) {
+ /* cancel the call to the load balancer service, if any */
+ grpc_call_cancel(lb_client_data_get_call(glb_policy->lb_client), NULL);
+ }
+ pending_pick *pp = glb_policy->pending_picks;
+ glb_policy->pending_picks = NULL;
+ while (pp != NULL) {
+ pending_pick *next = pp->next;
+ if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
+ initial_metadata_flags_eq) {
+ grpc_polling_entity_del_from_pollset_set(
+ exec_ctx, pp->pollent, glb_policy->base.interested_parties);
+ grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete,
+ GRPC_ERROR_CANCELLED, NULL);
+ gpr_free(pp);
+ } else {
+ pp->next = glb_policy->pending_picks;
+ glb_policy->pending_picks = pp;
+ }
+ pp = next;
+ }
+ gpr_mu_unlock(&glb_policy->mu);
+}
+
+static void query_for_backends(grpc_exec_ctx *exec_ctx,
+ glb_lb_policy *glb_policy);
+static void start_picking(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy) {
+ glb_policy->started_picking = true;
+ query_for_backends(exec_ctx, glb_policy);
+}
+
+static void glb_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+ glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
+ gpr_mu_lock(&glb_policy->mu);
+ if (!glb_policy->started_picking) {
+ start_picking(exec_ctx, glb_policy);
+ }
+ gpr_mu_unlock(&glb_policy->mu);
+}
+
+static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ grpc_polling_entity *pollent,
+ grpc_metadata_batch *initial_metadata,
+ uint32_t initial_metadata_flags,
+ grpc_connected_subchannel **target,
+ grpc_closure *on_complete) {
+ glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
+ gpr_mu_lock(&glb_policy->mu);
+ int r;
+
+ if (glb_policy->rr_policy != NULL) {
+ if (grpc_lb_glb_trace) {
+ gpr_log(GPR_INFO, "about to PICK from 0x%" PRIxPTR "",
+ (intptr_t)glb_policy->rr_policy);
+ }
+ GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick");
+ memset(&glb_policy->wc_arg, 0, sizeof(wrapped_rr_closure_arg));
+ glb_policy->wc_arg.rr_policy = glb_policy->rr_policy;
+ glb_policy->wc_arg.wrapped_closure = on_complete;
+ grpc_closure_init(&glb_policy->wrapped_on_complete, wrapped_rr_closure,
+ &glb_policy->wc_arg);
+ r = grpc_lb_policy_pick(exec_ctx, glb_policy->rr_policy, pollent,
+ initial_metadata, initial_metadata_flags, target,
+ &glb_policy->wrapped_on_complete);
+ if (r != 0) {
+ /* the call to grpc_lb_policy_pick has been sychronous. Unreffing the RR
+ * policy and notify the original callback */
+ glb_policy->wc_arg.wrapped_closure = NULL;
+ if (grpc_lb_glb_trace) {
+ gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
+ (intptr_t)glb_policy->wc_arg.rr_policy);
+ }
+ GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->wc_arg.rr_policy, "glb_pick");
+ grpc_exec_ctx_sched(exec_ctx, glb_policy->wc_arg.wrapped_closure,
+ GRPC_ERROR_NONE, NULL);
+ }
+ } else {
+ grpc_polling_entity_add_to_pollset_set(exec_ctx, pollent,
+ glb_policy->base.interested_parties);
+ add_pending_pick(&glb_policy->pending_picks, pollent, initial_metadata,
+ initial_metadata_flags, target, on_complete);
+
+ if (!glb_policy->started_picking) {
+ start_picking(exec_ctx, glb_policy);
+ }
+ r = 0;
+ }
+ gpr_mu_unlock(&glb_policy->mu);
+ return r;
+}
+
+static grpc_connectivity_state glb_check_connectivity(
+ grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ grpc_error **connectivity_error) {
+ glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
+ grpc_connectivity_state st;
+ gpr_mu_lock(&glb_policy->mu);
+ st = grpc_connectivity_state_check(&glb_policy->state_tracker,
+ connectivity_error);
+ gpr_mu_unlock(&glb_policy->mu);
+ return st;
+}
+
+static void glb_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ grpc_closure *closure) {
+ glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
+ gpr_mu_lock(&glb_policy->mu);
+ if (glb_policy->rr_policy) {
+ grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy, closure);
+ } else {
+ add_pending_ping(&glb_policy->pending_pings, closure);
+ if (!glb_policy->started_picking) {
+ start_picking(exec_ctx, glb_policy);
+ }
+ }
+ gpr_mu_unlock(&glb_policy->mu);
+}
+
+static void glb_notify_on_state_change(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *pol,
+ grpc_connectivity_state *current,
+ grpc_closure *notify) {
+ glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
+ gpr_mu_lock(&glb_policy->mu);
+ grpc_connectivity_state_notify_on_state_change(
+ exec_ctx, &glb_policy->state_tracker, current, notify);
+
+ gpr_mu_unlock(&glb_policy->mu);
+}
+
+/*
+ * lb_client_data
+ *
+ * Used internally for the client call to the LB */
+typedef struct lb_client_data {
+ gpr_mu mu;
+
+ /* called once initial metadata's been sent */
+ grpc_closure md_sent;
+
+ /* called once initial metadata's been received */
+ grpc_closure md_rcvd;
+
+ /* called once the LoadBalanceRequest has been sent to the LB server. See
+ * src/proto/grpc/.../load_balancer.proto */
+ grpc_closure req_sent;
+
+ /* A response from the LB server has been received (or error). Process it */
+ grpc_closure res_rcvd;
+
+ /* After the client has sent a close to the LB server */
+ grpc_closure close_sent;
+
+ /* ... and the status from the LB server has been received */
+ grpc_closure srv_status_rcvd;
+
+ grpc_call *lb_call; /* streaming call to the LB server, */
+ gpr_timespec deadline; /* for the streaming call to the LB server */
+
+ grpc_metadata_array initial_metadata_recv; /* initial MD from LB server */
+ grpc_metadata_array trailing_metadata_recv; /* trailing MD from LB server */
+
+ /* what's being sent to the LB server. Note that its value may vary if the LB
+ * server indicates a redirect. */
+ grpc_byte_buffer *request_payload;
+
+ /* response from the LB server, if any. Processed in res_recv_cb() */
+ grpc_byte_buffer *response_payload;
+
+ /* the call's status and status detailset in srv_status_rcvd_cb() */
+ grpc_status_code status;
+ char *status_details;
+ size_t status_details_capacity;
+
+ /* pointer back to the enclosing policy */
+ glb_lb_policy *glb_policy;
+} lb_client_data;
+
+static void md_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
+static void md_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
+static void req_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
+static void res_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
+static void close_sent_cb(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error);
+static void srv_status_rcvd_cb(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error);
+
+static lb_client_data *lb_client_data_create(glb_lb_policy *glb_policy) {
+ lb_client_data *lb_client = gpr_malloc(sizeof(lb_client_data));
+ memset(lb_client, 0, sizeof(lb_client_data));
+
+ gpr_mu_init(&lb_client->mu);
+ grpc_closure_init(&lb_client->md_sent, md_sent_cb, lb_client);
+
+ grpc_closure_init(&lb_client->md_rcvd, md_recv_cb, lb_client);
+ grpc_closure_init(&lb_client->req_sent, req_sent_cb, lb_client);
+ grpc_closure_init(&lb_client->res_rcvd, res_recv_cb, lb_client);
+ grpc_closure_init(&lb_client->close_sent, close_sent_cb, lb_client);
+ grpc_closure_init(&lb_client->srv_status_rcvd, srv_status_rcvd_cb, lb_client);
+
+ /* TODO(dgq): get the deadline from the client config instead of fabricating
+ * one here. */
+ lb_client->deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+ gpr_time_from_seconds(3, GPR_TIMESPAN));
+
+ /* Note the following LB call progresses every time there's activity in \a
+ * glb_policy->base.interested_parties, which is comprised of the polling
+ * entities passed to glb_pick(). */
+ lb_client->lb_call = grpc_channel_create_pollset_set_call(
+ glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS,
+ glb_policy->base.interested_parties, "/BalanceLoad",
+ NULL, /* FIXME(dgq): which "host" value to use? */
+ lb_client->deadline, NULL);
+
+ grpc_metadata_array_init(&lb_client->initial_metadata_recv);
+ grpc_metadata_array_init(&lb_client->trailing_metadata_recv);
+
+ grpc_grpclb_request *request = grpc_grpclb_request_create(
+ "load.balanced.service.name"); /* FIXME(dgq): get the name of the load
+ balanced service from the resolver */
+ gpr_slice request_payload_slice = grpc_grpclb_request_encode(request);
+ lb_client->request_payload =
+ grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+ gpr_slice_unref(request_payload_slice);
+ grpc_grpclb_request_destroy(request);
+
+ lb_client->status_details = NULL;
+ lb_client->status_details_capacity = 0;
+ lb_client->glb_policy = glb_policy;
+ return lb_client;
+}
+
+static void lb_client_data_destroy(lb_client_data *lb_client) {
+ grpc_call_destroy(lb_client->lb_call);
+ grpc_metadata_array_destroy(&lb_client->initial_metadata_recv);
+ grpc_metadata_array_destroy(&lb_client->trailing_metadata_recv);
+
+ grpc_byte_buffer_destroy(lb_client->request_payload);
+
+ gpr_free(lb_client->status_details);
+ gpr_mu_destroy(&lb_client->mu);
+ gpr_free(lb_client);
+}
+static grpc_call *lb_client_data_get_call(lb_client_data *lb_client) {
+ return lb_client->lb_call;
+}
+
+/*
+ * Auxiliary functions and LB client callbacks.
+ */
+static void query_for_backends(grpc_exec_ctx *exec_ctx,
+ glb_lb_policy *glb_policy) {
+ GPR_ASSERT(glb_policy->lb_channel != NULL);
+
+ glb_policy->lb_client = lb_client_data_create(glb_policy);
+ grpc_call_error call_error;
+ grpc_op ops[1];
+ memset(ops, 0, sizeof(ops));
+ grpc_op *op = ops;
+ op->op = GRPC_OP_SEND_INITIAL_METADATA;
+ op->data.send_initial_metadata.count = 0;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ call_error = grpc_call_start_batch_and_execute(
+ exec_ctx, glb_policy->lb_client->lb_call, ops, (size_t)(op - ops),
+ &glb_policy->lb_client->md_sent);
+ GPR_ASSERT(GRPC_CALL_OK == call_error);
+
+ op = ops;
+ op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+ op->data.recv_status_on_client.trailing_metadata =
+ &glb_policy->lb_client->trailing_metadata_recv;
+ op->data.recv_status_on_client.status = &glb_policy->lb_client->status;
+ op->data.recv_status_on_client.status_details =
+ &glb_policy->lb_client->status_details;
+ op->data.recv_status_on_client.status_details_capacity =
+ &glb_policy->lb_client->status_details_capacity;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ call_error = grpc_call_start_batch_and_execute(
+ exec_ctx, glb_policy->lb_client->lb_call, ops, (size_t)(op - ops),
+ &glb_policy->lb_client->srv_status_rcvd);
+ GPR_ASSERT(GRPC_CALL_OK == call_error);
+}
+
+static void md_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+ lb_client_data *lb_client = arg;
+ GPR_ASSERT(lb_client->lb_call);
+ grpc_op ops[1];
+ memset(ops, 0, sizeof(ops));
+ grpc_op *op = ops;
+ op->op = GRPC_OP_RECV_INITIAL_METADATA;
+ op->data.recv_initial_metadata = &lb_client->initial_metadata_recv;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ grpc_call_error call_error = grpc_call_start_batch_and_execute(
+ exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
+ &lb_client->md_rcvd);
+ GPR_ASSERT(GRPC_CALL_OK == call_error);
+}
+
+static void md_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+ lb_client_data *lb_client = arg;
+ GPR_ASSERT(lb_client->lb_call);
+ grpc_op ops[1];
+ memset(ops, 0, sizeof(ops));
+ grpc_op *op = ops;
+
+ op->op = GRPC_OP_SEND_MESSAGE;
+ op->data.send_message = lb_client->request_payload;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ grpc_call_error call_error = grpc_call_start_batch_and_execute(
+ exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
+ &lb_client->req_sent);
+ GPR_ASSERT(GRPC_CALL_OK == call_error);
+}
+
+static void req_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+ lb_client_data *lb_client = arg;
+
+ grpc_op ops[1];
+ memset(ops, 0, sizeof(ops));
+ grpc_op *op = ops;
+
+ op->op = GRPC_OP_RECV_MESSAGE;
+ op->data.recv_message = &lb_client->response_payload;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ grpc_call_error call_error = grpc_call_start_batch_and_execute(
+ exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
+ &lb_client->res_rcvd);
+ GPR_ASSERT(GRPC_CALL_OK == call_error);
+}
+
+static void res_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+ lb_client_data *lb_client = arg;
+ grpc_op ops[2];
+ memset(ops, 0, sizeof(ops));
+ grpc_op *op = ops;
+ if (lb_client->response_payload != NULL) {
+ /* Received data from the LB server. Look inside
+ * lb_client->response_payload, for
+ * a serverlist. */
+ grpc_byte_buffer_reader bbr;
+ grpc_byte_buffer_reader_init(&bbr, lb_client->response_payload);
+ gpr_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
+ grpc_byte_buffer_destroy(lb_client->response_payload);
+ grpc_grpclb_serverlist *serverlist =
+ grpc_grpclb_response_parse_serverlist(response_slice);
+ if (serverlist != NULL) {
+ gpr_slice_unref(response_slice);
+ if (grpc_lb_glb_trace) {
+ gpr_log(GPR_INFO, "Serverlist with %zu servers received",
+ serverlist->num_servers);
+ }
+
+ /* update serverlist */
+ if (serverlist->num_servers > 0) {
+ if (grpc_grpclb_serverlist_equals(lb_client->glb_policy->serverlist,
+ serverlist)) {
+ if (grpc_lb_glb_trace) {
+ gpr_log(GPR_INFO,
+ "Incoming server list identical to current, ignoring.");
+ }
+ } else { /* new serverlist */
+ if (lb_client->glb_policy->serverlist != NULL) {
+ /* dispose of the old serverlist */
+ grpc_grpclb_destroy_serverlist(lb_client->glb_policy->serverlist);
+ }
+ /* and update the copy in the glb_lb_policy instance */
+ lb_client->glb_policy->serverlist = serverlist;
+ }
+ if (lb_client->glb_policy->rr_policy == NULL) {
+ /* initial "handover", in this case from a null RR policy, meaning
+ * it'll just create the first RR policy instance */
+ rr_handover(exec_ctx, lb_client->glb_policy, error);
+ } else {
+ /* unref the RR policy, eventually leading to its substitution with a
+ * new one constructed from the received serverlist (see
+ * rr_connectivity_changed) */
+ GRPC_LB_POLICY_UNREF(exec_ctx, lb_client->glb_policy->rr_policy,
+ "serverlist_received");
+ }
+ } else {
+ if (grpc_lb_glb_trace) {
+ gpr_log(GPR_INFO,
+ "Received empty server list. Picks will stay pending until a "
+ "response with > 0 servers is received");
+ }
+ }
+
+ /* keep listening for serverlist updates */
+ op->op = GRPC_OP_RECV_MESSAGE;
+ op->data.recv_message = &lb_client->response_payload;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ const grpc_call_error call_error = grpc_call_start_batch_and_execute(
+ exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
+ &lb_client->res_rcvd); /* loop */
+ GPR_ASSERT(GRPC_CALL_OK == call_error);
+ return;
+ }
+
+ GPR_ASSERT(serverlist == NULL);
+ gpr_log(GPR_ERROR, "Invalid LB response received: '%s'",
+ gpr_dump_slice(response_slice, GPR_DUMP_ASCII));
+ gpr_slice_unref(response_slice);
+
+ /* Disconnect from server returning invalid response. */
+ op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ grpc_call_error call_error = grpc_call_start_batch_and_execute(
+ exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
+ &lb_client->close_sent);
+ GPR_ASSERT(GRPC_CALL_OK == call_error);
+ }
+ /* empty payload: call cancelled by server. Cleanups happening in
+ * srv_status_rcvd_cb */
+}
+
+static void close_sent_cb(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ if (grpc_lb_glb_trace) {
+ gpr_log(GPR_INFO,
+ "Close from LB client sent. Waiting from server status now");
+ }
+}
+
+static void srv_status_rcvd_cb(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ lb_client_data *lb_client = arg;
+ if (grpc_lb_glb_trace) {
+ gpr_log(GPR_INFO,
+ "status from lb server received. Status = %d, Details = '%s', "
+ "Capaticy "
+ "= %zu",
+ lb_client->status, lb_client->status_details,
+ lb_client->status_details_capacity);
+ }
+ /* TODO(dgq): deal with stream termination properly (fire up another one? fail
+ * the original call?) */
+}
+
+/* Code wiring the policy with the rest of the core */
+static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
+ glb_destroy, glb_shutdown, glb_pick,
+ glb_cancel_pick, glb_cancel_picks, glb_ping_one,
+ glb_exit_idle, glb_check_connectivity, glb_notify_on_state_change};
+
+static void glb_factory_ref(grpc_lb_policy_factory *factory) {}
+
+static void glb_factory_unref(grpc_lb_policy_factory *factory) {}
+
+static const grpc_lb_policy_factory_vtable glb_factory_vtable = {
+ glb_factory_ref, glb_factory_unref, glb_create, "grpclb"};
+
+static grpc_lb_policy_factory glb_lb_policy_factory = {&glb_factory_vtable};
+
+grpc_lb_policy_factory *grpc_glb_lb_factory_create() {
+ return &glb_lb_policy_factory;
+}
+
+/* Plugin registration */
+void grpc_lb_policy_grpclb_init() {
+ grpc_register_lb_policy(grpc_glb_lb_factory_create());
+ grpc_register_tracer("glb", &grpc_lb_glb_trace);
+}
+
+void grpc_lb_policy_grpclb_shutdown() {}
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/core/ext/lb_policy/grpclb/grpclb.h
index 8e5c9a8ce2..83552b4fa0 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.h
+++ b/src/core/ext/lb_policy/grpclb/grpclb.h
@@ -31,20 +31,14 @@
*
*/
-/* TODO(atash) remove cruft */
-#ifndef PYGRPC_CYTHON_WINDOWS_IMPORTS_H_
-#define PYGRPC_CYTHON_WINDOWS_IMPORTS_H_
+#ifndef GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_H
+#define GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_H
-#include <grpc/support/port_platform.h>
+#include "src/core/ext/client_config/lb_policy_factory.h"
-#include <grpc/byte_buffer.h>
-#include <grpc/byte_buffer_reader.h>
-#include <grpc/compression.h>
-#include <grpc/grpc.h>
-#include <grpc/grpc_security.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/time.h>
-#include <grpc/status.h>
+/** Returns a load balancing factory for the glb policy, which tries to connect
+ * to a load balancing server to decide the next successfully connected
+ * subchannel to pick. */
+grpc_lb_policy_factory *grpc_glb_lb_factory_create();
-#endif
+#endif /* GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_H */
diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.c b/src/core/ext/lb_policy/grpclb/load_balancer_api.c
index 59b89997dd..f4720a1345 100644
--- a/src/core/ext/lb_policy/grpclb/load_balancer_api.c
+++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.c
@@ -38,9 +38,15 @@
#include <grpc/support/alloc.h>
typedef struct decode_serverlist_arg {
- int first_pass;
- int i;
+ /* The first pass counts the number of servers in the server list. The second
+ * one allocates and decodes. */
+ bool first_pass;
+ /* The decoding callback is invoked once per server in serverlist. Remember
+ * which index of the serverlist are we currently decoding */
+ size_t decoding_idx;
+ /* Populated after the first pass. Number of server in the input serverlist */
size_t num_servers;
+ /* The decoded serverlist */
grpc_grpclb_server **servers;
} decode_serverlist_arg;
@@ -48,23 +54,24 @@ typedef struct decode_serverlist_arg {
static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field,
void **arg) {
decode_serverlist_arg *dec_arg = *arg;
- if (dec_arg->first_pass != 0) { /* first pass */
+ if (dec_arg->first_pass) { /* count how many server do we have */
grpc_grpclb_server server;
if (!pb_decode(stream, grpc_lb_v1_Server_fields, &server)) {
return false;
}
dec_arg->num_servers++;
- } else { /* second pass */
+ } else { /* second pass. Actually decode. */
grpc_grpclb_server *server = gpr_malloc(sizeof(grpc_grpclb_server));
+ memset(server, 0, sizeof(grpc_grpclb_server));
GPR_ASSERT(dec_arg->num_servers > 0);
- if (dec_arg->i == 0) { /* first iteration of second pass */
+ if (dec_arg->decoding_idx == 0) { /* first iteration of second pass */
dec_arg->servers =
gpr_malloc(sizeof(grpc_grpclb_server *) * dec_arg->num_servers);
}
if (!pb_decode(stream, grpc_lb_v1_Server_fields, server)) {
return false;
}
- dec_arg->servers[dec_arg->i++] = server;
+ dec_arg->servers[dec_arg->decoding_idx++] = server;
}
return true;
@@ -102,57 +109,59 @@ void grpc_grpclb_request_destroy(grpc_grpclb_request *request) {
gpr_free(request);
}
-grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response) {
- bool status;
+typedef grpc_lb_v1_LoadBalanceResponse grpc_grpclb_response;
+grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse(
+ gpr_slice encoded_grpc_grpclb_response) {
pb_istream_t stream =
- pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
- GPR_SLICE_LENGTH(encoded_response));
- grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
- memset(res, 0, sizeof(*res));
- status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, res);
- if (!status) {
- grpc_grpclb_response_destroy(res);
+ pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_grpc_grpclb_response),
+ GPR_SLICE_LENGTH(encoded_grpc_grpclb_response));
+ grpc_grpclb_response res;
+ memset(&res, 0, sizeof(grpc_grpclb_response));
+ if (!pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res)) {
return NULL;
}
- return res;
+ grpc_grpclb_initial_response *initial_res =
+ gpr_malloc(sizeof(grpc_grpclb_initial_response));
+ memcpy(initial_res, &res.initial_response,
+ sizeof(grpc_grpclb_initial_response));
+
+ return initial_res;
}
grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
- gpr_slice encoded_response) {
+ gpr_slice encoded_grpc_grpclb_response) {
bool status;
decode_serverlist_arg arg;
pb_istream_t stream =
- pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
- GPR_SLICE_LENGTH(encoded_response));
+ pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_grpc_grpclb_response),
+ GPR_SLICE_LENGTH(encoded_grpc_grpclb_response));
pb_istream_t stream_at_start = stream;
- grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
- memset(res, 0, sizeof(*res));
+ grpc_grpclb_response res;
+ memset(&res, 0, sizeof(grpc_grpclb_response));
memset(&arg, 0, sizeof(decode_serverlist_arg));
- res->server_list.servers.funcs.decode = decode_serverlist;
- res->server_list.servers.arg = &arg;
- arg.first_pass = 1;
- status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, res);
+ res.server_list.servers.funcs.decode = decode_serverlist;
+ res.server_list.servers.arg = &arg;
+ arg.first_pass = true;
+ status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res);
if (!status) {
- grpc_grpclb_response_destroy(res);
return NULL;
}
- arg.first_pass = 0;
+ arg.first_pass = false;
status =
- pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, res);
+ pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, &res);
if (!status) {
- grpc_grpclb_response_destroy(res);
return NULL;
}
grpc_grpclb_serverlist *sl = gpr_malloc(sizeof(grpc_grpclb_serverlist));
+ memset(sl, 0, sizeof(*sl));
sl->num_servers = arg.num_servers;
sl->servers = arg.servers;
- if (res->server_list.has_expiration_interval) {
- sl->expiration_interval = res->server_list.expiration_interval;
+ if (res.server_list.has_expiration_interval) {
+ sl->expiration_interval = res.server_list.expiration_interval;
}
- grpc_grpclb_response_destroy(res);
return sl;
}
@@ -167,6 +176,72 @@ void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist) {
gpr_free(serverlist);
}
-void grpc_grpclb_response_destroy(grpc_grpclb_response *response) {
+grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy(
+ const grpc_grpclb_serverlist *sl) {
+ grpc_grpclb_serverlist *copy = gpr_malloc(sizeof(grpc_grpclb_serverlist));
+ memset(copy, 0, sizeof(grpc_grpclb_serverlist));
+ copy->num_servers = sl->num_servers;
+ memcpy(&copy->expiration_interval, &sl->expiration_interval,
+ sizeof(grpc_grpclb_duration));
+ copy->servers = gpr_malloc(sizeof(grpc_grpclb_server *) * sl->num_servers);
+ for (size_t i = 0; i < sl->num_servers; i++) {
+ copy->servers[i] = gpr_malloc(sizeof(grpc_grpclb_server));
+ memcpy(copy->servers[i], sl->servers[i], sizeof(grpc_grpclb_server));
+ }
+ return copy;
+}
+
+bool grpc_grpclb_serverlist_equals(const grpc_grpclb_serverlist *lhs,
+ const grpc_grpclb_serverlist *rhs) {
+ if ((lhs == NULL) || (rhs == NULL)) {
+ return false;
+ }
+ if (lhs->num_servers != rhs->num_servers) {
+ return false;
+ }
+ if (grpc_grpclb_duration_compare(&lhs->expiration_interval,
+ &rhs->expiration_interval) != 0) {
+ return false;
+ }
+ for (size_t i = 0; i < lhs->num_servers; i++) {
+ if (!grpc_grpclb_server_equals(lhs->servers[i], rhs->servers[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool grpc_grpclb_server_equals(const grpc_grpclb_server *lhs,
+ const grpc_grpclb_server *rhs) {
+ return memcmp(lhs, rhs, sizeof(grpc_grpclb_server)) == 0;
+}
+
+int grpc_grpclb_duration_compare(const grpc_grpclb_duration *lhs,
+ const grpc_grpclb_duration *rhs) {
+ GPR_ASSERT(lhs && rhs);
+ if (lhs->has_seconds && rhs->has_seconds) {
+ if (lhs->seconds < rhs->seconds) return -1;
+ if (lhs->seconds > rhs->seconds) return 1;
+ } else if (lhs->has_seconds) {
+ return 1;
+ } else if (rhs->has_seconds) {
+ return -1;
+ }
+
+ GPR_ASSERT(lhs->seconds == rhs->seconds);
+ if (lhs->has_nanos && rhs->has_nanos) {
+ if (lhs->nanos < rhs->nanos) return -1;
+ if (lhs->nanos > rhs->nanos) return 1;
+ } else if (lhs->has_nanos) {
+ return 1;
+ } else if (rhs->has_nanos) {
+ return -1;
+ }
+
+ return 0;
+}
+
+void grpc_grpclb_initial_response_destroy(
+ grpc_grpclb_initial_response *response) {
gpr_free(response);
}
diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.h b/src/core/ext/lb_policy/grpclb/load_balancer_api.h
index 71b5616d0c..9726c87a37 100644
--- a/src/core/ext/lb_policy/grpclb/load_balancer_api.h
+++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.h
@@ -46,7 +46,7 @@ extern "C" {
#define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128
typedef grpc_lb_v1_LoadBalanceRequest grpc_grpclb_request;
-typedef grpc_lb_v1_LoadBalanceResponse grpc_grpclb_response;
+typedef grpc_lb_v1_InitialLoadBalanceResponse grpc_grpclb_initial_response;
typedef grpc_lb_v1_Server grpc_grpclb_server;
typedef grpc_lb_v1_Duration grpc_grpclb_duration;
typedef struct grpc_grpclb_serverlist {
@@ -64,19 +64,37 @@ gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request);
/** Destroy \a request */
void grpc_grpclb_request_destroy(grpc_grpclb_request *request);
-/** Parse (ie, decode) the bytes in \a encoded_response as a \a
- * grpc_grpclb_response */
-grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response);
+/** Parse (ie, decode) the bytes in \a encoded_grpc_grpclb_response as a \a
+ * grpc_grpclb_initial_response */
+grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse(
+ gpr_slice encoded_grpc_grpclb_response);
+
+/** Parse the list of servers from an encoded \a grpc_grpclb_response */
+grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
+ gpr_slice encoded_grpc_grpclb_response);
+
+/** Return a copy of \a sl. The caller is responsible for calling \a
+ * grpc_grpclb_destroy_serverlist on the returned copy. */
+grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy(
+ const grpc_grpclb_serverlist *sl);
+
+bool grpc_grpclb_serverlist_equals(const grpc_grpclb_serverlist *lhs,
+ const grpc_grpclb_serverlist *rhs);
+
+bool grpc_grpclb_server_equals(const grpc_grpclb_server *lhs,
+ const grpc_grpclb_server *rhs);
/** Destroy \a serverlist */
void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist);
-/** Parse the list of servers from an encoded \a grpc_grpclb_response */
-grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
- gpr_slice encoded_response);
+/** Compare \a lhs against \a rhs and return 0 if \a lhs and \a rhs are equal,
+ * < 0 if \a lhs represents a duration shorter than \a rhs and > 0 otherwise */
+int grpc_grpclb_duration_compare(const grpc_grpclb_duration *lhs,
+ const grpc_grpclb_duration *rhs);
-/** Destroy \a response */
-void grpc_grpclb_response_destroy(grpc_grpclb_response *response);
+/** Destroy \a initial_response */
+void grpc_grpclb_initial_response_destroy(
+ grpc_grpclb_initial_response *response);
#ifdef __cplusplus
}
diff --git a/src/core/ext/load_reporting/load_reporting.c b/src/core/ext/load_reporting/load_reporting.c
index 9e4d32676f..df1ea0ec9a 100644
--- a/src/core/ext/load_reporting/load_reporting.c
+++ b/src/core/ext/load_reporting/load_reporting.c
@@ -42,42 +42,12 @@
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/surface/channel_init.h"
-struct grpc_load_reporting_config {
- grpc_load_reporting_fn fn;
- void *user_data;
-};
-
-grpc_load_reporting_config *grpc_load_reporting_config_create(
- grpc_load_reporting_fn fn, void *user_data) {
- GPR_ASSERT(fn != NULL);
- grpc_load_reporting_config *lrc =
- gpr_malloc(sizeof(grpc_load_reporting_config));
- lrc->fn = fn;
- lrc->user_data = user_data;
- return lrc;
-}
-
-grpc_load_reporting_config *grpc_load_reporting_config_copy(
- grpc_load_reporting_config *src) {
- return grpc_load_reporting_config_create(src->fn, src->user_data);
-}
-
-void grpc_load_reporting_config_destroy(grpc_load_reporting_config *lrc) {
- gpr_free(lrc);
-}
-
-void grpc_load_reporting_config_call(
- grpc_load_reporting_config *lrc,
- const grpc_load_reporting_call_data *call_data) {
- lrc->fn(call_data, lrc->user_data);
-}
-
static bool is_load_reporting_enabled(const grpc_channel_args *a) {
if (a == NULL) return false;
for (size_t i = 0; i < a->num_args; i++) {
if (0 == strcmp(a->args[i].key, GRPC_ARG_ENABLE_LOAD_REPORTING)) {
- return a->args[i].type == GRPC_ARG_POINTER &&
- a->args[i].value.pointer.p != NULL;
+ return a->args[i].type == GRPC_ARG_INTEGER &&
+ a->args[i].value.integer != 0;
}
}
return false;
@@ -94,37 +64,17 @@ static bool maybe_add_load_reporting_filter(grpc_channel_stack_builder *builder,
return true;
}
-static void lrd_arg_destroy(void *p) { grpc_load_reporting_config_destroy(p); }
-
-static void *lrd_arg_copy(void *p) {
- return grpc_load_reporting_config_copy(p);
-}
-
-static int lrd_arg_cmp(void *a, void *b) {
- grpc_load_reporting_config *lhs = a;
- grpc_load_reporting_config *rhs = b;
- return !(lhs->fn == rhs->fn && lhs->user_data == rhs->user_data);
-}
-
-static const grpc_arg_pointer_vtable lrd_ptr_vtable = {
- lrd_arg_copy, lrd_arg_destroy, lrd_arg_cmp};
-
-grpc_arg grpc_load_reporting_config_create_arg(
- grpc_load_reporting_config *lrc) {
+grpc_arg grpc_load_reporting_enable_arg() {
grpc_arg arg;
- arg.type = GRPC_ARG_POINTER;
+ arg.type = GRPC_ARG_INTEGER;
arg.key = GRPC_ARG_ENABLE_LOAD_REPORTING;
- arg.value.pointer.p = lrc;
- arg.value.pointer.vtable = &lrd_ptr_vtable;
+ arg.value.integer = 1;
return arg;
}
/* Plugin registration */
void grpc_load_reporting_plugin_init(void) {
- grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
- maybe_add_load_reporting_filter,
- (void *)&grpc_load_reporting_filter);
grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
maybe_add_load_reporting_filter,
(void *)&grpc_load_reporting_filter);
diff --git a/src/core/ext/load_reporting/load_reporting.h b/src/core/ext/load_reporting/load_reporting.h
index 316cd89bd7..e37817d8c2 100644
--- a/src/core/ext/load_reporting/load_reporting.h
+++ b/src/core/ext/load_reporting/load_reporting.h
@@ -34,42 +34,47 @@
#ifndef GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H
#define GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H
-#include "src/core/lib/iomgr/closure.h"
-#include "src/core/lib/surface/call.h"
+#include <grpc/impl/codegen/grpc_types.h>
+#include "src/core/lib/channel/channel_stack.h"
-typedef struct grpc_load_reporting_config grpc_load_reporting_config;
+/** Metadata key for initial metadata coming from clients */
+/* TODO(dgq): change to the final value TBD */
+#define GRPC_LOAD_REPORTING_INITIAL_MD_KEY "load-reporting-initial"
-/** Call information to be passed to the provided load reporting function upon
- * completion of the call */
-typedef struct grpc_load_reporting_call_data {
- const grpc_call_stats *stats; /**< Stats for the call */
- const char *trailing_md_string; /**< LR trailing metadata info */
-} grpc_load_reporting_call_data;
+/** Metadata key for trailing metadata from servers */
+/* TODO(dgq): change to the final value TBD */
+#define GRPC_LOAD_REPORTING_TRAILING_MD_KEY "load-reporting-trailing"
-/** Custom function to be called by the load reporting filter. */
-typedef void (*grpc_load_reporting_fn)(
- const grpc_load_reporting_call_data *call_data, void *user_data);
+/** Identifiers for the invocation point of the users LR callback */
+typedef enum grpc_load_reporting_source {
+ GRPC_LR_POINT_UNKNOWN = 0,
+ GRPC_LR_POINT_CHANNEL_CREATION,
+ GRPC_LR_POINT_CHANNEL_DESTRUCTION,
+ GRPC_LR_POINT_CALL_CREATION,
+ GRPC_LR_POINT_CALL_DESTRUCTION
+} grpc_load_reporting_source;
-/** Register \a fn as the function to be invoked by the load reporting filter.
- * \a fn will be invoked at the beginning and at the end of the call.
- *
- * For the first invocation, \a fn's first argument
- * (grpc_load_reporting_call_data*) will be NULL. \a user_data is always passed
- * as-is. */
-grpc_load_reporting_config *grpc_load_reporting_config_create(
- grpc_load_reporting_fn fn, void *user_data);
+/** Call information to be passed to the provided LR callback. */
+typedef struct grpc_load_reporting_call_data {
+ const grpc_load_reporting_source source; /**< point of last data update. */
+
+ /** Unique identifier for the channel associated with the data */
+ intptr_t channel_id;
-grpc_load_reporting_config *grpc_load_reporting_config_copy(
- grpc_load_reporting_config *src);
+ /** Unique identifier for the call associated with the data. If the call
+ * hasn't been created yet, it'll have a value of zero. */
+ intptr_t call_id;
-void grpc_load_reporting_config_destroy(grpc_load_reporting_config *lrc);
+ /** Only valid when \a source is \a GRPC_LR_POINT_CALL_DESTRUCTION, that is,
+ * once the call has completed */
+ const grpc_call_final_info *final_info;
-/** Invoke the function registered by \a grpc_load_reporting_init. */
-void grpc_load_reporting_config_call(
- grpc_load_reporting_config *lrc,
- const grpc_load_reporting_call_data *call_data);
+ const char *initial_md_string; /**< value string for LR's initial md key */
+ const char *trailing_md_string; /**< value string for LR's trailing md key */
+ const char *method_name; /**< Corresponds to :path header */
+} grpc_load_reporting_call_data;
/** Return a \a grpc_arg enabling load reporting */
-grpc_arg grpc_load_reporting_config_create_arg(grpc_load_reporting_config *lrc);
+grpc_arg grpc_load_reporting_enable_arg();
#endif /* GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H */
diff --git a/src/core/ext/load_reporting/load_reporting_filter.c b/src/core/ext/load_reporting/load_reporting_filter.c
index f372f88c3a..394f0cb832 100644
--- a/src/core/ext/load_reporting/load_reporting_filter.c
+++ b/src/core/ext/load_reporting/load_reporting_filter.c
@@ -31,6 +31,7 @@
*
*/
+#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
@@ -42,38 +43,112 @@
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/transport/static_metadata.h"
-typedef struct call_data { const char *trailing_md_string; } call_data;
+typedef struct call_data {
+ intptr_t id; /**< an id unique to the call */
+ char *trailing_md_string;
+ char *initial_md_string;
+ const char *service_method;
+
+ /* stores the recv_initial_metadata op's ready closure, which we wrap with our
+ * own (on_initial_md_ready) in order to capture the incoming initial metadata
+ * */
+ grpc_closure *ops_recv_initial_metadata_ready;
+
+ /* to get notified of the availability of the incoming initial metadata. */
+ grpc_closure on_initial_md_ready;
+ grpc_metadata_batch *recv_initial_metadata;
+} call_data;
+
typedef struct channel_data {
- gpr_mu mu;
- grpc_load_reporting_config *lrc;
+ intptr_t id; /**< an id unique to the channel */
} channel_data;
-static void invoke_lr_fn_locked(grpc_load_reporting_config *lrc,
- grpc_load_reporting_call_data *lr_call_data) {
- GPR_TIMER_BEGIN("load_reporting_config_fn", 0);
- grpc_load_reporting_config_call(lrc, lr_call_data);
- GPR_TIMER_END("load_reporting_config_fn", 0);
+typedef struct {
+ grpc_call_element *elem;
+ grpc_exec_ctx *exec_ctx;
+} recv_md_filter_args;
+
+static grpc_mdelem *recv_md_filter(void *user_data, grpc_mdelem *md) {
+ recv_md_filter_args *a = user_data;
+ grpc_call_element *elem = a->elem;
+ call_data *calld = elem->call_data;
+
+ if (md->key == GRPC_MDSTR_PATH) {
+ calld->service_method = grpc_mdstr_as_c_string(md->value);
+ } else if (md->key == GRPC_MDSTR_LOAD_REPORTING_INITIAL) {
+ calld->initial_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value));
+ return NULL;
+ }
+
+ return md;
+}
+
+static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data,
+ grpc_error *err) {
+ grpc_call_element *elem = user_data;
+ call_data *calld = elem->call_data;
+
+ if (err == GRPC_ERROR_NONE) {
+ recv_md_filter_args a;
+ a.elem = elem;
+ a.exec_ctx = exec_ctx;
+ grpc_metadata_batch_filter(calld->recv_initial_metadata, recv_md_filter,
+ &a);
+ if (calld->service_method == NULL) {
+ err =
+ grpc_error_add_child(err, GRPC_ERROR_CREATE("Missing :path header"));
+ }
+ } else {
+ GRPC_ERROR_REF(err);
+ }
+ calld->ops_recv_initial_metadata_ready->cb(
+ exec_ctx, calld->ops_recv_initial_metadata_ready->cb_arg, err);
+ GRPC_ERROR_UNREF(err);
}
/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
call_data *calld = elem->call_data;
memset(calld, 0, sizeof(call_data));
+
+ calld->id = (intptr_t)args->call_stack;
+ grpc_closure_init(&calld->on_initial_md_ready, on_initial_md_ready, elem);
+
+ /* TODO(dgq): do something with the data
+ channel_data *chand = elem->channel_data;
+ grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_CREATION,
+ (intptr_t)chand->id,
+ (intptr_t)calld->id,
+ NULL,
+ NULL,
+ NULL,
+ NULL};
+ */
+
+ return GRPC_ERROR_NONE;
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- const grpc_call_stats *stats, void *ignored) {
- channel_data *chand = elem->channel_data;
+ const grpc_call_final_info *final_info,
+ void *ignored) {
call_data *calld = elem->call_data;
- grpc_load_reporting_call_data lr_call_data = {stats,
- calld->trailing_md_string};
-
- gpr_mu_lock(&chand->mu);
- invoke_lr_fn_locked(chand->lrc, &lr_call_data);
- gpr_mu_unlock(&chand->mu);
+ /* TODO(dgq): do something with the data
+ channel_data *chand = elem->channel_data;
+ grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_DESTRUCTION,
+ (intptr_t)chand->id,
+ (intptr_t)calld->id,
+ final_info,
+ calld->initial_md_string,
+ calld->trailing_md_string,
+ calld->service_method};
+ */
+
+ gpr_free(calld->initial_md_string);
+ gpr_free(calld->trailing_md_string);
}
/* Constructor for channel_data */
@@ -85,37 +160,40 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
channel_data *chand = elem->channel_data;
memset(chand, 0, sizeof(channel_data));
- gpr_mu_init(&chand->mu);
- for (size_t i = 0; i < args->channel_args->num_args; i++) {
- if (0 == strcmp(args->channel_args->args[i].key,
- GRPC_ARG_ENABLE_LOAD_REPORTING)) {
- grpc_load_reporting_config *arg_lrc =
- args->channel_args->args[i].value.pointer.p;
- chand->lrc = grpc_load_reporting_config_copy(arg_lrc);
- GPR_ASSERT(chand->lrc != NULL);
- break;
- }
- }
- GPR_ASSERT(chand->lrc != NULL); /* arg actually found */
-
- gpr_mu_lock(&chand->mu);
- invoke_lr_fn_locked(chand->lrc, NULL);
- gpr_mu_unlock(&chand->mu);
+ chand->id = (intptr_t)args->channel_stack;
+
+ /* TODO(dgq): do something with the data
+ grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CHANNEL_CREATION,
+ (intptr_t)chand,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL};
+ */
}
/* Destructor for channel data */
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
+ /* TODO(dgq): do something with the data
channel_data *chand = elem->channel_data;
- gpr_mu_destroy(&chand->mu);
- grpc_load_reporting_config_destroy(chand->lrc);
+ grpc_load_reporting_call_data lr_call_data = {
+ GRPC_LR_POINT_CHANNEL_DESTRUCTION,
+ (intptr_t)chand->id,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL};
+ */
}
static grpc_mdelem *lr_trailing_md_filter(void *user_data, grpc_mdelem *md) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
- if (md->key == GRPC_MDSTR_LOAD_REPORTING) {
+ if (md->key == GRPC_MDSTR_LOAD_REPORTING_TRAILING) {
calld->trailing_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value));
return NULL;
}
@@ -127,8 +205,14 @@ static void lr_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
GPR_TIMER_BEGIN("lr_start_transport_stream_op", 0);
+ call_data *calld = elem->call_data;
- if (op->send_trailing_metadata) {
+ if (op->recv_initial_metadata) {
+ calld->recv_initial_metadata = op->recv_initial_metadata;
+ /* substitute our callback for the higher callback */
+ calld->ops_recv_initial_metadata_ready = op->recv_initial_metadata_ready;
+ op->recv_initial_metadata_ready = &calld->on_initial_md_ready;
+ } else if (op->send_trailing_metadata) {
grpc_metadata_batch_filter(op->send_trailing_metadata,
lr_trailing_md_filter, elem);
}
diff --git a/src/core/ext/load_reporting/load_reporting_filter.h b/src/core/ext/load_reporting/load_reporting_filter.h
index f69cd6fdc6..160ed32af9 100644
--- a/src/core/ext/load_reporting/load_reporting_filter.h
+++ b/src/core/ext/load_reporting/load_reporting_filter.h
@@ -34,6 +34,7 @@
#ifndef GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_FILTER_H
#define GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_FILTER_H
+#include "src/core/ext/load_reporting/load_reporting.h"
#include "src/core/lib/channel/channel_stack.h"
extern const grpc_channel_filter grpc_load_reporting_filter;
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
index 85f9efb3b6..cbaa75a90a 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
@@ -45,6 +45,7 @@
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/compress_filter.h"
+#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/channel/http_client_filter.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/surface/api_trace.h"
@@ -63,6 +64,8 @@ typedef struct {
grpc_endpoint *tcp;
grpc_closure connected;
+
+ grpc_handshake_manager *handshake_mgr;
} connector;
static void connector_ref(grpc_connector *con) {
@@ -74,6 +77,7 @@ static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
connector *c = (connector *)con;
if (gpr_unref(&c->refs)) {
/* c->initial_string_buffer does not need to be destroyed */
+ grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr);
gpr_free(c);
}
}
@@ -83,9 +87,29 @@ static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
connector_unref(exec_ctx, arg);
}
+static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint,
+ grpc_channel_args *args,
+ gpr_slice_buffer *read_buffer, void *user_data,
+ grpc_error *error) {
+ connector *c = user_data;
+ if (error != GRPC_ERROR_NONE) {
+ grpc_channel_args_destroy(args);
+ gpr_free(read_buffer);
+ } else {
+ c->result->transport =
+ grpc_create_chttp2_transport(exec_ctx, args, endpoint, 1);
+ GPR_ASSERT(c->result->transport);
+ grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport,
+ read_buffer);
+ c->result->channel_args = args;
+ }
+ grpc_closure *notify = c->notify;
+ c->notify = NULL;
+ grpc_exec_ctx_sched(exec_ctx, notify, error, NULL);
+}
+
static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
connector *c = arg;
- grpc_closure *notify;
grpc_endpoint *tcp = c->tcp;
if (tcp != NULL) {
if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) {
@@ -97,19 +121,17 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
connector_ref(arg);
grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
&c->initial_string_sent);
+ } else {
+ grpc_handshake_manager_do_handshake(
+ exec_ctx, c->handshake_mgr, tcp, c->args.channel_args,
+ c->args.deadline, NULL /* acceptor */, on_handshake_done, c);
}
- c->result->transport =
- grpc_create_chttp2_transport(exec_ctx, c->args.channel_args, tcp, 1);
- grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
- 0);
- GPR_ASSERT(c->result->transport);
- c->result->channel_args = grpc_channel_args_copy(c->args.channel_args);
} else {
memset(c->result, 0, sizeof(*c->result));
+ grpc_closure *notify = c->notify;
+ c->notify = NULL;
+ grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL);
}
- notify = c->notify;
- c->notify = NULL;
- grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL);
}
static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {}
@@ -171,6 +193,7 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
memset(c, 0, sizeof(*c));
c->base.vtable = &connector_vtable;
gpr_ref_init(&c->refs, 1);
+ c->handshake_mgr = grpc_handshake_manager_create();
args->args = final_args;
s = grpc_subchannel_create(exec_ctx, &c->base, args);
grpc_connector_unref(exec_ctx, &c->base);
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c b/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
index ca435c25ce..b2c5e5b088 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
@@ -75,7 +75,7 @@ grpc_channel *grpc_insecure_channel_create_from_fd(
grpc_channel *channel = grpc_channel_create(
&exec_ctx, target, final_args, GRPC_CLIENT_DIRECT_CHANNEL, transport);
grpc_channel_args_destroy(final_args);
- grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0);
+ grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL);
grpc_exec_ctx_finish(&exec_ctx);
diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
index 9acacbd92d..9e2bdd758f 100644
--- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
+++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
@@ -44,6 +44,7 @@
#include "src/core/ext/client_config/resolver_registry.h"
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"
@@ -69,6 +70,11 @@ typedef struct {
grpc_endpoint *newly_connecting_endpoint;
grpc_closure connected_closure;
+
+ grpc_handshake_manager *handshake_mgr;
+
+ // TODO(roth): Remove once we eliminate on_secure_handshake_done().
+ grpc_channel_args *tmp_args;
} connector;
static void connector_ref(grpc_connector *con) {
@@ -80,6 +86,8 @@ static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
connector *c = (connector *)con;
if (gpr_unref(&c->refs)) {
/* c->initial_string_buffer does not need to be destroyed */
+ grpc_channel_args_destroy(c->tmp_args);
+ grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr);
gpr_free(c);
}
}
@@ -89,7 +97,6 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *secure_endpoint,
grpc_auth_context *auth_context) {
connector *c = arg;
- grpc_closure *notify;
gpr_mu_lock(&c->mu);
grpc_error *error = GRPC_ERROR_NONE;
if (c->connecting_endpoint == NULL) {
@@ -107,28 +114,47 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_unlock(&c->mu);
c->result->transport = grpc_create_chttp2_transport(
exec_ctx, c->args.channel_args, secure_endpoint, 1);
- grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
- 0);
+ grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL);
auth_context_arg = grpc_auth_context_to_arg(auth_context);
- c->result->channel_args = grpc_channel_args_copy_and_add(
- c->args.channel_args, &auth_context_arg, 1);
+ c->result->channel_args =
+ grpc_channel_args_copy_and_add(c->tmp_args, &auth_context_arg, 1);
}
- notify = c->notify;
+ grpc_closure *notify = c->notify;
c->notify = NULL;
grpc_exec_ctx_sched(exec_ctx, notify, error, NULL);
}
+static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint,
+ grpc_channel_args *args,
+ gpr_slice_buffer *read_buffer, void *user_data,
+ grpc_error *error) {
+ connector *c = user_data;
+ c->tmp_args = args;
+ if (error != GRPC_ERROR_NONE) {
+ gpr_free(read_buffer);
+ grpc_closure *notify = c->notify;
+ c->notify = NULL;
+ grpc_exec_ctx_sched(exec_ctx, notify, error, NULL);
+ } else {
+ // TODO(roth, jboeuf): Convert security connector handshaking to use new
+ // handshake API, and then move the code from on_secure_handshake_done()
+ // into this function.
+ grpc_channel_security_connector_do_handshake(
+ exec_ctx, c->security_connector, endpoint, read_buffer,
+ c->args.deadline, on_secure_handshake_done, c);
+ }
+}
+
static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
connector *c = arg;
- grpc_channel_security_connector_do_handshake(
- exec_ctx, c->security_connector, c->connecting_endpoint, c->args.deadline,
- on_secure_handshake_done, c);
+ grpc_handshake_manager_do_handshake(
+ exec_ctx, c->handshake_mgr, c->connecting_endpoint, c->args.channel_args,
+ c->args.deadline, NULL /* acceptor */, on_handshake_done, c);
}
static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
connector *c = arg;
- grpc_closure *notify;
grpc_endpoint *tcp = c->newly_connecting_endpoint;
if (tcp != NULL) {
gpr_mu_lock(&c->mu);
@@ -144,13 +170,13 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
&c->initial_string_sent);
} else {
- grpc_channel_security_connector_do_handshake(
- exec_ctx, c->security_connector, tcp, c->args.deadline,
- on_secure_handshake_done, c);
+ grpc_handshake_manager_do_handshake(
+ exec_ctx, c->handshake_mgr, tcp, c->args.channel_args,
+ c->args.deadline, NULL /* acceptor */, on_handshake_done, c);
}
} else {
memset(c->result, 0, sizeof(*c->result));
- notify = c->notify;
+ grpc_closure *notify = c->notify;
c->notify = NULL;
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL);
}
@@ -229,6 +255,7 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
memset(c, 0, sizeof(*c));
c->base.vtable = &connector_vtable;
c->security_connector = f->security_connector;
+ c->handshake_mgr = grpc_handshake_manager_create();
gpr_mu_init(&c->mu);
gpr_ref_init(&c->refs, 1);
args->args = final_args;
diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
index e5c987925c..f0e07429fa 100644
--- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
+++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
@@ -37,35 +37,76 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
+
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/channel/http_server_filter.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/tcp_server.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/server.h"
-static void new_transport(grpc_exec_ctx *exec_ctx, void *server,
- grpc_endpoint *tcp, grpc_pollset *accepting_pollset,
- grpc_tcp_server_acceptor *acceptor) {
- /*
- * Beware that the call to grpc_create_chttp2_transport() has to happen before
- * grpc_tcp_server_destroy(). This is fine here, but similar code
- * asynchronously doing a handshake instead of calling grpc_tcp_server_start()
- * (as in server_secure_chttp2.c) needs to add synchronization to avoid this
- * case.
- */
- grpc_transport *transport = grpc_create_chttp2_transport(
- exec_ctx, grpc_server_get_channel_args(server), tcp, 0);
- grpc_server_setup_transport(exec_ctx, server, transport, accepting_pollset,
- grpc_server_get_channel_args(server));
- grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
+typedef struct server_connect_state {
+ grpc_server *server;
+ grpc_pollset *accepting_pollset;
+ grpc_tcp_server_acceptor *acceptor;
+ grpc_handshake_manager *handshake_mgr;
+} server_connect_state;
+
+static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint,
+ grpc_channel_args *args,
+ gpr_slice_buffer *read_buffer, void *user_data,
+ grpc_error *error) {
+ server_connect_state *state = user_data;
+ if (error != GRPC_ERROR_NONE) {
+ const char *error_str = grpc_error_string(error);
+ gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str);
+ grpc_error_free_string(error_str);
+ GRPC_ERROR_UNREF(error);
+ grpc_handshake_manager_shutdown(exec_ctx, state->handshake_mgr);
+ gpr_free(read_buffer);
+ } else {
+ // Beware that the call to grpc_create_chttp2_transport() has to happen
+ // before grpc_tcp_server_destroy(). This is fine here, but similar code
+ // asynchronously doing a handshake instead of calling
+ // grpc_tcp_server_start() (as in server_secure_chttp2.c) needs to add
+ // synchronization to avoid this case.
+ grpc_transport *transport =
+ grpc_create_chttp2_transport(exec_ctx, args, endpoint, 0);
+ grpc_server_setup_transport(exec_ctx, state->server, transport,
+ state->accepting_pollset,
+ grpc_server_get_channel_args(state->server));
+ grpc_chttp2_transport_start_reading(exec_ctx, transport, read_buffer);
+ }
+ // Clean up.
+ grpc_channel_args_destroy(args);
+ grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr);
+ gpr_free(state);
+}
+
+static void on_accept(grpc_exec_ctx *exec_ctx, void *server, grpc_endpoint *tcp,
+ grpc_pollset *accepting_pollset,
+ grpc_tcp_server_acceptor *acceptor) {
+ server_connect_state *state = gpr_malloc(sizeof(server_connect_state));
+ state->server = server;
+ state->accepting_pollset = accepting_pollset;
+ state->acceptor = acceptor;
+ state->handshake_mgr = grpc_handshake_manager_create();
+ // TODO(roth): We should really get this timeout value from channel
+ // args instead of hard-coding it.
+ const gpr_timespec deadline = gpr_time_add(
+ gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN));
+ grpc_handshake_manager_do_handshake(
+ exec_ctx, state->handshake_mgr, tcp, grpc_server_get_channel_args(server),
+ deadline, acceptor, on_handshake_done, state);
}
/* Server callback: start listening on our ports */
static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp,
grpc_pollset **pollsets, size_t pollset_count) {
grpc_tcp_server *tcp = tcpp;
- grpc_tcp_server_start(exec_ctx, tcp, pollsets, pollset_count, new_transport,
+ grpc_tcp_server_start(exec_ctx, tcp, pollsets, pollset_count, on_accept,
server);
}
@@ -74,6 +115,7 @@ static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp,
static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp,
grpc_closure *destroy_done) {
grpc_tcp_server *tcp = tcpp;
+ grpc_tcp_server_shutdown_listeners(exec_ctx, tcp);
grpc_tcp_server_unref(exec_ctx, tcp);
grpc_exec_ctx_sched(exec_ctx, destroy_done, GRPC_ERROR_NONE, NULL);
}
diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c b/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c
index 96bf4d6f30..4350543c27 100644
--- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c
+++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c
@@ -67,7 +67,7 @@ void grpc_server_add_insecure_channel_from_fd(grpc_server *server,
&exec_ctx, server_args, server_endpoint, 0 /* is_client */);
grpc_endpoint_add_to_pollset(&exec_ctx, server_endpoint, grpc_cq_pollset(cq));
grpc_server_setup_transport(&exec_ctx, server, transport, NULL, server_args);
- grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0);
+ grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL);
grpc_exec_ctx_finish(&exec_ctx);
}
diff --git a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
index c42810e913..da3e284fcf 100644
--- a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
+++ b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
@@ -42,6 +42,7 @@
#include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/channel/http_server_filter.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/resolve_address.h"
@@ -58,7 +59,7 @@ typedef struct server_secure_state {
grpc_tcp_server *tcp;
grpc_server_security_connector *sc;
grpc_server_credentials *creds;
- int is_shutdown;
+ bool is_shutdown;
gpr_mu mu;
gpr_refcount refcount;
grpc_closure destroy_closure;
@@ -68,6 +69,12 @@ typedef struct server_secure_state {
typedef struct server_secure_connect {
server_secure_state *state;
grpc_pollset *accepting_pollset;
+ grpc_tcp_server_acceptor *acceptor;
+ grpc_handshake_manager *handshake_mgr;
+ // TODO(roth): Remove the following two fields when we eliminate
+ // grpc_server_security_connector_do_handshake().
+ gpr_timespec deadline;
+ grpc_channel_args *args;
} server_secure_connect;
static void state_ref(server_secure_state *state) { gpr_ref(&state->refcount); }
@@ -89,25 +96,22 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
grpc_endpoint *secure_endpoint,
grpc_auth_context *auth_context) {
server_secure_connect *state = statep;
- grpc_transport *transport;
if (status == GRPC_SECURITY_OK) {
if (secure_endpoint) {
gpr_mu_lock(&state->state->mu);
if (!state->state->is_shutdown) {
- transport = grpc_create_chttp2_transport(
+ grpc_transport *transport = grpc_create_chttp2_transport(
exec_ctx, grpc_server_get_channel_args(state->state->server),
secure_endpoint, 0);
- grpc_channel_args *args_copy;
grpc_arg args_to_add[2];
args_to_add[0] = grpc_server_credentials_to_arg(state->state->creds);
args_to_add[1] = grpc_auth_context_to_arg(auth_context);
- args_copy = grpc_channel_args_copy_and_add(
- grpc_server_get_channel_args(state->state->server), args_to_add,
- GPR_ARRAY_SIZE(args_to_add));
+ grpc_channel_args *args_copy = grpc_channel_args_copy_and_add(
+ state->args, args_to_add, GPR_ARRAY_SIZE(args_to_add));
grpc_server_setup_transport(exec_ctx, state->state->server, transport,
state->accepting_pollset, args_copy);
grpc_channel_args_destroy(args_copy);
- grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
+ grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL);
} else {
/* We need to consume this here, because the server may already have
* gone away. */
@@ -118,10 +122,40 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
} else {
gpr_log(GPR_ERROR, "Secure transport failed with error %d", status);
}
+ grpc_channel_args_destroy(state->args);
state_unref(state->state);
gpr_free(state);
}
+static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint,
+ grpc_channel_args *args,
+ gpr_slice_buffer *read_buffer, void *user_data,
+ grpc_error *error) {
+ server_secure_connect *state = user_data;
+ if (error != GRPC_ERROR_NONE) {
+ const char *error_str = grpc_error_string(error);
+ gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str);
+ grpc_error_free_string(error_str);
+ GRPC_ERROR_UNREF(error);
+ grpc_channel_args_destroy(args);
+ gpr_free(read_buffer);
+ grpc_handshake_manager_shutdown(exec_ctx, state->handshake_mgr);
+ grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr);
+ state_unref(state->state);
+ gpr_free(state);
+ return;
+ }
+ grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr);
+ state->handshake_mgr = NULL;
+ // TODO(roth, jboeuf): Convert security connector handshaking to use new
+ // handshake API, and then move the code from on_secure_handshake_done()
+ // into this function.
+ state->args = args;
+ grpc_server_security_connector_do_handshake(
+ exec_ctx, state->state->sc, state->acceptor, endpoint, read_buffer,
+ state->deadline, on_secure_handshake_done, state);
+}
+
static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
grpc_pollset *accepting_pollset,
grpc_tcp_server_acceptor *acceptor) {
@@ -129,11 +163,16 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
state->state = statep;
state_ref(state->state);
state->accepting_pollset = accepting_pollset;
- grpc_server_security_connector_do_handshake(
- exec_ctx, state->state->sc, acceptor, tcp,
- gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
- gpr_time_from_seconds(120, GPR_TIMESPAN)),
- on_secure_handshake_done, state);
+ state->acceptor = acceptor;
+ state->handshake_mgr = grpc_handshake_manager_create();
+ // TODO(roth): We should really get this timeout value from channel
+ // args instead of hard-coding it.
+ state->deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+ gpr_time_from_seconds(120, GPR_TIMESPAN));
+ grpc_handshake_manager_do_handshake(
+ exec_ctx, state->handshake_mgr, tcp,
+ grpc_server_get_channel_args(state->state->server), state->deadline,
+ acceptor, on_handshake_done, state);
}
/* Server callback: start listening on our ports */
@@ -162,10 +201,11 @@ static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
server_secure_state *state = statep;
grpc_tcp_server *tcp;
gpr_mu_lock(&state->mu);
- state->is_shutdown = 1;
+ state->is_shutdown = true;
state->destroy_callback = callback;
tcp = state->tcp;
gpr_mu_unlock(&state->mu);
+ grpc_tcp_server_shutdown_listeners(exec_ctx, tcp);
grpc_tcp_server_unref(exec_ctx, tcp);
}
@@ -226,7 +266,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
state->tcp = tcp;
state->sc = sc;
state->creds = grpc_server_credentials_ref(creds);
- state->is_shutdown = 0;
+ state->is_shutdown = false;
gpr_mu_init(&state->mu);
gpr_ref_init(&state->refcount, 1);
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index be8a8f8498..0e8dfb7d96 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -46,12 +46,12 @@
#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
-#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
#include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/workqueue.h"
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h"
+#include "src/core/lib/transport/timeout_encoding.h"
#include "src/core/lib/transport/transport_impl.h"
#define DEFAULT_WINDOW 65535
@@ -94,7 +94,8 @@ static void initiate_writing(grpc_exec_ctx *exec_ctx, void *t,
static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
static void end_waiting_for_write(grpc_exec_ctx *exec_ctx,
- grpc_chttp2_transport *t, grpc_error *error);
+ grpc_chttp2_transport *t, grpc_error *error,
+ const char *reason);
/** Set a transport level setting, and push it to our peer */
static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@@ -876,7 +877,7 @@ static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE,
"start_writing:nothing_to_write");
}
- end_waiting_for_write(exec_ctx, t, GRPC_ERROR_CREATE("Nothing to write"));
+ end_waiting_for_write(exec_ctx, t, GRPC_ERROR_NONE, "Nothing to write");
if (t->ep && !t->endpoint_reading) {
destroy_endpoint(exec_ctx, t);
}
@@ -925,11 +926,18 @@ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
}
}
+/* error may be GRPC_ERROR_NONE if there is no error allocated yet.
+ In that case, use "reason" as the text for a new error. */
static void end_waiting_for_write(grpc_exec_ctx *exec_ctx,
- grpc_chttp2_transport *t, grpc_error *error) {
+ grpc_chttp2_transport *t, grpc_error *error,
+ const char *reason) {
grpc_chttp2_stream_global *stream_global;
while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global,
&stream_global)) {
+ if (error == GRPC_ERROR_NONE && reason != NULL) {
+ /* create error object. */
+ error = GRPC_ERROR_CREATE(reason);
+ }
fail_pending_writes(exec_ctx, &t->global, stream_global,
GRPC_ERROR_REF(error));
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
@@ -951,7 +959,7 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing);
- end_waiting_for_write(exec_ctx, t, error);
+ end_waiting_for_write(exec_ctx, t, error, NULL);
switch (t->executor.write_state) {
case GRPC_CHTTP2_WRITING_INACTIVE:
@@ -2005,6 +2013,7 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_chttp2_transport *t = arg;
+ grpc_error *err = GRPC_ERROR_NONE;
GPR_TIMER_BEGIN("reading_action.parse", 0);
size_t i = 0;
grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
@@ -2013,15 +2022,13 @@ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
errors[1] = grpc_chttp2_perform_read(exec_ctx, &t->parsing,
t->read_buffer.slices[i]);
};
- if (i != t->read_buffer.count) {
+ if (errors[1] == GRPC_ERROR_NONE) {
+ err = GRPC_ERROR_REF(error);
+ } else {
errors[2] = try_http_parsing(exec_ctx, t);
+ err = GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors,
+ GPR_ARRAY_SIZE(errors));
}
- grpc_error *err =
- errors[0] == GRPC_ERROR_NONE && errors[1] == GRPC_ERROR_NONE &&
- errors[2] == GRPC_ERROR_NONE
- ? GRPC_ERROR_NONE
- : GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors,
- GPR_ARRAY_SIZE(errors));
for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) {
GRPC_ERROR_UNREF(errors[i]);
}
@@ -2539,9 +2546,12 @@ grpc_transport *grpc_create_chttp2_transport(
void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx,
grpc_transport *transport,
- gpr_slice *slices, size_t nslices) {
+ gpr_slice_buffer *read_buffer) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
REF_TRANSPORT(t, "reading_action"); /* matches unref inside reading_action */
- gpr_slice_buffer_addn(&t->read_buffer, slices, nslices);
+ if (read_buffer != NULL) {
+ gpr_slice_buffer_move_into(read_buffer, &t->read_buffer);
+ gpr_free(read_buffer);
+ }
reading_action(exec_ctx, t, GRPC_ERROR_NONE);
}
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.h b/src/core/ext/transport/chttp2/transport/chttp2_transport.h
index 5da4276f82..4e2d0954bf 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.h
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.h
@@ -44,8 +44,10 @@ grpc_transport *grpc_create_chttp2_transport(
grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
grpc_endpoint *ep, int is_client);
+/// Takes ownership of \a read_buffer, which (if non-NULL) contains
+/// leftover bytes previously read from the endpoint (e.g., by handshakers).
void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx,
grpc_transport *transport,
- gpr_slice *slices, size_t nslices);
+ gpr_slice_buffer *read_buffer);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H */
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
index ebeee37f0d..2cb8205d94 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
@@ -47,10 +47,10 @@
#include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
#include "src/core/ext/transport/chttp2/transport/hpack_table.h"
-#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
#include "src/core/ext/transport/chttp2/transport/varint.h"
#include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/static_metadata.h"
+#include "src/core/lib/transport/timeout_encoding.h"
#define HASH_FRAGMENT_1(x) ((x)&255)
#define HASH_FRAGMENT_2(x) ((x >> 8) & 255)
@@ -456,9 +456,9 @@ static void hpack_enc(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem,
static void deadline_enc(grpc_chttp2_hpack_compressor *c, gpr_timespec deadline,
framer_state *st) {
- char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
+ char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
grpc_mdelem *mdelem;
- grpc_chttp2_encode_timeout(
+ grpc_http2_encode_timeout(
gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str);
mdelem = grpc_mdelem_from_metadata_strings(
GRPC_MDSTR_GRPC_TIMEOUT, grpc_mdstr_from_string(timeout_str));
diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c
index e1fc0ddee2..482cd55c44 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.c
+++ b/src/core/ext/transport/chttp2/transport/parsing.c
@@ -41,9 +41,9 @@
#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
-#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/transport/static_metadata.h"
+#include "src/core/lib/transport/timeout_encoding.h"
#define TRANSPORT_FROM_PARSING(tp) \
((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \
@@ -668,8 +668,8 @@ static void on_initial_header(void *tp, grpc_mdelem *md) {
if (!cached_timeout) {
/* not already parsed: parse it now, and store the result away */
cached_timeout = gpr_malloc(sizeof(gpr_timespec));
- if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
- cached_timeout)) {
+ if (!grpc_http2_decode_timeout(grpc_mdstr_as_c_string(md->value),
+ cached_timeout)) {
gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
grpc_mdstr_as_c_string(md->value));
*cached_timeout = gpr_inf_future(GPR_TIMESPAN);
diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c
index e0d87725e9..8f7a1f55c6 100644
--- a/src/core/ext/transport/chttp2/transport/writing.c
+++ b/src/core/ext/transport/chttp2/transport/writing.c
@@ -202,6 +202,7 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
GPR_TIMER_BEGIN("finalize_outbuf", 0);
+ bool is_first_data_frame = true;
while (
grpc_chttp2_list_pop_writing_stream(transport_writing, &stream_writing)) {
uint32_t max_outgoing =
@@ -266,6 +267,11 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
stream_writing->id, &stream_writing->flow_controlled_buffer,
send_bytes, is_last_frame, &stream_writing->stats,
&transport_writing->outbuf);
+ if (is_first_data_frame) {
+ /* TODO(dgq): this is a hack. It'll be fix in a future refactoring */
+ stream_writing->stats.data_bytes -= 5; /* discount grpc framing */
+ is_first_data_frame = false;
+ }
GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing,
stream_writing, outgoing_window,
send_bytes);
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c
index 25d8aca250..029c15014e 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.c
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.c
@@ -46,617 +46,964 @@
#include "src/core/lib/support/string.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/metadata_batch.h"
+#include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/transport_impl.h"
#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h"
#define GRPC_HEADER_SIZE_IN_BYTES 5
-// Global flag that gets set with GRPC_TRACE env variable
-int grpc_cronet_trace = 1;
+#define CRONET_LOG(...) \
+ do { \
+ if (grpc_cronet_trace) gpr_log(__VA_ARGS__); \
+ } while (0)
-// Cronet transport object
+/* TODO (makdharma): Hook up into the wider tracing mechanism */
+int grpc_cronet_trace = 0;
+
+enum e_op_result {
+ ACTION_TAKEN_WITH_CALLBACK,
+ ACTION_TAKEN_NO_CALLBACK,
+ NO_ACTION_POSSIBLE
+};
+
+enum e_op_id {
+ OP_SEND_INITIAL_METADATA = 0,
+ OP_SEND_MESSAGE,
+ OP_SEND_TRAILING_METADATA,
+ OP_RECV_MESSAGE,
+ OP_RECV_INITIAL_METADATA,
+ OP_RECV_TRAILING_METADATA,
+ OP_CANCEL_ERROR,
+ OP_ON_COMPLETE,
+ OP_FAILED,
+ OP_SUCCEEDED,
+ OP_CANCELED,
+ OP_RECV_MESSAGE_AND_ON_COMPLETE,
+ OP_READ_REQ_MADE,
+ OP_NUM_OPS
+};
+
+/* Cronet callbacks. See cronet_c_for_grpc.h for documentation for each. */
+
+static void on_request_headers_sent(cronet_bidirectional_stream *);
+static void on_response_headers_received(
+ cronet_bidirectional_stream *,
+ const cronet_bidirectional_stream_header_array *, const char *);
+static void on_write_completed(cronet_bidirectional_stream *, const char *);
+static void on_read_completed(cronet_bidirectional_stream *, char *, int);
+static void on_response_trailers_received(
+ cronet_bidirectional_stream *,
+ const cronet_bidirectional_stream_header_array *);
+static void on_succeeded(cronet_bidirectional_stream *);
+static void on_failed(cronet_bidirectional_stream *, int);
+static void on_canceled(cronet_bidirectional_stream *);
+static cronet_bidirectional_stream_callback cronet_callbacks = {
+ on_request_headers_sent,
+ on_response_headers_received,
+ on_read_completed,
+ on_write_completed,
+ on_response_trailers_received,
+ on_succeeded,
+ on_failed,
+ on_canceled};
+
+/* Cronet transport object */
struct grpc_cronet_transport {
grpc_transport base; /* must be first element in this structure */
cronet_engine *engine;
char *host;
};
-
typedef struct grpc_cronet_transport grpc_cronet_transport;
-enum send_state {
- CRONET_SEND_IDLE = 0,
- CRONET_REQ_STARTED,
- CRONET_SEND_HEADER,
- CRONET_WRITE,
- CRONET_WRITE_COMPLETED,
+/* TODO (makdharma): reorder structure for memory efficiency per
+ http://www.catb.org/esr/structure-packing/#_structure_reordering: */
+struct read_state {
+ /* vars to store data coming from server */
+ char *read_buffer;
+ bool length_field_received;
+ int received_bytes;
+ int remaining_bytes;
+ int length_field;
+ char grpc_header_bytes[GRPC_HEADER_SIZE_IN_BYTES];
+ char *payload_field;
+ bool read_stream_closed;
+
+ /* vars for holding data destined for the application */
+ struct grpc_slice_buffer_stream sbs;
+ gpr_slice_buffer read_slice_buffer;
+
+ /* vars for trailing metadata */
+ grpc_chttp2_incoming_metadata_buffer trailing_metadata;
+ bool trailing_metadata_valid;
+
+ /* vars for initial metadata */
+ grpc_chttp2_incoming_metadata_buffer initial_metadata;
};
-enum recv_state {
- CRONET_RECV_IDLE = 0,
- CRONET_RECV_READ_LENGTH,
- CRONET_RECV_READ_DATA,
- CRONET_RECV_CLOSED,
+struct write_state {
+ char *write_buffer;
};
-static const char *recv_state_name[] = {
- "CRONET_RECV_IDLE", "CRONET_RECV_READ_LENGTH", "CRONET_RECV_READ_DATA,",
- "CRONET_RECV_CLOSED"};
+/* track state of one stream op */
+struct op_state {
+ bool state_op_done[OP_NUM_OPS];
+ bool state_callback_received[OP_NUM_OPS];
+ /* data structure for storing data coming from server */
+ struct read_state rs;
+ /* data structure for storing data going to the server */
+ struct write_state ws;
+};
-// Enum that identifies calling function.
-enum e_caller {
- PERFORM_STREAM_OP,
- ON_READ_COMPLETE,
- ON_RESPONSE_HEADERS_RECEIVED,
- ON_RESPONSE_TRAILERS_RECEIVED
+struct op_and_state {
+ grpc_transport_stream_op op;
+ struct op_state state;
+ bool done;
+ struct stream_obj *s; /* Pointer back to the stream object */
+ struct op_and_state *next; /* next op_and_state in the linked list */
};
-enum callback_id {
- CB_SEND_INITIAL_METADATA = 0,
- CB_SEND_MESSAGE,
- CB_SEND_TRAILING_METADATA,
- CB_RECV_MESSAGE,
- CB_RECV_INITIAL_METADATA,
- CB_RECV_TRAILING_METADATA,
- CB_NUM_CALLBACKS
+struct op_storage {
+ int num_pending_ops;
+ struct op_and_state *head;
};
struct stream_obj {
- // we store received bytes here as they trickle in.
- gpr_slice_buffer write_slice_buffer;
+ struct op_and_state *oas;
+ grpc_transport_stream_op *curr_op;
+ grpc_cronet_transport curr_ct;
+ grpc_stream *curr_gs;
cronet_bidirectional_stream *cbs;
- gpr_slice slice;
- gpr_slice_buffer read_slice_buffer;
- struct grpc_slice_buffer_stream sbs;
- char *read_buffer;
- int remaining_read_bytes;
- int total_read_bytes;
-
- char *write_buffer;
- size_t write_buffer_size;
-
- // Hold the URL
- char *url;
-
- bool response_headers_received;
- bool read_requested;
- bool response_trailers_received;
- bool read_closed;
-
- // Recv message stuff
- grpc_byte_buffer **recv_message;
- // Initial metadata stuff
- grpc_metadata_batch *recv_initial_metadata;
- // Trailing metadata stuff
- grpc_metadata_batch *recv_trailing_metadata;
- grpc_chttp2_incoming_metadata_buffer imb;
-
- // This mutex protects receive state machine execution
- gpr_mu recv_mu;
- // we can queue up up to 2 callbacks for each OP
- grpc_closure *callback_list[CB_NUM_CALLBACKS][2];
-
- // storage for header
- cronet_bidirectional_stream_header *headers;
- uint32_t num_headers;
cronet_bidirectional_stream_header_array header_array;
- // state tracking
- enum recv_state cronet_recv_state;
- enum send_state cronet_send_state;
-};
-typedef struct stream_obj stream_obj;
+ /* Stream level state. Some state will be tracked both at stream and stream_op
+ * level */
+ struct op_state state;
-static void next_send_step(stream_obj *s);
-static void next_recv_step(stream_obj *s, enum e_caller caller);
+ /* OP storage */
+ struct op_storage storage;
-static void set_pollset_do_nothing(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
- grpc_stream *gs, grpc_pollset *pollset) {}
+ /* Mutex to protect storage */
+ gpr_mu mu;
+};
+typedef struct stream_obj stream_obj;
-static void set_pollset_set_do_nothing(grpc_exec_ctx *exec_ctx,
- grpc_transport *gt, grpc_stream *gs,
- grpc_pollset_set *pollset_set) {}
+static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
+ struct op_and_state *oas);
-static void enqueue_callbacks(grpc_closure *callback_list[]) {
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- if (callback_list[0]) {
- grpc_exec_ctx_sched(&exec_ctx, callback_list[0], GRPC_ERROR_NONE, NULL);
- callback_list[0] = NULL;
- }
- if (callback_list[1]) {
- grpc_exec_ctx_sched(&exec_ctx, callback_list[1], GRPC_ERROR_NONE, NULL);
- callback_list[1] = NULL;
+/*
+ Utility function to translate enum into string for printing
+*/
+static const char *op_result_string(enum e_op_result i) {
+ switch (i) {
+ case ACTION_TAKEN_WITH_CALLBACK:
+ return "ACTION_TAKEN_WITH_CALLBACK";
+ case ACTION_TAKEN_NO_CALLBACK:
+ return "ACTION_TAKEN_NO_CALLBACK";
+ case NO_ACTION_POSSIBLE:
+ return "NO_ACTION_POSSIBLE";
}
- grpc_exec_ctx_finish(&exec_ctx);
+ GPR_UNREACHABLE_CODE(return "UNKNOWN");
}
-static void on_canceled(cronet_bidirectional_stream *stream) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "on_canceled %p", stream);
+static const char *op_id_string(enum e_op_id i) {
+ switch (i) {
+ case OP_SEND_INITIAL_METADATA:
+ return "OP_SEND_INITIAL_METADATA";
+ case OP_SEND_MESSAGE:
+ return "OP_SEND_MESSAGE";
+ case OP_SEND_TRAILING_METADATA:
+ return "OP_SEND_TRAILING_METADATA";
+ case OP_RECV_MESSAGE:
+ return "OP_RECV_MESSAGE";
+ case OP_RECV_INITIAL_METADATA:
+ return "OP_RECV_INITIAL_METADATA";
+ case OP_RECV_TRAILING_METADATA:
+ return "OP_RECV_TRAILING_METADATA";
+ case OP_CANCEL_ERROR:
+ return "OP_CANCEL_ERROR";
+ case OP_ON_COMPLETE:
+ return "OP_ON_COMPLETE";
+ case OP_FAILED:
+ return "OP_FAILED";
+ case OP_SUCCEEDED:
+ return "OP_SUCCEEDED";
+ case OP_CANCELED:
+ return "OP_CANCELED";
+ case OP_RECV_MESSAGE_AND_ON_COMPLETE:
+ return "OP_RECV_MESSAGE_AND_ON_COMPLETE";
+ case OP_READ_REQ_MADE:
+ return "OP_READ_REQ_MADE";
+ case OP_NUM_OPS:
+ return "OP_NUM_OPS";
}
+ return "UNKNOWN";
}
-static void on_failed(cronet_bidirectional_stream *stream, int net_error) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "on_failed %p, error = %d", stream, net_error);
- }
+/*
+ Add a new stream op to op storage.
+*/
+static void add_to_storage(struct stream_obj *s, grpc_transport_stream_op *op) {
+ struct op_storage *storage = &s->storage;
+ /* add new op at the beginning of the linked list. The memory is freed
+ in remove_from_storage */
+ struct op_and_state *new_op = gpr_malloc(sizeof(struct op_and_state));
+ memcpy(&new_op->op, op, sizeof(grpc_transport_stream_op));
+ memset(&new_op->state, 0, sizeof(new_op->state));
+ new_op->s = s;
+ new_op->done = false;
+ gpr_mu_lock(&s->mu);
+ new_op->next = storage->head;
+ storage->head = new_op;
+ storage->num_pending_ops++;
+ CRONET_LOG(GPR_DEBUG, "adding new op %p. %d in the queue.", new_op,
+ storage->num_pending_ops);
+ gpr_mu_unlock(&s->mu);
}
-static void on_succeeded(cronet_bidirectional_stream *stream) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "on_succeeded %p", stream);
+/*
+ Traverse the linked list and delete op and free memory
+*/
+static void remove_from_storage(struct stream_obj *s,
+ struct op_and_state *oas) {
+ struct op_and_state *curr;
+ if (s->storage.head == NULL || oas == NULL) {
+ return;
}
-}
-
-static void on_response_trailers_received(
- cronet_bidirectional_stream *stream,
- const cronet_bidirectional_stream_header_array *trailers) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: on_response_trailers_received");
+ if (s->storage.head == oas) {
+ s->storage.head = oas->next;
+ gpr_free(oas);
+ s->storage.num_pending_ops--;
+ CRONET_LOG(GPR_DEBUG, "Freed %p. Now %d in the queue", oas,
+ s->storage.num_pending_ops);
+ } else {
+ for (curr = s->storage.head; curr != NULL; curr = curr->next) {
+ if (curr->next == oas) {
+ curr->next = oas->next;
+ s->storage.num_pending_ops--;
+ CRONET_LOG(GPR_DEBUG, "Freed %p. Now %d in the queue", oas,
+ s->storage.num_pending_ops);
+ gpr_free(oas);
+ break;
+ } else if (curr->next == NULL) {
+ CRONET_LOG(GPR_ERROR, "Reached end of LL and did not find op to free");
+ }
+ }
}
- stream_obj *s = (stream_obj *)stream->annotation;
+}
- memset(&s->imb, 0, sizeof(s->imb));
- grpc_chttp2_incoming_metadata_buffer_init(&s->imb);
- unsigned int i = 0;
- for (i = 0; i < trailers->count; i++) {
- grpc_chttp2_incoming_metadata_buffer_add(
- &s->imb, grpc_mdelem_from_metadata_strings(
- grpc_mdstr_from_string(trailers->headers[i].key),
- grpc_mdstr_from_string(trailers->headers[i].value)));
+/*
+ Cycle through ops and try to take next action. Break when either
+ an action with callback is taken, or no action is possible.
+ This can be executed from the Cronet network thread via cronet callback
+ or on the application supplied thread via the perform_stream_op function.
+*/
+static void execute_from_storage(stream_obj *s) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ gpr_mu_lock(&s->mu);
+ for (struct op_and_state *curr = s->storage.head; curr != NULL;) {
+ CRONET_LOG(GPR_DEBUG, "calling op at %p. done = %d", curr, curr->done);
+ GPR_ASSERT(curr->done == 0);
+ enum e_op_result result = execute_stream_op(&exec_ctx, curr);
+ CRONET_LOG(GPR_DEBUG, "execute_stream_op[%p] returns %s", curr,
+ op_result_string(result));
+ /* if this op is done, then remove it and free memory */
+ if (curr->done) {
+ struct op_and_state *next = curr->next;
+ remove_from_storage(s, curr);
+ curr = next;
+ }
+ /* continue processing the same op if ACTION_TAKEN_WITHOUT_CALLBACK */
+ if (result == NO_ACTION_POSSIBLE) {
+ curr = curr->next;
+ } else if (result == ACTION_TAKEN_WITH_CALLBACK) {
+ break;
+ }
}
- s->response_trailers_received = true;
- next_recv_step(s, ON_RESPONSE_TRAILERS_RECEIVED);
+ gpr_mu_unlock(&s->mu);
+ grpc_exec_ctx_finish(&exec_ctx);
}
-static void on_write_completed(cronet_bidirectional_stream *stream,
- const char *data) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "W: on_write_completed");
- }
+/*
+ Cronet callback
+*/
+static void on_failed(cronet_bidirectional_stream *stream, int net_error) {
+ CRONET_LOG(GPR_DEBUG, "on_failed(%p, %d)", stream, net_error);
stream_obj *s = (stream_obj *)stream->annotation;
- enqueue_callbacks(s->callback_list[CB_SEND_MESSAGE]);
- s->cronet_send_state = CRONET_WRITE_COMPLETED;
- next_send_step(s);
+ cronet_bidirectional_stream_destroy(s->cbs);
+ s->state.state_callback_received[OP_FAILED] = true;
+ s->cbs = NULL;
+ if (s->header_array.headers) {
+ gpr_free(s->header_array.headers);
+ s->header_array.headers = NULL;
+ }
+ if (s->state.ws.write_buffer) {
+ gpr_free(s->state.ws.write_buffer);
+ s->state.ws.write_buffer = NULL;
+ }
+ execute_from_storage(s);
}
-static void process_recv_message(stream_obj *s, const uint8_t *recv_data) {
- gpr_slice read_data_slice = gpr_slice_malloc((uint32_t)s->total_read_bytes);
- uint8_t *dst_p = GPR_SLICE_START_PTR(read_data_slice);
- if (s->total_read_bytes > 0) {
- // Only copy if there is non-zero number of bytes
- memcpy(dst_p, recv_data, (size_t)s->total_read_bytes);
- gpr_slice_buffer_add(&s->read_slice_buffer, read_data_slice);
+/*
+ Cronet callback
+*/
+static void on_canceled(cronet_bidirectional_stream *stream) {
+ CRONET_LOG(GPR_DEBUG, "on_canceled(%p)", stream);
+ stream_obj *s = (stream_obj *)stream->annotation;
+ cronet_bidirectional_stream_destroy(s->cbs);
+ s->state.state_callback_received[OP_CANCELED] = true;
+ s->cbs = NULL;
+ if (s->header_array.headers) {
+ gpr_free(s->header_array.headers);
+ s->header_array.headers = NULL;
}
- grpc_slice_buffer_stream_init(&s->sbs, &s->read_slice_buffer, 0);
- *s->recv_message = (grpc_byte_buffer *)&s->sbs;
+ if (s->state.ws.write_buffer) {
+ gpr_free(s->state.ws.write_buffer);
+ s->state.ws.write_buffer = NULL;
+ }
+ execute_from_storage(s);
}
-static int parse_grpc_header(const uint8_t *data) {
- const uint8_t *p = data + 1;
- int length = 0;
- length |= ((uint8_t)*p++) << 24;
- length |= ((uint8_t)*p++) << 16;
- length |= ((uint8_t)*p++) << 8;
- length |= ((uint8_t)*p++);
- return length;
+/*
+ Cronet callback
+*/
+static void on_succeeded(cronet_bidirectional_stream *stream) {
+ CRONET_LOG(GPR_DEBUG, "on_succeeded(%p)", stream);
+ stream_obj *s = (stream_obj *)stream->annotation;
+ cronet_bidirectional_stream_destroy(s->cbs);
+ s->state.state_callback_received[OP_SUCCEEDED] = true;
+ s->cbs = NULL;
+ execute_from_storage(s);
}
-static void on_read_completed(cronet_bidirectional_stream *stream, char *data,
- int count) {
+/*
+ Cronet callback
+*/
+static void on_request_headers_sent(cronet_bidirectional_stream *stream) {
+ CRONET_LOG(GPR_DEBUG, "W: on_request_headers_sent(%p)", stream);
stream_obj *s = (stream_obj *)stream->annotation;
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: on_read_completed count=%d, total=%d, remaining=%d",
- count, s->total_read_bytes, s->remaining_read_bytes);
- }
- if (count > 0) {
- GPR_ASSERT(s->recv_message);
- s->remaining_read_bytes -= count;
- next_recv_step(s, ON_READ_COMPLETE);
- } else {
- s->read_closed = true;
- next_recv_step(s, ON_READ_COMPLETE);
+ s->state.state_op_done[OP_SEND_INITIAL_METADATA] = true;
+ s->state.state_callback_received[OP_SEND_INITIAL_METADATA] = true;
+ /* Free the memory allocated for headers */
+ if (s->header_array.headers) {
+ gpr_free(s->header_array.headers);
+ s->header_array.headers = NULL;
}
+ execute_from_storage(s);
}
+/*
+ Cronet callback
+*/
static void on_response_headers_received(
cronet_bidirectional_stream *stream,
const cronet_bidirectional_stream_header_array *headers,
const char *negotiated_protocol) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: on_response_headers_received");
- }
+ CRONET_LOG(GPR_DEBUG, "R: on_response_headers_received(%p, %p, %s)", stream,
+ headers, negotiated_protocol);
stream_obj *s = (stream_obj *)stream->annotation;
- enqueue_callbacks(s->callback_list[CB_RECV_INITIAL_METADATA]);
- s->response_headers_received = true;
- next_recv_step(s, ON_RESPONSE_HEADERS_RECEIVED);
-}
-
-static void on_request_headers_sent(cronet_bidirectional_stream *stream) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "W: on_request_headers_sent");
+ memset(&s->state.rs.initial_metadata, 0,
+ sizeof(s->state.rs.initial_metadata));
+ grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.initial_metadata);
+ for (size_t i = 0; i < headers->count; i++) {
+ grpc_chttp2_incoming_metadata_buffer_add(
+ &s->state.rs.initial_metadata,
+ grpc_mdelem_from_metadata_strings(
+ grpc_mdstr_from_string(headers->headers[i].key),
+ grpc_mdstr_from_string(headers->headers[i].value)));
}
- stream_obj *s = (stream_obj *)stream->annotation;
- enqueue_callbacks(s->callback_list[CB_SEND_INITIAL_METADATA]);
- s->cronet_send_state = CRONET_SEND_HEADER;
- next_send_step(s);
+ s->state.state_callback_received[OP_RECV_INITIAL_METADATA] = true;
+ execute_from_storage(s);
}
-// Callback function pointers (invoked by cronet in response to events)
-static cronet_bidirectional_stream_callback callbacks = {
- on_request_headers_sent,
- on_response_headers_received,
- on_read_completed,
- on_write_completed,
- on_response_trailers_received,
- on_succeeded,
- on_failed,
- on_canceled};
-
-static void invoke_closing_callback(stream_obj *s) {
- grpc_chttp2_incoming_metadata_buffer_publish(&s->imb,
- s->recv_trailing_metadata);
- if (s->callback_list[CB_RECV_TRAILING_METADATA]) {
- enqueue_callbacks(s->callback_list[CB_RECV_TRAILING_METADATA]);
+/*
+ Cronet callback
+*/
+static void on_write_completed(cronet_bidirectional_stream *stream,
+ const char *data) {
+ stream_obj *s = (stream_obj *)stream->annotation;
+ CRONET_LOG(GPR_DEBUG, "W: on_write_completed(%p, %s)", stream, data);
+ if (s->state.ws.write_buffer) {
+ gpr_free(s->state.ws.write_buffer);
+ s->state.ws.write_buffer = NULL;
}
+ s->state.state_callback_received[OP_SEND_MESSAGE] = true;
+ execute_from_storage(s);
}
-static void set_recv_state(stream_obj *s, enum recv_state state) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "next_state = %s", recv_state_name[state]);
+/*
+ Cronet callback
+*/
+static void on_read_completed(cronet_bidirectional_stream *stream, char *data,
+ int count) {
+ stream_obj *s = (stream_obj *)stream->annotation;
+ CRONET_LOG(GPR_DEBUG, "R: on_read_completed(%p, %p, %d)", stream, data,
+ count);
+ s->state.state_callback_received[OP_RECV_MESSAGE] = true;
+ if (count > 0) {
+ s->state.rs.received_bytes += count;
+ s->state.rs.remaining_bytes -= count;
+ if (s->state.rs.remaining_bytes > 0) {
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs);
+ s->state.state_op_done[OP_READ_REQ_MADE] = true;
+ cronet_bidirectional_stream_read(
+ s->cbs, s->state.rs.read_buffer + s->state.rs.received_bytes,
+ s->state.rs.remaining_bytes);
+ } else {
+ execute_from_storage(s);
+ }
+ } else {
+ s->state.rs.read_stream_closed = true;
+ execute_from_storage(s);
}
- s->cronet_recv_state = state;
}
-// This is invoked from perform_stream_op, and all on_xxxx callbacks.
-static void next_recv_step(stream_obj *s, enum e_caller caller) {
- gpr_mu_lock(&s->recv_mu);
- switch (s->cronet_recv_state) {
- case CRONET_RECV_IDLE:
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_IDLE");
- }
- if (caller == PERFORM_STREAM_OP ||
- caller == ON_RESPONSE_HEADERS_RECEIVED) {
- if (s->read_closed && s->response_trailers_received) {
- invoke_closing_callback(s);
- set_recv_state(s, CRONET_RECV_CLOSED);
- } else if (s->response_headers_received == true &&
- s->read_requested == true) {
- set_recv_state(s, CRONET_RECV_READ_LENGTH);
- s->total_read_bytes = s->remaining_read_bytes =
- GRPC_HEADER_SIZE_IN_BYTES;
- GPR_ASSERT(s->read_buffer);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()");
- }
- cronet_bidirectional_stream_read(s->cbs, s->read_buffer,
- s->remaining_read_bytes);
- }
- }
- break;
- case CRONET_RECV_READ_LENGTH:
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_LENGTH");
- }
- if (caller == ON_READ_COMPLETE) {
- if (s->read_closed) {
- invoke_closing_callback(s);
- enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]);
- set_recv_state(s, CRONET_RECV_CLOSED);
- } else {
- GPR_ASSERT(s->remaining_read_bytes == 0);
- set_recv_state(s, CRONET_RECV_READ_DATA);
- s->total_read_bytes = s->remaining_read_bytes =
- parse_grpc_header((const uint8_t *)s->read_buffer);
- s->read_buffer =
- gpr_realloc(s->read_buffer, (uint32_t)s->remaining_read_bytes);
- GPR_ASSERT(s->read_buffer);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()");
- }
- if (s->remaining_read_bytes > 0) {
- cronet_bidirectional_stream_read(s->cbs, (char *)s->read_buffer,
- s->remaining_read_bytes);
- } else {
- // Calling the closing callback directly since this is a 0 byte read
- // for an empty message.
- process_recv_message(s, NULL);
- enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]);
- invoke_closing_callback(s);
- set_recv_state(s, CRONET_RECV_CLOSED);
- }
- }
- }
- break;
- case CRONET_RECV_READ_DATA:
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_DATA");
- }
- if (caller == ON_READ_COMPLETE) {
- if (s->remaining_read_bytes > 0) {
- int offset = s->total_read_bytes - s->remaining_read_bytes;
- GPR_ASSERT(s->read_buffer);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()");
- }
- cronet_bidirectional_stream_read(
- s->cbs, (char *)s->read_buffer + offset, s->remaining_read_bytes);
- } else {
- gpr_slice_buffer_init(&s->read_slice_buffer);
- uint8_t *p = (uint8_t *)s->read_buffer;
- process_recv_message(s, p);
- set_recv_state(s, CRONET_RECV_IDLE);
- enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]);
- }
- }
- break;
- case CRONET_RECV_CLOSED:
- break;
- default:
- GPR_ASSERT(0); // Should not reach here
- break;
+/*
+ Cronet callback
+*/
+static void on_response_trailers_received(
+ cronet_bidirectional_stream *stream,
+ const cronet_bidirectional_stream_header_array *trailers) {
+ CRONET_LOG(GPR_DEBUG, "R: on_response_trailers_received(%p,%p)", stream,
+ trailers);
+ stream_obj *s = (stream_obj *)stream->annotation;
+ memset(&s->state.rs.trailing_metadata, 0,
+ sizeof(s->state.rs.trailing_metadata));
+ s->state.rs.trailing_metadata_valid = false;
+ grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.trailing_metadata);
+ for (size_t i = 0; i < trailers->count; i++) {
+ CRONET_LOG(GPR_DEBUG, "trailer key=%s, value=%s", trailers->headers[i].key,
+ trailers->headers[i].value);
+ grpc_chttp2_incoming_metadata_buffer_add(
+ &s->state.rs.trailing_metadata,
+ grpc_mdelem_from_metadata_strings(
+ grpc_mdstr_from_string(trailers->headers[i].key),
+ grpc_mdstr_from_string(trailers->headers[i].value)));
+ s->state.rs.trailing_metadata_valid = true;
}
- gpr_mu_unlock(&s->recv_mu);
+ s->state.state_callback_received[OP_RECV_TRAILING_METADATA] = true;
+ execute_from_storage(s);
}
-// This function takes the data from s->write_slice_buffer and assembles into
-// a contiguous byte stream with 5 byte gRPC header prepended.
-static void create_grpc_frame(stream_obj *s) {
- gpr_slice slice = gpr_slice_buffer_take_first(&s->write_slice_buffer);
- uint8_t *raw_data = GPR_SLICE_START_PTR(slice);
+/*
+ Utility function that takes the data from s->write_slice_buffer and assembles
+ into a contiguous byte stream with 5 byte gRPC header prepended.
+*/
+static void create_grpc_frame(gpr_slice_buffer *write_slice_buffer,
+ char **pp_write_buffer,
+ size_t *p_write_buffer_size) {
+ gpr_slice slice = gpr_slice_buffer_take_first(write_slice_buffer);
size_t length = GPR_SLICE_LENGTH(slice);
- s->write_buffer_size = length + GRPC_HEADER_SIZE_IN_BYTES;
- s->write_buffer = gpr_realloc(s->write_buffer, s->write_buffer_size);
- uint8_t *p = (uint8_t *)s->write_buffer;
- // Append 5 byte header
+ *p_write_buffer_size = length + GRPC_HEADER_SIZE_IN_BYTES;
+ /* This is freed in the on_write_completed callback */
+ char *write_buffer = gpr_malloc(length + GRPC_HEADER_SIZE_IN_BYTES);
+ *pp_write_buffer = write_buffer;
+ uint8_t *p = (uint8_t *)write_buffer;
+ /* Append 5 byte header */
*p++ = 0;
*p++ = (uint8_t)(length >> 24);
*p++ = (uint8_t)(length >> 16);
*p++ = (uint8_t)(length >> 8);
*p++ = (uint8_t)(length);
- // append actual data
- memcpy(p, raw_data, length);
+ /* append actual data */
+ memcpy(p, GPR_SLICE_START_PTR(slice), length);
}
-static void do_write(stream_obj *s) {
- gpr_slice_buffer *sb = &s->write_slice_buffer;
- GPR_ASSERT(sb->count <= 1);
- if (sb->count > 0) {
- create_grpc_frame(s);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write");
- }
- cronet_bidirectional_stream_write(s->cbs, s->write_buffer,
- (int)s->write_buffer_size, false);
- }
-}
-
-//
-static void next_send_step(stream_obj *s) {
- switch (s->cronet_send_state) {
- case CRONET_SEND_IDLE:
- GPR_ASSERT(
- s->cbs); // cronet_bidirectional_stream is not initialized yet.
- s->cronet_send_state = CRONET_REQ_STARTED;
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_start to %s", s->url);
- }
- cronet_bidirectional_stream_start(s->cbs, s->url, 0, "POST",
- &s->header_array, false);
- // we no longer need the memory that was allocated earlier.
- gpr_free(s->header_array.headers);
- break;
- case CRONET_SEND_HEADER:
- do_write(s);
- s->cronet_send_state = CRONET_WRITE;
- break;
- case CRONET_WRITE_COMPLETED:
- do_write(s);
- break;
- default:
- GPR_ASSERT(0);
- break;
- }
-}
-
-static void convert_metadata_to_cronet_headers(grpc_linked_mdelem *head,
- const char *host,
- stream_obj *s) {
+/*
+ Convert metadata in a format that Cronet can consume
+*/
+static void convert_metadata_to_cronet_headers(
+ grpc_linked_mdelem *head, const char *host, char **pp_url,
+ cronet_bidirectional_stream_header **pp_headers, size_t *p_num_headers) {
grpc_linked_mdelem *curr = head;
- // Walk the linked list and get number of header fields
- uint32_t num_headers_available = 0;
+ /* Walk the linked list and get number of header fields */
+ size_t num_headers_available = 0;
while (curr != NULL) {
curr = curr->next;
num_headers_available++;
}
- // Allocate enough memory
- s->headers = (cronet_bidirectional_stream_header *)gpr_malloc(
- sizeof(cronet_bidirectional_stream_header) * num_headers_available);
-
- // Walk the linked list again, this time copying the header fields.
- // s->num_headers
- // can be less than num_headers_available, as some headers are not used for
- // cronet
+ /* Allocate enough memory. It is freed in the on_request_headers_sent callback
+ */
+ cronet_bidirectional_stream_header *headers =
+ (cronet_bidirectional_stream_header *)gpr_malloc(
+ sizeof(cronet_bidirectional_stream_header) * num_headers_available);
+ *pp_headers = headers;
+
+ /* Walk the linked list again, this time copying the header fields.
+ s->num_headers can be less than num_headers_available, as some headers
+ are not used for cronet.
+ TODO (makdharma): Eliminate need to traverse the LL second time for perf.
+ */
curr = head;
- s->num_headers = 0;
- while (s->num_headers < num_headers_available) {
+ size_t num_headers = 0;
+ while (num_headers < num_headers_available) {
grpc_mdelem *mdelem = curr->md;
curr = curr->next;
const char *key = grpc_mdstr_as_c_string(mdelem->key);
const char *value = grpc_mdstr_as_c_string(mdelem->value);
- if (strcmp(key, ":scheme") == 0 || strcmp(key, ":method") == 0 ||
- strcmp(key, ":authority") == 0) {
- // Cronet populates these fields on its own.
+ if (mdelem->key == GRPC_MDSTR_METHOD || mdelem->key == GRPC_MDSTR_SCHEME ||
+ mdelem->key == GRPC_MDSTR_AUTHORITY) {
+ /* Cronet populates these fields on its own */
continue;
}
- if (strcmp(key, ":path") == 0) {
- // Create URL by appending :path value to the hostname
- gpr_asprintf(&s->url, "https://%s%s", host, value);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "extracted URL = %s", s->url);
- }
+ if (mdelem->key == GRPC_MDSTR_PATH) {
+ /* Create URL by appending :path value to the hostname */
+ gpr_asprintf(pp_url, "https://%s%s", host, value);
continue;
}
- s->headers[s->num_headers].key = key;
- s->headers[s->num_headers].value = value;
- s->num_headers++;
+ CRONET_LOG(GPR_DEBUG, "header %s = %s", key, value);
+ headers[num_headers].key = key;
+ headers[num_headers].value = value;
+ num_headers++;
if (curr == NULL) {
break;
}
}
+ *p_num_headers = (size_t)num_headers;
}
-static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
- grpc_stream *gs, grpc_transport_stream_op *op) {
- grpc_cronet_transport *ct = (grpc_cronet_transport *)gt;
- GPR_ASSERT(ct->engine);
- stream_obj *s = (stream_obj *)gs;
- if (op->recv_trailing_metadata) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG,
- "perform_stream_op - recv_trailing_metadata: on_complete=%p",
- op->on_complete);
+static int parse_grpc_header(const uint8_t *data) {
+ const uint8_t *p = data + 1;
+ int length = 0;
+ length |= ((uint8_t)*p++) << 24;
+ length |= ((uint8_t)*p++) << 16;
+ length |= ((uint8_t)*p++) << 8;
+ length |= ((uint8_t)*p++);
+ return length;
+}
+
+/*
+ Op Execution: Decide if one of the actions contained in the stream op can be
+ executed. This is the heart of the state machine.
+*/
+static bool op_can_be_run(grpc_transport_stream_op *curr_op,
+ struct op_state *stream_state,
+ struct op_state *op_state, enum e_op_id op_id) {
+ bool result = true;
+ /* When call is canceled, every op can be run, except under following
+ conditions
+ */
+ bool is_canceled_of_failed = stream_state->state_op_done[OP_CANCEL_ERROR] ||
+ stream_state->state_callback_received[OP_FAILED];
+ if (is_canceled_of_failed) {
+ if (op_id == OP_SEND_INITIAL_METADATA) result = false;
+ if (op_id == OP_SEND_MESSAGE) result = false;
+ if (op_id == OP_SEND_TRAILING_METADATA) result = false;
+ if (op_id == OP_CANCEL_ERROR) result = false;
+ /* already executed */
+ if (op_id == OP_RECV_INITIAL_METADATA &&
+ stream_state->state_op_done[OP_RECV_INITIAL_METADATA])
+ result = false;
+ if (op_id == OP_RECV_MESSAGE &&
+ stream_state->state_op_done[OP_RECV_MESSAGE])
+ result = false;
+ if (op_id == OP_RECV_TRAILING_METADATA &&
+ stream_state->state_op_done[OP_RECV_TRAILING_METADATA])
+ result = false;
+ } else if (op_id == OP_SEND_INITIAL_METADATA) {
+ /* already executed */
+ if (stream_state->state_op_done[OP_SEND_INITIAL_METADATA]) result = false;
+ } else if (op_id == OP_RECV_INITIAL_METADATA) {
+ /* already executed */
+ if (stream_state->state_op_done[OP_RECV_INITIAL_METADATA]) result = false;
+ /* we haven't sent headers yet. */
+ else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA])
+ result = false;
+ /* we haven't received headers yet. */
+ else if (!stream_state->state_callback_received[OP_RECV_INITIAL_METADATA])
+ result = false;
+ } else if (op_id == OP_SEND_MESSAGE) {
+ /* already executed (note we're checking op specific state, not stream
+ state) */
+ if (op_state->state_op_done[OP_SEND_MESSAGE]) result = false;
+ /* we haven't sent headers yet. */
+ else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA])
+ result = false;
+ } else if (op_id == OP_RECV_MESSAGE) {
+ /* already executed */
+ if (op_state->state_op_done[OP_RECV_MESSAGE]) result = false;
+ /* we haven't received headers yet. */
+ else if (!stream_state->state_callback_received[OP_RECV_INITIAL_METADATA])
+ result = false;
+ } else if (op_id == OP_RECV_TRAILING_METADATA) {
+ /* already executed */
+ if (stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) result = false;
+ /* we have asked for but haven't received message yet. */
+ else if (stream_state->state_op_done[OP_READ_REQ_MADE] &&
+ !stream_state->state_op_done[OP_RECV_MESSAGE])
+ result = false;
+ /* we haven't received trailers yet. */
+ else if (!stream_state->state_callback_received[OP_RECV_TRAILING_METADATA])
+ result = false;
+ /* we haven't received on_succeeded yet. */
+ else if (!stream_state->state_callback_received[OP_SUCCEEDED])
+ result = false;
+ } else if (op_id == OP_SEND_TRAILING_METADATA) {
+ /* already executed */
+ if (stream_state->state_op_done[OP_SEND_TRAILING_METADATA]) result = false;
+ /* we haven't sent initial metadata yet */
+ else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA])
+ result = false;
+ /* we haven't sent message yet */
+ else if (curr_op->send_message &&
+ !stream_state->state_op_done[OP_SEND_MESSAGE])
+ result = false;
+ /* we haven't got on_write_completed for the send yet */
+ else if (stream_state->state_op_done[OP_SEND_MESSAGE] &&
+ !stream_state->state_callback_received[OP_SEND_MESSAGE])
+ result = false;
+ } else if (op_id == OP_CANCEL_ERROR) {
+ /* already executed */
+ if (stream_state->state_op_done[OP_CANCEL_ERROR]) result = false;
+ } else if (op_id == OP_ON_COMPLETE) {
+ /* already executed (note we're checking op specific state, not stream
+ state) */
+ if (op_state->state_op_done[OP_ON_COMPLETE]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
}
- s->recv_trailing_metadata = op->recv_trailing_metadata;
- GPR_ASSERT(!s->callback_list[CB_RECV_TRAILING_METADATA][0]);
- s->callback_list[CB_RECV_TRAILING_METADATA][0] = op->on_complete;
- }
- if (op->recv_message) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "perform_stream_op - recv_message: on_complete=%p",
- op->on_complete);
+ /* Check if every op that was asked for is done. */
+ else if (curr_op->send_initial_metadata &&
+ !stream_state->state_callback_received[OP_SEND_INITIAL_METADATA]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->send_message &&
+ !op_state->state_op_done[OP_SEND_MESSAGE]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->send_message &&
+ !stream_state->state_callback_received[OP_SEND_MESSAGE]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->send_trailing_metadata &&
+ !stream_state->state_op_done[OP_SEND_TRAILING_METADATA]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->recv_initial_metadata &&
+ !stream_state->state_op_done[OP_RECV_INITIAL_METADATA]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->recv_message &&
+ !stream_state->state_op_done[OP_RECV_MESSAGE]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->recv_trailing_metadata) {
+ /* We aren't done with trailing metadata yet */
+ if (!stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ }
+ /* We've asked for actual message in an earlier op, and it hasn't been
+ delivered yet. */
+ else if (stream_state->state_op_done[OP_READ_REQ_MADE]) {
+ /* If this op is not the one asking for read, (which means some earlier
+ op has asked), and the read hasn't been delivered. */
+ if (!curr_op->recv_message &&
+ !stream_state->state_callback_received[OP_SUCCEEDED]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ }
+ }
}
- s->recv_message = (grpc_byte_buffer **)op->recv_message;
- GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][0]);
- GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][1]);
- s->callback_list[CB_RECV_MESSAGE][0] = op->recv_message_ready;
- s->callback_list[CB_RECV_MESSAGE][1] = op->on_complete;
- s->read_requested = true;
- next_recv_step(s, PERFORM_STREAM_OP);
+ /* We should see at least one on_write_completed for the trailers that we
+ sent */
+ else if (curr_op->send_trailing_metadata &&
+ !stream_state->state_callback_received[OP_SEND_MESSAGE])
+ result = false;
}
- if (op->recv_initial_metadata) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "perform_stream_op - recv_initial_metadata:=%p",
- op->on_complete);
+ CRONET_LOG(GPR_DEBUG, "op_can_be_run %s : %s", op_id_string(op_id),
+ result ? "YES" : "NO");
+ return result;
+}
+
+/*
+ TODO (makdharma): Break down this function in smaller chunks for readability.
+*/
+static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
+ struct op_and_state *oas) {
+ grpc_transport_stream_op *stream_op = &oas->op;
+ struct stream_obj *s = oas->s;
+ struct op_state *stream_state = &s->state;
+ enum e_op_result result = NO_ACTION_POSSIBLE;
+ if (stream_op->send_initial_metadata &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_SEND_INITIAL_METADATA)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_INITIAL_METADATA", oas);
+ /* This OP is the beginning. Reset various states */
+ memset(&s->header_array, 0, sizeof(s->header_array));
+ memset(&stream_state->rs, 0, sizeof(stream_state->rs));
+ memset(&stream_state->ws, 0, sizeof(stream_state->ws));
+ memset(stream_state->state_op_done, 0, sizeof(stream_state->state_op_done));
+ memset(stream_state->state_callback_received, 0,
+ sizeof(stream_state->state_callback_received));
+ /* Start new cronet stream. It is destroyed in on_succeeded, on_canceled,
+ * on_failed */
+ GPR_ASSERT(s->cbs == NULL);
+ s->cbs = cronet_bidirectional_stream_create(s->curr_ct.engine, s->curr_gs,
+ &cronet_callbacks);
+ CRONET_LOG(GPR_DEBUG, "%p = cronet_bidirectional_stream_create()", s->cbs);
+ char *url;
+ s->header_array.headers = NULL;
+ convert_metadata_to_cronet_headers(
+ stream_op->send_initial_metadata->list.head, s->curr_ct.host, &url,
+ &s->header_array.headers, &s->header_array.count);
+ s->header_array.capacity = s->header_array.count;
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_start(%p, %s)", s->cbs,
+ url);
+ cronet_bidirectional_stream_start(s->cbs, url, 0, "POST", &s->header_array,
+ false);
+ stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true;
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ } else if (stream_op->recv_initial_metadata &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_RECV_INITIAL_METADATA)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_INITIAL_METADATA", oas);
+ if (!stream_state->state_op_done[OP_CANCEL_ERROR]) {
+ grpc_chttp2_incoming_metadata_buffer_publish(
+ &oas->s->state.rs.initial_metadata, stream_op->recv_initial_metadata);
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
+ GRPC_ERROR_NONE, NULL);
+ } else {
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
+ GRPC_ERROR_CANCELLED, NULL);
}
- s->recv_initial_metadata = op->recv_initial_metadata;
- GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][0]);
- GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][1]);
- s->callback_list[CB_RECV_INITIAL_METADATA][0] =
- op->recv_initial_metadata_ready;
- s->callback_list[CB_RECV_INITIAL_METADATA][1] = op->on_complete;
- }
- if (op->send_initial_metadata) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG,
- "perform_stream_op - send_initial_metadata: on_complete=%p",
- op->on_complete);
+ stream_state->state_op_done[OP_RECV_INITIAL_METADATA] = true;
+ result = ACTION_TAKEN_NO_CALLBACK;
+ } else if (stream_op->send_message &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_SEND_MESSAGE)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_MESSAGE", oas);
+ gpr_slice_buffer write_slice_buffer;
+ gpr_slice slice;
+ gpr_slice_buffer_init(&write_slice_buffer);
+ grpc_byte_stream_next(NULL, stream_op->send_message, &slice,
+ stream_op->send_message->length, NULL);
+ /* Check that compression flag is OFF. We don't support compression yet. */
+ if (stream_op->send_message->flags != 0) {
+ gpr_log(GPR_ERROR, "Compression is not supported");
+ GPR_ASSERT(stream_op->send_message->flags == 0);
}
- s->num_headers = 0;
- convert_metadata_to_cronet_headers(op->send_initial_metadata->list.head,
- ct->host, s);
- s->header_array.count = s->num_headers;
- s->header_array.capacity = s->num_headers;
- s->header_array.headers = s->headers;
- GPR_ASSERT(!s->callback_list[CB_SEND_INITIAL_METADATA][0]);
- s->callback_list[CB_SEND_INITIAL_METADATA][0] = op->on_complete;
- }
- if (op->send_message) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "perform_stream_op - send_message: on_complete=%p",
- op->on_complete);
+ gpr_slice_buffer_add(&write_slice_buffer, slice);
+ if (write_slice_buffer.count != 1) {
+ /* Empty request not handled yet */
+ gpr_log(GPR_ERROR, "Empty request is not supported");
+ GPR_ASSERT(write_slice_buffer.count == 1);
+ }
+ if (write_slice_buffer.count > 0) {
+ size_t write_buffer_size;
+ create_grpc_frame(&write_slice_buffer, &stream_state->ws.write_buffer,
+ &write_buffer_size);
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_write (%p, %p)",
+ s->cbs, stream_state->ws.write_buffer);
+ stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
+ cronet_bidirectional_stream_write(s->cbs, stream_state->ws.write_buffer,
+ (int)write_buffer_size, false);
+ result = ACTION_TAKEN_WITH_CALLBACK;
}
- grpc_byte_stream_next(exec_ctx, op->send_message, &s->slice,
- op->send_message->length, NULL);
- // Check that compression flag is not ON. We don't support compression yet.
- // TODO (makdharma): add compression support
- GPR_ASSERT(op->send_message->flags == 0);
- gpr_slice_buffer_add(&s->write_slice_buffer, s->slice);
- if (s->cbs == NULL) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_create");
+ stream_state->state_op_done[OP_SEND_MESSAGE] = true;
+ oas->state.state_op_done[OP_SEND_MESSAGE] = true;
+ } else if (stream_op->recv_message &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_RECV_MESSAGE)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_MESSAGE", oas);
+ if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_message_ready,
+ GRPC_ERROR_CANCELLED, NULL);
+ stream_state->state_op_done[OP_RECV_MESSAGE] = true;
+ } else if (stream_state->rs.read_stream_closed == true) {
+ /* No more data will be received */
+ CRONET_LOG(GPR_DEBUG, "read stream closed");
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_message_ready,
+ GRPC_ERROR_NONE, NULL);
+ stream_state->state_op_done[OP_RECV_MESSAGE] = true;
+ oas->state.state_op_done[OP_RECV_MESSAGE] = true;
+ } else if (stream_state->rs.length_field_received == false) {
+ if (stream_state->rs.received_bytes == GRPC_HEADER_SIZE_IN_BYTES &&
+ stream_state->rs.remaining_bytes == 0) {
+ /* Start a read operation for data */
+ stream_state->rs.length_field_received = true;
+ stream_state->rs.length_field = stream_state->rs.remaining_bytes =
+ parse_grpc_header((const uint8_t *)stream_state->rs.read_buffer);
+ CRONET_LOG(GPR_DEBUG, "length field = %d",
+ stream_state->rs.length_field);
+ if (stream_state->rs.length_field > 0) {
+ stream_state->rs.read_buffer =
+ gpr_malloc((size_t)stream_state->rs.length_field);
+ GPR_ASSERT(stream_state->rs.read_buffer);
+ stream_state->rs.remaining_bytes = stream_state->rs.length_field;
+ stream_state->rs.received_bytes = 0;
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs);
+ stream_state->state_op_done[OP_READ_REQ_MADE] =
+ true; /* Indicates that at least one read request has been made */
+ cronet_bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer,
+ stream_state->rs.remaining_bytes);
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ } else {
+ stream_state->rs.remaining_bytes = 0;
+ CRONET_LOG(GPR_DEBUG, "read operation complete. Empty response.");
+ gpr_slice_buffer_init(&stream_state->rs.read_slice_buffer);
+ grpc_slice_buffer_stream_init(&stream_state->rs.sbs,
+ &stream_state->rs.read_slice_buffer, 0);
+ *((grpc_byte_buffer **)stream_op->recv_message) =
+ (grpc_byte_buffer *)&stream_state->rs.sbs;
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_message_ready,
+ GRPC_ERROR_NONE, NULL);
+ stream_state->state_op_done[OP_RECV_MESSAGE] = true;
+ oas->state.state_op_done[OP_RECV_MESSAGE] = true;
+ result = ACTION_TAKEN_NO_CALLBACK;
+ }
+ } else if (stream_state->rs.remaining_bytes == 0) {
+ /* Start a read operation for first 5 bytes (GRPC header) */
+ stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes;
+ stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES;
+ stream_state->rs.received_bytes = 0;
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs);
+ stream_state->state_op_done[OP_READ_REQ_MADE] =
+ true; /* Indicates that at least one read request has been made */
+ cronet_bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer,
+ stream_state->rs.remaining_bytes);
}
- s->cbs = cronet_bidirectional_stream_create(ct->engine, s, &callbacks);
- GPR_ASSERT(s->cbs);
- s->read_closed = false;
- s->response_trailers_received = false;
- s->response_headers_received = false;
- s->cronet_send_state = CRONET_SEND_IDLE;
- s->cronet_recv_state = CRONET_RECV_IDLE;
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ } else if (stream_state->rs.remaining_bytes == 0) {
+ CRONET_LOG(GPR_DEBUG, "read operation complete");
+ gpr_slice read_data_slice =
+ gpr_slice_malloc((uint32_t)stream_state->rs.length_field);
+ uint8_t *dst_p = GPR_SLICE_START_PTR(read_data_slice);
+ memcpy(dst_p, stream_state->rs.read_buffer,
+ (size_t)stream_state->rs.length_field);
+ gpr_slice_buffer_init(&stream_state->rs.read_slice_buffer);
+ gpr_slice_buffer_add(&stream_state->rs.read_slice_buffer,
+ read_data_slice);
+ grpc_slice_buffer_stream_init(&stream_state->rs.sbs,
+ &stream_state->rs.read_slice_buffer, 0);
+ *((grpc_byte_buffer **)stream_op->recv_message) =
+ (grpc_byte_buffer *)&stream_state->rs.sbs;
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_message_ready,
+ GRPC_ERROR_NONE, NULL);
+ stream_state->state_op_done[OP_RECV_MESSAGE] = true;
+ oas->state.state_op_done[OP_RECV_MESSAGE] = true;
+ /* Clear read state of the stream, so next read op (if it were to come)
+ * will work */
+ stream_state->rs.received_bytes = stream_state->rs.remaining_bytes =
+ stream_state->rs.length_field_received = 0;
+ result = ACTION_TAKEN_NO_CALLBACK;
}
- GPR_ASSERT(!s->callback_list[CB_SEND_MESSAGE][0]);
- s->callback_list[CB_SEND_MESSAGE][0] = op->on_complete;
- next_send_step(s);
- }
- if (op->send_trailing_metadata) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG,
- "perform_stream_op - send_trailing_metadata: on_complete=%p",
- op->on_complete);
+ } else if (stream_op->recv_trailing_metadata &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_RECV_TRAILING_METADATA)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas);
+ if (oas->s->state.rs.trailing_metadata_valid) {
+ grpc_chttp2_incoming_metadata_buffer_publish(
+ &oas->s->state.rs.trailing_metadata,
+ stream_op->recv_trailing_metadata);
+ stream_state->rs.trailing_metadata_valid = false;
}
- GPR_ASSERT(!s->callback_list[CB_SEND_TRAILING_METADATA][0]);
- s->callback_list[CB_SEND_TRAILING_METADATA][0] = op->on_complete;
+ stream_state->state_op_done[OP_RECV_TRAILING_METADATA] = true;
+ result = ACTION_TAKEN_NO_CALLBACK;
+ } else if (stream_op->send_trailing_metadata &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_SEND_TRAILING_METADATA)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_TRAILING_METADATA", oas);
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_write (%p, 0)", s->cbs);
+ stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
+ cronet_bidirectional_stream_write(s->cbs, "", 0, true);
+ stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true;
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ } else if (stream_op->cancel_error &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_CANCEL_ERROR)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_CANCEL_ERROR", oas);
+ CRONET_LOG(GPR_DEBUG, "W: cronet_bidirectional_stream_cancel(%p)", s->cbs);
if (s->cbs) {
- // Send an "empty" write to the far end to signal that we're done.
- // This will induce the server to send down trailers.
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write");
- }
- cronet_bidirectional_stream_write(s->cbs, "abc", 0, true);
- } else {
- // We never created a stream. This was probably an empty request.
- invoke_closing_callback(s);
+ cronet_bidirectional_stream_cancel(s->cbs);
}
+ stream_state->state_op_done[OP_CANCEL_ERROR] = true;
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ } else if (stream_op->on_complete &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_ON_COMPLETE)) {
+ /* All actions in this stream_op are complete. Call the on_complete callback
+ */
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_ON_COMPLETE", oas);
+ grpc_exec_ctx_sched(exec_ctx, stream_op->on_complete, GRPC_ERROR_NONE,
+ NULL);
+ oas->state.state_op_done[OP_ON_COMPLETE] = true;
+ oas->done = true;
+ /* reset any send message state, only if this ON_COMPLETE is about a send.
+ */
+ if (stream_op->send_message) {
+ stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
+ stream_state->state_op_done[OP_SEND_MESSAGE] = false;
+ }
+ result = ACTION_TAKEN_NO_CALLBACK;
+ /* If this is the on_complete callback being called for a received message -
+ make a note */
+ if (stream_op->recv_message)
+ stream_state->state_op_done[OP_RECV_MESSAGE_AND_ON_COMPLETE] = true;
+ } else {
+ result = NO_ACTION_POSSIBLE;
}
+ return result;
}
+/*
+ Functions used by upper layers to access transport functionality.
+*/
+
static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_stream_refcount *refcount,
const void *server_data) {
stream_obj *s = (stream_obj *)gs;
- memset(s->callback_list, 0, sizeof(s->callback_list));
+ memset(&s->storage, 0, sizeof(s->storage));
+ s->storage.head = NULL;
+ memset(&s->state, 0, sizeof(s->state));
+ s->curr_op = NULL;
s->cbs = NULL;
- gpr_mu_init(&s->recv_mu);
- s->read_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES);
- s->write_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES);
- gpr_slice_buffer_init(&s->write_slice_buffer);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_transport - init_stream");
- }
+ memset(&s->header_array, 0, sizeof(s->header_array));
+ memset(&s->state.rs, 0, sizeof(s->state.rs));
+ memset(&s->state.ws, 0, sizeof(s->state.ws));
+ memset(s->state.state_op_done, 0, sizeof(s->state.state_op_done));
+ memset(s->state.state_callback_received, 0,
+ sizeof(s->state.state_callback_received));
+ gpr_mu_init(&s->mu);
return 0;
}
-static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
- grpc_stream *gs, void *and_free_memory) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "Destroy stream");
- }
+static void set_pollset_do_nothing(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+ grpc_stream *gs, grpc_pollset *pollset) {}
+
+static void set_pollset_set_do_nothing(grpc_exec_ctx *exec_ctx,
+ grpc_transport *gt, grpc_stream *gs,
+ grpc_pollset_set *pollset_set) {}
+
+static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+ grpc_stream *gs, grpc_transport_stream_op *op) {
+ CRONET_LOG(GPR_DEBUG, "perform_stream_op");
stream_obj *s = (stream_obj *)gs;
- s->cbs = NULL;
- gpr_free(s->read_buffer);
- gpr_free(s->write_buffer);
- gpr_free(s->url);
- gpr_mu_destroy(&s->recv_mu);
- if (and_free_memory) {
- gpr_free(and_free_memory);
- }
+ s->curr_gs = gs;
+ memcpy(&s->curr_ct, gt, sizeof(grpc_cronet_transport));
+ add_to_storage(s, op);
+ execute_from_storage(s);
}
-static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
- grpc_cronet_transport *ct = (grpc_cronet_transport *)gt;
- gpr_free(ct->host);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "Destroy transport");
- }
+static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+ grpc_stream *gs, void *and_free_memory) {}
+
+static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {}
+
+static char *get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
+ return NULL;
}
+static void perform_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+ grpc_transport_op *op) {}
+
const grpc_transport_vtable grpc_cronet_vtable = {sizeof(stream_obj),
"cronet_http",
init_stream,
set_pollset_do_nothing,
set_pollset_set_do_nothing,
perform_stream_op,
- NULL,
+ perform_op,
destroy_stream,
destroy_transport,
- NULL};
+ get_peer};
diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h
index 653d04f427..aec61ee7c6 100644
--- a/src/core/lib/channel/channel_args.h
+++ b/src/core/lib/channel/channel_args.h
@@ -37,6 +37,8 @@
#include <grpc/compression.h>
#include <grpc/grpc.h>
+// Channel args are intentionally immutable, to avoid the need for locking.
+
/** Copy the arguments in \a src into a new instance */
grpc_channel_args *grpc_channel_args_copy(const grpc_channel_args *src);
diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c
index 87175d7943..98f304f2da 100644
--- a/src/core/lib/channel/channel_stack.c
+++ b/src/core/lib/channel/channel_stack.c
@@ -157,12 +157,13 @@ void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
}
}
-void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
- grpc_channel_stack *channel_stack, int initial_refs,
- grpc_iomgr_cb_func destroy, void *destroy_arg,
- grpc_call_context_element *context,
- const void *transport_server_data,
- grpc_call_stack *call_stack) {
+grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
+ grpc_channel_stack *channel_stack,
+ int initial_refs, grpc_iomgr_cb_func destroy,
+ void *destroy_arg,
+ grpc_call_context_element *context,
+ const void *transport_server_data,
+ grpc_call_stack *call_stack) {
grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
grpc_call_element_args args;
size_t count = channel_stack->count;
@@ -178,6 +179,7 @@ void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
/* init per-filter data */
+ grpc_error *first_error = GRPC_ERROR_NONE;
for (i = 0; i < count; i++) {
args.call_stack = call_stack;
args.server_transport_data = transport_server_data;
@@ -185,10 +187,19 @@ void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
call_elems[i].filter = channel_elems[i].filter;
call_elems[i].channel_data = channel_elems[i].channel_data;
call_elems[i].call_data = user_data;
- call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i], &args);
+ grpc_error *error =
+ call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i], &args);
+ if (error != GRPC_ERROR_NONE) {
+ if (first_error == GRPC_ERROR_NONE) {
+ first_error = error;
+ } else {
+ GRPC_ERROR_UNREF(error);
+ }
+ }
user_data +=
ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
}
+ return first_error;
}
void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
@@ -217,7 +228,7 @@ void grpc_call_stack_ignore_set_pollset_or_pollset_set(
grpc_polling_entity *pollent) {}
void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack,
- const grpc_call_stats *call_stats,
+ const grpc_call_final_info *final_info,
void *and_free_memory) {
grpc_call_element *elems = CALL_ELEMS_FROM_STACK(stack);
size_t count = stack->count;
@@ -225,7 +236,7 @@ void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack,
/* destroy per-filter data */
for (i = 0; i < count; i++) {
- elems[i].filter->destroy_call_elem(exec_ctx, &elems[i], call_stats,
+ elems[i].filter->destroy_call_elem(exec_ctx, &elems[i], final_info,
i == count - 1 ? and_free_memory : NULL);
}
}
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
index d72c015b67..6b73cce380 100644
--- a/src/core/lib/channel/channel_stack.h
+++ b/src/core/lib/channel/channel_stack.h
@@ -51,6 +51,10 @@
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/transport/transport.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef struct grpc_channel_element grpc_channel_element;
typedef struct grpc_call_element grpc_call_element;
@@ -75,9 +79,14 @@ typedef struct {
typedef struct {
grpc_transport_stream_stats transport_stream_stats;
gpr_timespec latency; /* From call creating to enqueing of received status */
- grpc_status_code final_status;
} grpc_call_stats;
+/** Information about the call upon completion. */
+typedef struct {
+ grpc_call_stats stats;
+ grpc_status_code final_status;
+} grpc_call_final_info;
+
/* Channel filters specify:
1. the amount of memory needed in the channel & call (via the sizeof_XXX
members)
@@ -110,8 +119,9 @@ typedef struct {
on a client; if it is non-NULL, then it points to memory owned by the
transport and is on the server. Most filters want to ignore this
argument. */
- void (*init_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_call_element_args *args);
+ grpc_error *(*init_call_elem)(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args);
void (*set_pollset_or_pollset_set)(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_polling_entity *pollent);
@@ -119,16 +129,17 @@ typedef struct {
The filter does not need to do any chaining.
The bottom filter of a stack will be passed a non-NULL pointer to
\a and_free_memory that should be passed to gpr_free when destruction
- is complete. */
+ is complete. \a final_info contains data about the completed call, mainly
+ for reporting purposes. */
void (*destroy_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- const grpc_call_stats *stats,
+ const grpc_call_final_info *final_info,
void *and_free_memory);
/* sizeof(per channel data) */
size_t sizeof_channel_data;
/* Initialize per-channel data.
- elem is initialized at the start of the call, and elem->channel_data is
- what needs initializing.
+ elem is initialized at the creating of the channel, and elem->channel_data
+ is what needs initializing.
is_first, is_last designate this elements position in the stack, and are
useful for asserting correct configuration by upper layer code.
The filter does not need to do any chaining */
@@ -209,12 +220,13 @@ void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
/* Initialize a call stack given a channel stack. transport_server_data is
expected to be NULL on a client, or an opaque transport owned pointer on the
server. */
-void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
- grpc_channel_stack *channel_stack, int initial_refs,
- grpc_iomgr_cb_func destroy, void *destroy_arg,
- grpc_call_context_element *context,
- const void *transport_server_data,
- grpc_call_stack *call_stack);
+grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
+ grpc_channel_stack *channel_stack,
+ int initial_refs, grpc_iomgr_cb_func destroy,
+ void *destroy_arg,
+ grpc_call_context_element *context,
+ const void *transport_server_data,
+ grpc_call_stack *call_stack);
/* Set a pollset or a pollset_set for a call stack: must occur before the first
* op is started */
void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
@@ -243,7 +255,7 @@ void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
/* Destroy a call stack */
void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack,
- const grpc_call_stats *call_stats,
+ const grpc_call_final_info *final_info,
void *and_free_memory);
/* Ignore set pollset{_set} - used by filters if they don't care about pollsets
@@ -283,4 +295,8 @@ extern int grpc_trace_channel;
#define GRPC_CALL_LOG_OP(sev, elem, op) \
if (grpc_trace_channel) grpc_call_log_op(sev, elem, op)
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_H */
diff --git a/src/core/lib/channel/channel_stack_builder.h b/src/core/lib/channel/channel_stack_builder.h
index 0e6bfd9aa6..4a00f7bfdb 100644
--- a/src/core/lib/channel/channel_stack_builder.h
+++ b/src/core/lib/channel/channel_stack_builder.h
@@ -39,6 +39,10 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/// grpc_channel_stack_builder offers a programmatic interface to selected
/// and order channel filters
typedef struct grpc_channel_stack_builder grpc_channel_stack_builder;
@@ -158,4 +162,8 @@ void grpc_channel_stack_builder_destroy(grpc_channel_stack_builder *builder);
extern int grpc_trace_channel_stack_builder;
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_BUILDER_H */
diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c
index 32ebe53ee6..134180e619 100644
--- a/src/core/lib/channel/compress_filter.c
+++ b/src/core/lib/channel/compress_filter.c
@@ -256,8 +256,9 @@ static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
}
/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
@@ -266,11 +267,14 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
calld->has_compression_algorithm = 0;
grpc_closure_init(&calld->got_slice, got_slice, elem);
grpc_closure_init(&calld->send_done, send_done, elem);
+
+ return GRPC_ERROR_NONE;
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- const grpc_call_stats *stats, void *ignored) {
+ const grpc_call_final_info *final_info,
+ void *ignored) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
gpr_slice_buffer_destroy(&calld->slices);
diff --git a/src/core/lib/channel/connected_channel.c b/src/core/lib/channel/connected_channel.c
index 0a7d27a1dc..918379c845 100644
--- a/src/core/lib/channel/connected_channel.c
+++ b/src/core/lib/channel/connected_channel.c
@@ -81,16 +81,16 @@ static void con_start_transport_op(grpc_exec_ctx *exec_ctx,
}
/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
- int r;
-
- r = grpc_transport_init_stream(
+ int r = grpc_transport_init_stream(
exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld),
&args->call_stack->refcount, args->server_transport_data);
- GPR_ASSERT(r == 0);
+ return r == 0 ? GRPC_ERROR_NONE
+ : GRPC_ERROR_CREATE("transport stream initialization failed");
}
static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
@@ -104,7 +104,7 @@ static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
/* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- const grpc_call_stats *stats,
+ const grpc_call_final_info *final_info,
void *and_free_memory) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
diff --git a/src/core/lib/channel/context.h b/src/core/lib/channel/context.h
index c50e84279d..071c5f695c 100644
--- a/src/core/lib/channel/context.h
+++ b/src/core/lib/channel/context.h
@@ -34,10 +34,19 @@
#ifndef GRPC_CORE_LIB_CHANNEL_CONTEXT_H
#define GRPC_CORE_LIB_CHANNEL_CONTEXT_H
-/* Call object context pointers */
+/// Call object context pointers.
+
+/// Call context is represented as an array of \a grpc_call_context_elements.
+/// This enum represents the indexes into the array, where each index
+/// contains a different type of value.
typedef enum {
+ /// Value is either a \a grpc_client_security_context or a
+ /// \a grpc_server_security_context.
GRPC_CONTEXT_SECURITY = 0,
+
+ /// Value is a \a census_context.
GRPC_CONTEXT_TRACING,
+
GRPC_CONTEXT_COUNT
} grpc_context_index;
diff --git a/src/core/lib/channel/handshaker.c b/src/core/lib/channel/handshaker.c
new file mode 100644
index 0000000000..c0979f5e80
--- /dev/null
+++ b/src/core/lib/channel/handshaker.c
@@ -0,0 +1,203 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <string.h>
+
+#include <grpc/impl/codegen/alloc.h>
+#include <grpc/impl/codegen/log.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/handshaker.h"
+
+//
+// grpc_handshaker
+//
+
+void grpc_handshaker_init(const struct grpc_handshaker_vtable* vtable,
+ grpc_handshaker* handshaker) {
+ handshaker->vtable = vtable;
+}
+
+void grpc_handshaker_destroy(grpc_exec_ctx* exec_ctx,
+ grpc_handshaker* handshaker) {
+ handshaker->vtable->destroy(exec_ctx, handshaker);
+}
+
+void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx,
+ grpc_handshaker* handshaker) {
+ handshaker->vtable->shutdown(exec_ctx, handshaker);
+}
+
+void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx,
+ grpc_handshaker* handshaker,
+ grpc_endpoint* endpoint,
+ grpc_channel_args* args,
+ gpr_slice_buffer* read_buffer,
+ gpr_timespec deadline,
+ grpc_tcp_server_acceptor* acceptor,
+ grpc_handshaker_done_cb cb, void* user_data) {
+ handshaker->vtable->do_handshake(exec_ctx, handshaker, endpoint, args,
+ read_buffer, deadline, acceptor, cb,
+ user_data);
+}
+
+//
+// grpc_handshake_manager
+//
+
+// State used while chaining handshakers.
+struct grpc_handshaker_state {
+ // The index of the handshaker to invoke next.
+ size_t index;
+ // The deadline for all handshakers.
+ gpr_timespec deadline;
+ // The acceptor to call the handshakers with.
+ grpc_tcp_server_acceptor* acceptor;
+ // The final callback and user_data to invoke after the last handshaker.
+ grpc_handshaker_done_cb final_cb;
+ void* final_user_data;
+};
+
+struct grpc_handshake_manager {
+ // An array of handshakers added via grpc_handshake_manager_add().
+ size_t count;
+ grpc_handshaker** handshakers;
+ // State used while chaining handshakers.
+ struct grpc_handshaker_state* state;
+};
+
+grpc_handshake_manager* grpc_handshake_manager_create() {
+ grpc_handshake_manager* mgr = gpr_malloc(sizeof(grpc_handshake_manager));
+ memset(mgr, 0, sizeof(*mgr));
+ return mgr;
+}
+
+static bool is_power_of_2(size_t n) { return (n & (n - 1)) == 0; }
+
+void grpc_handshake_manager_add(grpc_handshake_manager* mgr,
+ grpc_handshaker* handshaker) {
+ // To avoid allocating memory for each handshaker we add, we double
+ // the number of elements every time we need more.
+ size_t realloc_count = 0;
+ if (mgr->count == 0) {
+ realloc_count = 2;
+ } else if (mgr->count >= 2 && is_power_of_2(mgr->count)) {
+ realloc_count = mgr->count * 2;
+ }
+ if (realloc_count > 0) {
+ mgr->handshakers =
+ gpr_realloc(mgr->handshakers, realloc_count * sizeof(grpc_handshaker*));
+ }
+ mgr->handshakers[mgr->count++] = handshaker;
+}
+
+void grpc_handshake_manager_destroy(grpc_exec_ctx* exec_ctx,
+ grpc_handshake_manager* mgr) {
+ for (size_t i = 0; i < mgr->count; ++i) {
+ grpc_handshaker_destroy(exec_ctx, mgr->handshakers[i]);
+ }
+ gpr_free(mgr->handshakers);
+ gpr_free(mgr);
+}
+
+void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx,
+ grpc_handshake_manager* mgr) {
+ for (size_t i = 0; i < mgr->count; ++i) {
+ grpc_handshaker_shutdown(exec_ctx, mgr->handshakers[i]);
+ }
+ if (mgr->state != NULL) {
+ gpr_free(mgr->state);
+ mgr->state = NULL;
+ }
+}
+
+// A function used as the handshaker-done callback when chaining
+// handshakers together.
+static void call_next_handshaker(grpc_exec_ctx* exec_ctx,
+ grpc_endpoint* endpoint,
+ grpc_channel_args* args,
+ gpr_slice_buffer* read_buffer, void* user_data,
+ grpc_error* error) {
+ grpc_handshake_manager* mgr = user_data;
+ GPR_ASSERT(mgr->state != NULL);
+ GPR_ASSERT(mgr->state->index < mgr->count);
+ // If we got an error, skip all remaining handshakers and invoke the
+ // caller-supplied callback immediately.
+ if (error != GRPC_ERROR_NONE) {
+ mgr->state->final_cb(exec_ctx, endpoint, args, read_buffer,
+ mgr->state->final_user_data, error);
+ return;
+ }
+ grpc_handshaker_done_cb cb = call_next_handshaker;
+ // If this is the last handshaker, use the caller-supplied callback
+ // and user_data instead of chaining back to this function again.
+ if (mgr->state->index == mgr->count - 1) {
+ cb = mgr->state->final_cb;
+ user_data = mgr->state->final_user_data;
+ }
+ // Invoke handshaker.
+ grpc_handshaker_do_handshake(
+ exec_ctx, mgr->handshakers[mgr->state->index], endpoint, args,
+ read_buffer, mgr->state->deadline, mgr->state->acceptor, cb, user_data);
+ ++mgr->state->index;
+ // If this is the last handshaker, clean up state.
+ if (mgr->state->index == mgr->count) {
+ gpr_free(mgr->state);
+ mgr->state = NULL;
+ }
+}
+
+void grpc_handshake_manager_do_handshake(
+ grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr,
+ grpc_endpoint* endpoint, const grpc_channel_args* args,
+ gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor,
+ grpc_handshaker_done_cb cb, void* user_data) {
+ grpc_channel_args* args_copy = grpc_channel_args_copy(args);
+ gpr_slice_buffer* read_buffer = malloc(sizeof(*read_buffer));
+ gpr_slice_buffer_init(read_buffer);
+ if (mgr->count == 0) {
+ // No handshakers registered, so we just immediately call the done
+ // callback with the passed-in endpoint.
+ cb(exec_ctx, endpoint, args_copy, read_buffer, user_data, GRPC_ERROR_NONE);
+ } else {
+ GPR_ASSERT(mgr->state == NULL);
+ mgr->state = gpr_malloc(sizeof(struct grpc_handshaker_state));
+ memset(mgr->state, 0, sizeof(*mgr->state));
+ mgr->state->deadline = deadline;
+ mgr->state->acceptor = acceptor;
+ mgr->state->final_cb = cb;
+ mgr->state->final_user_data = user_data;
+ call_next_handshaker(exec_ctx, endpoint, args_copy, read_buffer, mgr,
+ GRPC_ERROR_NONE);
+ }
+}
diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h
new file mode 100644
index 0000000000..b276f6028c
--- /dev/null
+++ b/src/core/lib/channel/handshaker.h
@@ -0,0 +1,150 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H
+#define GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/impl/codegen/time.h>
+#include <grpc/support/slice_buffer.h>
+
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/tcp_server.h"
+
+/// Handshakers are used to perform initial handshakes on a connection
+/// before the client sends the initial request. Some examples of what
+/// a handshaker can be used for includes support for HTTP CONNECT on
+/// the client side and various types of security initialization.
+///
+/// In general, handshakers should be used via a handshake manager.
+
+///
+/// grpc_handshaker
+///
+
+typedef struct grpc_handshaker grpc_handshaker;
+
+/// Callback type invoked when a handshaker is done.
+/// Takes ownership of \a args and \a read_buffer.
+typedef void (*grpc_handshaker_done_cb)(grpc_exec_ctx* exec_ctx,
+ grpc_endpoint* endpoint,
+ grpc_channel_args* args,
+ gpr_slice_buffer* read_buffer,
+ void* user_data, grpc_error* error);
+
+struct grpc_handshaker_vtable {
+ /// Destroys the handshaker.
+ void (*destroy)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker);
+
+ /// Shuts down the handshaker (e.g., to clean up when the operation is
+ /// aborted in the middle).
+ void (*shutdown)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker);
+
+ /// Performs handshaking. When finished, calls \a cb with \a user_data.
+ /// Takes ownership of \a args.
+ /// Takes ownership of \a read_buffer, which contains leftover bytes read
+ /// from the endpoint by the previous handshaker.
+ /// \a acceptor will be NULL for client-side handshakers.
+ void (*do_handshake)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker,
+ grpc_endpoint* endpoint, grpc_channel_args* args,
+ gpr_slice_buffer* read_buffer, gpr_timespec deadline,
+ grpc_tcp_server_acceptor* acceptor,
+ grpc_handshaker_done_cb cb, void* user_data);
+};
+
+/// Base struct. To subclass, make this the first member of the
+/// implementation struct.
+struct grpc_handshaker {
+ const struct grpc_handshaker_vtable* vtable;
+};
+
+/// Called by concrete implementations to initialize the base struct.
+void grpc_handshaker_init(const struct grpc_handshaker_vtable* vtable,
+ grpc_handshaker* handshaker);
+
+/// Convenient wrappers for invoking methods via the vtable.
+/// These probably do not need to be called from anywhere but
+/// grpc_handshake_manager.
+void grpc_handshaker_destroy(grpc_exec_ctx* exec_ctx,
+ grpc_handshaker* handshaker);
+void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx,
+ grpc_handshaker* handshaker);
+void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx,
+ grpc_handshaker* handshaker,
+ grpc_endpoint* endpoint,
+ grpc_channel_args* args,
+ gpr_slice_buffer* read_buffer,
+ gpr_timespec deadline,
+ grpc_tcp_server_acceptor* acceptor,
+ grpc_handshaker_done_cb cb, void* user_data);
+
+///
+/// grpc_handshake_manager
+///
+
+typedef struct grpc_handshake_manager grpc_handshake_manager;
+
+/// Creates a new handshake manager. Caller takes ownership.
+grpc_handshake_manager* grpc_handshake_manager_create();
+
+/// Adds a handshaker to the handshake manager.
+/// Takes ownership of \a handshaker.
+void grpc_handshake_manager_add(grpc_handshake_manager* mgr,
+ grpc_handshaker* handshaker);
+
+/// Destroys the handshake manager.
+void grpc_handshake_manager_destroy(grpc_exec_ctx* exec_ctx,
+ grpc_handshake_manager* mgr);
+
+/// Shuts down the handshake manager (e.g., to clean up when the operation is
+/// aborted in the middle).
+/// The caller must still call grpc_handshake_manager_destroy() after
+/// calling this function.
+void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx,
+ grpc_handshake_manager* mgr);
+
+/// Invokes handshakers in the order they were added.
+/// Does NOT take ownership of \a args. Instead, makes a copy before
+/// invoking the first handshaker.
+/// \a acceptor will be NULL for client-side handshakers.
+/// Invokes \a cb with \a user_data after either a handshaker fails or
+/// all handshakers have completed successfully.
+void grpc_handshake_manager_do_handshake(
+ grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr,
+ grpc_endpoint* endpoint, const grpc_channel_args* args,
+ gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor,
+ grpc_handshaker_done_cb cb, void* user_data);
+
+#endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H */
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c
index 8057e251f0..a7a775cc53 100644
--- a/src/core/lib/channel/http_client_filter.c
+++ b/src/core/lib/channel/http_client_filter.c
@@ -175,16 +175,19 @@ static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
}
/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
call_data *calld = elem->call_data;
calld->on_done_recv = NULL;
grpc_closure_init(&calld->hc_on_recv, hc_on_recv, elem);
+ return GRPC_ERROR_NONE;
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- const grpc_call_stats *stats, void *ignored) {}
+ const grpc_call_final_info *final_info,
+ void *ignored) {}
static grpc_mdelem *scheme_from_args(const grpc_channel_args *args) {
unsigned i;
diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c
index d0beebd817..5ce51f9016 100644
--- a/src/core/lib/channel/http_server_filter.c
+++ b/src/core/lib/channel/http_server_filter.c
@@ -224,18 +224,21 @@ static void hs_start_transport_op(grpc_exec_ctx *exec_ctx,
}
/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
/* initialize members */
memset(calld, 0, sizeof(*calld));
grpc_closure_init(&calld->hs_on_recv, hs_on_recv, elem);
+ return GRPC_ERROR_NONE;
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- const grpc_call_stats *stats, void *ignored) {}
+ const grpc_call_final_info *final_info,
+ void *ignored) {}
/* Constructor for channel_data */
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/http/httpcli_security_connector.c b/src/core/lib/http/httpcli_security_connector.c
index a57d93bb7b..0006e809a6 100644
--- a/src/core/lib/http/httpcli_security_connector.c
+++ b/src/core/lib/http/httpcli_security_connector.c
@@ -61,6 +61,7 @@ static void httpcli_ssl_destroy(grpc_security_connector *sc) {
static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc,
grpc_endpoint *nonsecure_endpoint,
+ gpr_slice_buffer *read_buffer,
gpr_timespec deadline,
grpc_security_handshake_done_cb cb,
void *user_data) {
@@ -69,6 +70,7 @@ static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
tsi_result result = TSI_OK;
tsi_handshaker *handshaker;
if (c->handshaker_factory == NULL) {
+ gpr_free(read_buffer);
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
return;
}
@@ -77,10 +79,12 @@ static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
tsi_result_to_string(result));
+ gpr_free(read_buffer);
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
} else {
grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
- nonsecure_endpoint, deadline, cb, user_data);
+ nonsecure_endpoint, read_buffer, deadline, cb,
+ user_data);
}
}
@@ -183,7 +187,7 @@ static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
pem_root_certs, pem_root_certs_size, host, &sc) ==
GRPC_SECURITY_OK);
grpc_channel_security_connector_do_handshake(
- exec_ctx, sc, tcp, deadline, on_secure_transport_setup_done, c);
+ exec_ctx, sc, tcp, NULL, deadline, on_secure_transport_setup_done, c);
GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli");
}
diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h
index 13f898e31a..bc7781250e 100644
--- a/src/core/lib/iomgr/error.h
+++ b/src/core/lib/iomgr/error.h
@@ -171,6 +171,8 @@ grpc_error *grpc_error_set_time(grpc_error *src, grpc_error_times which,
gpr_timespec value) GRPC_MUST_USE_RESULT;
grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which,
const char *value) GRPC_MUST_USE_RESULT;
+/// Returns NULL if the specified string is not set.
+/// Caller does NOT own return value.
const char *grpc_error_get_str(grpc_error *error, grpc_error_strs which);
/// Add a child error: an error that is believed to have contributed to this
/// error occurring. Allows root causing high level errors from lower level
diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c
index 6a63c4d1d1..02bcbaa10f 100644
--- a/src/core/lib/iomgr/ev_epoll_linux.c
+++ b/src/core/lib/iomgr/ev_epoll_linux.c
@@ -42,6 +42,7 @@
#include <assert.h>
#include <errno.h>
#include <poll.h>
+#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <sys/epoll.h>
diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c
index 4b593f4b2c..16a5e3083e 100644
--- a/src/core/lib/iomgr/ev_poll_posix.c
+++ b/src/core/lib/iomgr/ev_poll_posix.c
@@ -844,6 +844,11 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
*worker_hdl = &worker;
grpc_error *error = GRPC_ERROR_NONE;
+ /* Avoid malloc for small number of elements. */
+ enum { inline_elements = 96 };
+ struct pollfd pollfd_space[inline_elements];
+ struct grpc_fd_watcher watcher_space[inline_elements];
+
/* pollset->mu already held */
int added_worker = 0;
int locked = 1;
@@ -899,15 +904,23 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
int r;
size_t i, fd_count;
nfds_t pfd_count;
- /* TODO(ctiller): inline some elements to avoid an allocation */
grpc_fd_watcher *watchers;
struct pollfd *pfds;
timeout = poll_deadline_to_millis_timeout(deadline, now);
- /* TODO(ctiller): perform just one malloc here if we exceed the inline
- * case */
- pfds = gpr_malloc(sizeof(*pfds) * (pollset->fd_count + 2));
- watchers = gpr_malloc(sizeof(*watchers) * (pollset->fd_count + 2));
+
+ if (pollset->fd_count + 2 <= inline_elements) {
+ pfds = pollfd_space;
+ watchers = watcher_space;
+ } else {
+ /* Allocate one buffer to hold both pfds and watchers arrays */
+ const size_t pfd_size = sizeof(*pfds) * (pollset->fd_count + 2);
+ const size_t watch_size = sizeof(*watchers) * (pollset->fd_count + 2);
+ void *buf = gpr_malloc(pfd_size + watch_size);
+ pfds = buf;
+ watchers = (void *)((char *)buf + pfd_size);
+ }
+
fd_count = 0;
pfd_count = 2;
pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd);
@@ -974,8 +987,11 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
}
}
- gpr_free(pfds);
- gpr_free(watchers);
+ if (pfds != pollfd_space) {
+ /* pfds and watchers are in the same memory block pointed to by pfds */
+ gpr_free(pfds);
+ }
+
GPR_TIMER_END("maybe_work_and_unlock", 0);
locked = 0;
} else {
diff --git a/src/core/lib/iomgr/network_status_tracker.c b/src/core/lib/iomgr/network_status_tracker.c
index 90c074b007..b4bb7e3cf7 100644
--- a/src/core/lib/iomgr/network_status_tracker.c
+++ b/src/core/lib/iomgr/network_status_tracker.c
@@ -56,6 +56,15 @@ void grpc_network_status_init(void) {
// TODO(makarandd): Install callback with OS to monitor network status.
}
+void grpc_destroy_network_status_monitor() {
+ for (endpoint_ll_node *curr = head; curr != NULL;) {
+ endpoint_ll_node *next = curr->next;
+ gpr_free(curr);
+ curr = next;
+ }
+ gpr_mu_destroy(&g_endpoint_mutex);
+}
+
void grpc_network_status_register_endpoint(grpc_endpoint *ep) {
gpr_mu_lock(&g_endpoint_mutex);
if (head == NULL) {
diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c
index ec21e03944..974d5ae479 100644
--- a/src/core/lib/iomgr/tcp_posix.c
+++ b/src/core/lib/iomgr/tcp_posix.c
@@ -284,7 +284,7 @@ static void tcp_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
}
/* returns true if done, false if pending; if returning true, *error is set */
-#define MAX_WRITE_IOVEC 1024
+#define MAX_WRITE_IOVEC 1000
static bool tcp_flush(grpc_tcp *tcp, grpc_error **error) {
struct msghdr msg;
struct iovec iov[MAX_WRITE_IOVEC];
diff --git a/src/core/lib/iomgr/tcp_server.h b/src/core/lib/iomgr/tcp_server.h
index 875a6ca14a..5a25d39a0c 100644
--- a/src/core/lib/iomgr/tcp_server.h
+++ b/src/core/lib/iomgr/tcp_server.h
@@ -105,4 +105,8 @@ void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
a call (exec_ctx!=NULL) to shutdown_complete. */
void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s);
+/* Shutdown the fds of listeners. */
+void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx,
+ grpc_tcp_server *s);
+
#endif /* GRPC_CORE_LIB_IOMGR_TCP_SERVER_H */
diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c
index cb2ff782d6..ea8d241154 100644
--- a/src/core/lib/iomgr/tcp_server_posix.c
+++ b/src/core/lib/iomgr/tcp_server_posix.c
@@ -90,10 +90,12 @@ struct grpc_tcp_listener {
grpc_closure read_closure;
grpc_closure destroyed_closure;
struct grpc_tcp_listener *next;
- /* When we add a listener, more than one can be created, mainly because of
- IPv6. A sibling will still be in the normal list, but will be flagged
- as such. Any action, such as ref or unref, will affect all of the
- siblings in the list. */
+ /* sibling is a linked list of all listeners for a given port. add_port and
+ clone_port place all new listeners in the same sibling list. A member of
+ the 'sibling' list is also a member of the 'next' list. The head of each
+ sibling list has is_sibling==0, and subsequent members of sibling lists
+ have is_sibling==1. is_sibling allows separate sibling lists to be
+ identified while iterating through 'next'. */
struct grpc_tcp_listener *sibling;
int is_sibling;
};
@@ -306,7 +308,7 @@ static grpc_error *prepare_socket(int fd, const struct sockaddr *addr,
GPR_ASSERT(fd >= 0);
- if (so_reuseport) {
+ if (so_reuseport && !grpc_is_unix_socket(addr)) {
err = grpc_set_socket_reuse_port(fd, 1);
if (err != GRPC_ERROR_NONE) goto error;
}
@@ -480,6 +482,9 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd,
return err;
}
+/* Insert count new listeners after listener. Every new listener will have the
+ same listen address as listener (SO_REUSEPORT must be enabled). Every new
+ listener is a sibling of listener. */
static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
grpc_tcp_listener *sp = NULL;
char *addr_str;
@@ -506,6 +511,11 @@ static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
sp = gpr_malloc(sizeof(grpc_tcp_listener));
sp->next = listener->next;
listener->next = sp;
+ /* sp (the new listener) is a sibling of 'listener' (the original
+ listener). */
+ sp->is_sibling = 1;
+ sp->sibling = listener->sibling;
+ listener->sibling = sp;
sp->server = listener->server;
sp->fd = fd;
sp->emfd = grpc_fd_create(fd, name);
@@ -514,8 +524,6 @@ static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
sp->port = port;
sp->port_index = listener->port_index;
sp->fd_index = listener->fd_index + count - i;
- sp->is_sibling = 1;
- sp->sibling = listener->is_sibling ? listener->sibling : listener;
GPR_ASSERT(sp->emfd);
while (listener->server->tail->next != NULL) {
listener->server->tail = listener->server->tail->next;
@@ -685,7 +693,8 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
s->pollset_count = pollset_count;
sp = s->head;
while (sp != NULL) {
- if (s->so_reuseport && pollset_count > 1) {
+ if (s->so_reuseport && !grpc_is_unix_socket(&sp->addr.sockaddr) &&
+ pollset_count > 1) {
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"clone_port", clone_port(sp, (unsigned)(pollset_count - 1))));
for (i = 0; i < pollset_count; i++) {
@@ -741,4 +750,17 @@ void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
}
}
+void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx,
+ grpc_tcp_server *s) {
+ gpr_mu_lock(&s->mu);
+ /* shutdown all fd's */
+ if (s->active_ports) {
+ grpc_tcp_listener *sp;
+ for (sp = s->head; sp; sp = sp->next) {
+ grpc_fd_shutdown(exec_ctx, sp->emfd);
+ }
+ }
+ gpr_mu_unlock(&s->mu);
+}
+
#endif
diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c
index 7b0966704c..1b125e7005 100644
--- a/src/core/lib/iomgr/tcp_server_windows.c
+++ b/src/core/lib/iomgr/tcp_server_windows.c
@@ -540,4 +540,7 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
gpr_mu_unlock(&s->mu);
}
+void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx,
+ grpc_tcp_server *s) {}
+
#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c
index 1ebccf2ee2..48032412a2 100644
--- a/src/core/lib/iomgr/udp_server.c
+++ b/src/core/lib/iomgr/udp_server.c
@@ -60,6 +60,7 @@
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
+#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
@@ -128,7 +129,7 @@ grpc_udp_server *grpc_udp_server_create(void) {
}
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
- grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1, NULL);
+ grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL);
gpr_mu_destroy(&s->mu);
gpr_cv_destroy(&s->cv);
@@ -138,7 +139,7 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
}
static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server,
- bool success) {
+ grpc_error *error) {
grpc_udp_server *s = server;
gpr_mu_lock(&s->mu);
s->destroyed_ports++;
@@ -217,14 +218,23 @@ static int prepare_socket(int fd, const struct sockaddr *addr,
goto error;
}
- if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1)) {
- gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
- strerror(errno));
+ if (grpc_set_socket_nonblocking(fd, 1) != GRPC_ERROR_NONE) {
+ gpr_log(GPR_ERROR, "Unable to set nonblocking %d: %s", fd, strerror(errno));
+ goto error;
+ }
+ if (grpc_set_socket_cloexec(fd, 1) != GRPC_ERROR_NONE) {
+ gpr_log(GPR_ERROR, "Unable to set cloexec %d: %s", fd, strerror(errno));
+ goto error;
}
- if (grpc_set_socket_ip_pktinfo_if_possible(fd) &&
- addr->sa_family == AF_INET6) {
- grpc_set_socket_ipv6_recvpktinfo_if_possible(fd);
+ if (grpc_set_socket_ip_pktinfo_if_possible(fd) != GRPC_ERROR_NONE) {
+ gpr_log(GPR_ERROR, "Unable to set ip_pktinfo.");
+ goto error;
+ } else if (addr->sa_family == AF_INET6) {
+ if (grpc_set_socket_ipv6_recvpktinfo_if_possible(fd) != GRPC_ERROR_NONE) {
+ gpr_log(GPR_ERROR, "Unable to set ipv6_recvpktinfo.");
+ goto error;
+ }
}
GPR_ASSERT(addr_len < ~(socklen_t)0);
@@ -241,13 +251,13 @@ static int prepare_socket(int fd, const struct sockaddr *addr,
goto error;
}
- if (!grpc_set_socket_sndbuf(fd, buffer_size_bytes)) {
+ if (grpc_set_socket_sndbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) {
gpr_log(GPR_ERROR, "Failed to set send buffer size to %d bytes",
buffer_size_bytes);
goto error;
}
- if (!grpc_set_socket_rcvbuf(fd, buffer_size_bytes)) {
+ if (grpc_set_socket_rcvbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) {
gpr_log(GPR_ERROR, "Failed to set receive buffer size to %d bytes",
buffer_size_bytes);
goto error;
@@ -263,10 +273,10 @@ error:
}
/* event manager callback when reads are ready */
-static void on_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
server_port *sp = arg;
- if (!success) {
+ if (error != GRPC_ERROR_NONE) {
gpr_mu_lock(&sp->server->mu);
if (0 == --sp->server->active_ports) {
gpr_mu_unlock(&sp->server->mu);
@@ -369,7 +379,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
/* Try listening on IPv6 first. */
addr = (struct sockaddr *)&wild6;
addr_len = sizeof(wild6);
- fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode);
+ // TODO(rjshade): Test and propagate the returned grpc_error*:
+ grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd);
allocated_port1 =
add_socket_to_server(s, fd, addr, addr_len, read_cb, orphan_cb);
if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
@@ -384,7 +395,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
addr_len = sizeof(wild4);
}
- fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode);
+ // TODO(rjshade): Test and propagate the returned grpc_error*:
+ grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd);
if (fd < 0) {
gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
}
diff --git a/src/core/lib/json/json_reader.c b/src/core/lib/json/json_reader.c
index bc04bccc65..5b42ca53ff 100644
--- a/src/core/lib/json/json_reader.c
+++ b/src/core/lib/json/json_reader.c
@@ -1,6 +1,6 @@
/*
*
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -171,8 +171,9 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
switch (reader->state) {
case GRPC_JSON_STATE_OBJECT_KEY_STRING:
case GRPC_JSON_STATE_VALUE_STRING:
- if (reader->unicode_high_surrogate != 0)
+ if (reader->unicode_high_surrogate != 0) {
return GRPC_JSON_PARSE_ERROR;
+ }
json_reader_string_add_char(reader, c);
break;
@@ -289,8 +290,9 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
break;
case GRPC_JSON_STATE_OBJECT_KEY_STRING:
- if (reader->unicode_high_surrogate != 0)
+ if (reader->unicode_high_surrogate != 0) {
return GRPC_JSON_PARSE_ERROR;
+ }
if (c == '"') {
reader->state = GRPC_JSON_STATE_OBJECT_KEY_END;
json_reader_set_key(reader);
@@ -302,8 +304,9 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
break;
case GRPC_JSON_STATE_VALUE_STRING:
- if (reader->unicode_high_surrogate != 0)
+ if (reader->unicode_high_surrogate != 0) {
return GRPC_JSON_PARSE_ERROR;
+ }
if (c == '"') {
reader->state = GRPC_JSON_STATE_VALUE_END;
json_reader_set_string(reader);
@@ -383,8 +386,9 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
} else {
reader->state = GRPC_JSON_STATE_VALUE_STRING;
}
- if (reader->unicode_high_surrogate && c != 'u')
+ if (reader->unicode_high_surrogate && c != 'u') {
return GRPC_JSON_PARSE_ERROR;
+ }
switch (c) {
case '"':
case '/':
diff --git a/src/core/lib/security/context/security_context.h b/src/core/lib/security/context/security_context.h
index ef0c06b1fb..4e7666dfe3 100644
--- a/src/core/lib/security/context/security_context.h
+++ b/src/core/lib/security/context/security_context.h
@@ -37,6 +37,10 @@
#include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/security/credentials/credentials.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* --- grpc_auth_context ---
High level authentication context object. Can optionally be chained. */
@@ -111,4 +115,8 @@ grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg);
grpc_auth_context *grpc_find_auth_context_in_args(
const grpc_channel_args *args);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H */
diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c
index ed7929aa27..2a1bf4d4e3 100644
--- a/src/core/lib/security/transport/client_auth_filter.c
+++ b/src/core/lib/security/transport/client_auth_filter.c
@@ -267,10 +267,12 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
}
/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
call_data *calld = elem->call_data;
memset(calld, 0, sizeof(*calld));
+ return GRPC_ERROR_NONE;
}
static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
@@ -282,7 +284,8 @@ static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
/* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- const grpc_call_stats *stats, void *ignored) {
+ const grpc_call_final_info *final_info,
+ void *ignored) {
call_data *calld = elem->call_data;
grpc_call_credentials_unref(calld->creds);
if (calld->host != NULL) {
diff --git a/src/core/lib/security/transport/handshake.c b/src/core/lib/security/transport/handshake.c
index b374ca7633..fbeec312b6 100644
--- a/src/core/lib/security/transport/handshake.c
+++ b/src/core/lib/security/transport/handshake.c
@@ -325,8 +325,9 @@ static void on_timeout(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
void grpc_do_security_handshake(
grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
grpc_security_connector *connector, bool is_client_side,
- grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
- grpc_security_handshake_done_cb cb, void *user_data) {
+ grpc_endpoint *nonsecure_endpoint, gpr_slice_buffer *read_buffer,
+ gpr_timespec deadline, grpc_security_handshake_done_cb cb,
+ void *user_data) {
grpc_security_connector_handshake_list *handshake_node;
grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake));
memset(h, 0, sizeof(grpc_security_handshake));
@@ -346,6 +347,10 @@ void grpc_do_security_handshake(
gpr_slice_buffer_init(&h->left_overs);
gpr_slice_buffer_init(&h->outgoing);
gpr_slice_buffer_init(&h->incoming);
+ if (read_buffer != NULL) {
+ gpr_slice_buffer_move_into(read_buffer, &h->incoming);
+ gpr_free(read_buffer);
+ }
if (!is_client_side) {
grpc_server_security_connector *server_connector =
(grpc_server_security_connector *)connector;
@@ -357,8 +362,9 @@ void grpc_do_security_handshake(
gpr_mu_unlock(&server_connector->mu);
}
send_handshake_bytes_to_peer(exec_ctx, h);
- grpc_timer_init(exec_ctx, &h->timer, deadline, on_timeout, h,
- gpr_now(deadline.clock_type));
+ grpc_timer_init(exec_ctx, &h->timer,
+ gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
+ on_timeout, h, gpr_now(GPR_CLOCK_MONOTONIC));
}
void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/security/transport/handshake.h b/src/core/lib/security/transport/handshake.h
index c0906dd6af..53092f5421 100644
--- a/src/core/lib/security/transport/handshake.h
+++ b/src/core/lib/security/transport/handshake.h
@@ -37,12 +37,13 @@
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/security/transport/security_connector.h"
-/* Calls the callback upon completion. Takes owership of handshaker. */
+/* Calls the callback upon completion. Takes owership of handshaker and
+ * read_buffer. */
void grpc_do_security_handshake(
grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
grpc_security_connector *connector, bool is_client_side,
- grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
- grpc_security_handshake_done_cb cb, void *user_data);
+ grpc_endpoint *nonsecure_endpoint, gpr_slice_buffer *read_buffer,
+ gpr_timespec deadline, grpc_security_handshake_done_cb cb, void *user_data);
void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, void *handshake);
diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c
index bc50f9d1b0..0169ccd9ef 100644
--- a/src/core/lib/security/transport/secure_endpoint.c
+++ b/src/core/lib/security/transport/secure_endpoint.c
@@ -128,7 +128,7 @@ static void flush_read_staging_buffer(secure_endpoint *ep, uint8_t **cur,
static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep,
grpc_error *error) {
- if (false && grpc_trace_secure_endpoint) {
+ if (grpc_trace_secure_endpoint) {
size_t i;
for (i = 0; i < ep->read_buffer->count; i++) {
char *data = gpr_dump_slice(ep->read_buffer->slices[i],
@@ -256,7 +256,7 @@ static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
- if (false && grpc_trace_secure_endpoint) {
+ if (grpc_trace_secure_endpoint) {
for (i = 0; i < slices->count; i++) {
char *data =
gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
index f0ee6770e5..0eca46eb52 100644
--- a/src/core/lib/security/transport/security_connector.c
+++ b/src/core/lib/security/transport/security_connector.c
@@ -127,25 +127,29 @@ void grpc_server_security_connector_shutdown(
void grpc_channel_security_connector_do_handshake(
grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
- grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
- grpc_security_handshake_done_cb cb, void *user_data) {
+ grpc_endpoint *nonsecure_endpoint, gpr_slice_buffer *read_buffer,
+ gpr_timespec deadline, grpc_security_handshake_done_cb cb,
+ void *user_data) {
if (sc == NULL || nonsecure_endpoint == NULL) {
+ gpr_free(read_buffer);
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
} else {
- sc->do_handshake(exec_ctx, sc, nonsecure_endpoint, deadline, cb, user_data);
+ sc->do_handshake(exec_ctx, sc, nonsecure_endpoint, read_buffer, deadline,
+ cb, user_data);
}
}
void grpc_server_security_connector_do_handshake(
grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
- gpr_timespec deadline, grpc_security_handshake_done_cb cb,
- void *user_data) {
+ gpr_slice_buffer *read_buffer, gpr_timespec deadline,
+ grpc_security_handshake_done_cb cb, void *user_data) {
if (sc == NULL || nonsecure_endpoint == NULL) {
+ gpr_free(read_buffer);
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
} else {
- sc->do_handshake(exec_ctx, sc, acceptor, nonsecure_endpoint, deadline, cb,
- user_data);
+ sc->do_handshake(exec_ctx, sc, acceptor, nonsecure_endpoint, read_buffer,
+ deadline, cb, user_data);
}
}
@@ -312,23 +316,23 @@ static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
static void fake_channel_do_handshake(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc,
grpc_endpoint *nonsecure_endpoint,
+ gpr_slice_buffer *read_buffer,
gpr_timespec deadline,
grpc_security_handshake_done_cb cb,
void *user_data) {
grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(1), &sc->base,
- true, nonsecure_endpoint, deadline, cb, user_data);
+ true, nonsecure_endpoint, read_buffer, deadline,
+ cb, user_data);
}
-static void fake_server_do_handshake(grpc_exec_ctx *exec_ctx,
- grpc_server_security_connector *sc,
- grpc_tcp_server_acceptor *acceptor,
- grpc_endpoint *nonsecure_endpoint,
- gpr_timespec deadline,
- grpc_security_handshake_done_cb cb,
- void *user_data) {
+static void fake_server_do_handshake(
+ grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
+ grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
+ gpr_slice_buffer *read_buffer, gpr_timespec deadline,
+ grpc_security_handshake_done_cb cb, void *user_data) {
grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(0), &sc->base,
- false, nonsecure_endpoint, deadline, cb,
- user_data);
+ false, nonsecure_endpoint, read_buffer, deadline,
+ cb, user_data);
}
static grpc_security_connector_vtable fake_channel_vtable = {
@@ -418,6 +422,7 @@ static grpc_security_status ssl_create_handshaker(
static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc,
grpc_endpoint *nonsecure_endpoint,
+ gpr_slice_buffer *read_buffer,
gpr_timespec deadline,
grpc_security_handshake_done_cb cb,
void *user_data) {
@@ -430,30 +435,32 @@ static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx,
: c->target_name,
&handshaker);
if (status != GRPC_SECURITY_OK) {
+ gpr_free(read_buffer);
cb(exec_ctx, user_data, status, NULL, NULL);
} else {
grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
- nonsecure_endpoint, deadline, cb, user_data);
+ nonsecure_endpoint, read_buffer, deadline, cb,
+ user_data);
}
}
-static void ssl_server_do_handshake(grpc_exec_ctx *exec_ctx,
- grpc_server_security_connector *sc,
- grpc_tcp_server_acceptor *acceptor,
- grpc_endpoint *nonsecure_endpoint,
- gpr_timespec deadline,
- grpc_security_handshake_done_cb cb,
- void *user_data) {
+static void ssl_server_do_handshake(
+ grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
+ grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
+ gpr_slice_buffer *read_buffer, gpr_timespec deadline,
+ grpc_security_handshake_done_cb cb, void *user_data) {
grpc_ssl_server_security_connector *c =
(grpc_ssl_server_security_connector *)sc;
tsi_handshaker *handshaker;
grpc_security_status status =
ssl_create_handshaker(c->handshaker_factory, false, NULL, &handshaker);
if (status != GRPC_SECURITY_OK) {
+ gpr_free(read_buffer);
cb(exec_ctx, user_data, status, NULL, NULL);
} else {
grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, false,
- nonsecure_endpoint, deadline, cb, user_data);
+ nonsecure_endpoint, read_buffer, deadline, cb,
+ user_data);
}
}
diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h
index c2ddf5ee1e..0b5b44bf1a 100644
--- a/src/core/lib/security/transport/security_connector.h
+++ b/src/core/lib/security/transport/security_connector.h
@@ -143,7 +143,8 @@ struct grpc_channel_security_connector {
grpc_security_call_host_check_cb cb, void *user_data);
void (*do_handshake)(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc,
- grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
+ grpc_endpoint *nonsecure_endpoint,
+ gpr_slice_buffer *read_buffer, gpr_timespec deadline,
grpc_security_handshake_done_cb cb, void *user_data);
};
@@ -156,8 +157,8 @@ void grpc_channel_security_connector_check_call_host(
/* Handshake. */
void grpc_channel_security_connector_do_handshake(
grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector,
- grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
- grpc_security_handshake_done_cb cb, void *user_data);
+ grpc_endpoint *nonsecure_endpoint, gpr_slice_buffer *read_buffer,
+ gpr_timespec deadline, grpc_security_handshake_done_cb cb, void *user_data);
/* --- server_security_connector object. ---
@@ -174,14 +175,16 @@ struct grpc_server_security_connector {
void (*do_handshake)(grpc_exec_ctx *exec_ctx,
grpc_server_security_connector *sc,
grpc_tcp_server_acceptor *acceptor,
- grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
+ grpc_endpoint *nonsecure_endpoint,
+ gpr_slice_buffer *read_buffer, gpr_timespec deadline,
grpc_security_handshake_done_cb cb, void *user_data);
};
void grpc_server_security_connector_do_handshake(
grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
- gpr_timespec deadline, grpc_security_handshake_done_cb cb, void *user_data);
+ gpr_slice_buffer *read_buffer, gpr_timespec deadline,
+ grpc_security_handshake_done_cb cb, void *user_data);
void grpc_server_security_connector_shutdown(
grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector);
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c
index 12e789bde9..def16c8229 100644
--- a/src/core/lib/security/transport/server_auth_filter.c
+++ b/src/core/lib/security/transport/server_auth_filter.c
@@ -199,8 +199,9 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
}
/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
@@ -222,11 +223,14 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
args->context[GRPC_CONTEXT_SECURITY].value = server_ctx;
args->context[GRPC_CONTEXT_SECURITY].destroy =
grpc_server_security_context_destroy;
+
+ return GRPC_ERROR_NONE;
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- const grpc_call_stats *stats, void *ignored) {}
+ const grpc_call_final_info *final_info,
+ void *ignored) {}
/* Constructor for channel_data */
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/support/log.c b/src/core/lib/support/log.c
index bae0957df7..899f1218b6 100644
--- a/src/core/lib/support/log.c
+++ b/src/core/lib/support/log.c
@@ -79,17 +79,18 @@ void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print) {
void gpr_log_verbosity_init() {
char *verbosity = gpr_getenv("GRPC_VERBOSITY");
- if (verbosity == NULL) return;
- gpr_atm min_severity_to_print = GPR_LOG_VERBOSITY_UNSET;
- if (strcmp(verbosity, "DEBUG") == 0) {
- min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_DEBUG;
- } else if (strcmp(verbosity, "INFO") == 0) {
- min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_INFO;
- } else if (strcmp(verbosity, "ERROR") == 0) {
- min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_ERROR;
+ gpr_atm min_severity_to_print = GPR_LOG_SEVERITY_ERROR;
+ if (verbosity != NULL) {
+ if (strcmp(verbosity, "DEBUG") == 0) {
+ min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_DEBUG;
+ } else if (strcmp(verbosity, "INFO") == 0) {
+ min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_INFO;
+ } else if (strcmp(verbosity, "ERROR") == 0) {
+ min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_ERROR;
+ }
+ gpr_free(verbosity);
}
- gpr_free(verbosity);
if ((gpr_atm_no_barrier_load(&g_min_severity_to_print)) ==
GPR_LOG_VERBOSITY_UNSET) {
gpr_atm_no_barrier_store(&g_min_severity_to_print, min_severity_to_print);
diff --git a/src/core/lib/support/log_linux.c b/src/core/lib/support/log_linux.c
index 508fae4eec..299b377373 100644
--- a/src/core/lib/support/log_linux.c
+++ b/src/core/lib/support/log_linux.c
@@ -47,7 +47,6 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
-#include <linux/unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
diff --git a/src/core/lib/support/slice.c b/src/core/lib/support/slice.c
index b9a7c77bda..8a2c0a9086 100644
--- a/src/core/lib/support/slice.c
+++ b/src/core/lib/support/slice.c
@@ -94,14 +94,16 @@ static void new_slice_unref(void *p) {
}
}
-gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *)) {
+gpr_slice gpr_slice_new_with_user_data(void *p, size_t len,
+ void (*destroy)(void *),
+ void *user_data) {
gpr_slice slice;
new_slice_refcount *rc = gpr_malloc(sizeof(new_slice_refcount));
gpr_ref_init(&rc->refs, 1);
rc->rc.ref = new_slice_ref;
rc->rc.unref = new_slice_unref;
rc->user_destroy = destroy;
- rc->user_data = p;
+ rc->user_data = user_data;
slice.refcount = &rc->rc;
slice.data.refcounted.bytes = p;
@@ -109,6 +111,11 @@ gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *)) {
return slice;
}
+gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *)) {
+ /* Pass "p" to *destroy when the slice is no longer needed. */
+ return gpr_slice_new_with_user_data(p, len, destroy, p);
+}
+
/* gpr_slice_new_with_len support structures - we create a refcount object
extended with the user provided data pointer & destroy function */
typedef struct new_with_len_slice_refcount {
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index fc9df76dc1..772681109a 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -154,8 +154,9 @@ struct grpc_call {
/* Received call statuses from various sources */
received_status status[STATUS_SOURCE_COUNT];
- /* Call stats: only valid after trailing metadata received */
- grpc_call_stats stats;
+ /* Call data useful used for reporting. Only valid after the call has
+ * completed */
+ grpc_call_final_info final_info;
/* Compression algorithm for *incoming* data */
grpc_compression_algorithm incoming_compression_algorithm;
@@ -263,9 +264,19 @@ grpc_call *grpc_call_create(
gpr_convert_clock_type(send_deadline, GPR_CLOCK_MONOTONIC);
GRPC_CHANNEL_INTERNAL_REF(channel, "call");
/* initial refcount dropped by grpc_call_destroy */
- grpc_call_stack_init(&exec_ctx, channel_stack, 1, destroy_call, call,
- call->context, server_transport_data,
- CALL_STACK_FROM_CALL(call));
+ grpc_error *error = grpc_call_stack_init(
+ &exec_ctx, channel_stack, 1, destroy_call, call, call->context,
+ server_transport_data, CALL_STACK_FROM_CALL(call));
+ if (error != GRPC_ERROR_NONE) {
+ intptr_t status;
+ if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &status))
+ status = GRPC_STATUS_UNKNOWN;
+ const char *error_str =
+ grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION);
+ close_with_status(&exec_ctx, call, (grpc_status_code)status,
+ error_str == NULL ? "unknown error" : error_str);
+ GRPC_ERROR_UNREF(error);
+ }
if (cq != NULL) {
GPR_ASSERT(
pollset_set_alternative == NULL &&
@@ -361,6 +372,25 @@ void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) {
GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON);
}
+static void get_final_status(grpc_call *call,
+ void (*set_value)(grpc_status_code code,
+ void *user_data),
+ void *set_value_user_data) {
+ int i;
+ for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+ if (call->status[i].is_set) {
+ set_value(call->status[i].code, set_value_user_data);
+ return;
+ }
+ }
+ if (call->is_client) {
+ set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
+ } else {
+ set_value(GRPC_STATUS_OK, set_value_user_data);
+ }
+}
+
+static void set_status_value_directly(grpc_status_code status, void *dest);
static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
grpc_error *error) {
size_t i;
@@ -392,7 +422,11 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
GRPC_CQ_INTERNAL_UNREF(c->cq, "bind");
}
grpc_channel *channel = c->channel;
- grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->stats, c);
+
+ get_final_status(call, set_status_value_directly,
+ &c->final_info.final_status);
+
+ grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, c);
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call");
GPR_TIMER_END("destroy_call", 0);
}
@@ -414,24 +448,6 @@ static void set_status_details(grpc_call *call, status_source source,
}
}
-static void get_final_status(grpc_call *call,
- void (*set_value)(grpc_status_code code,
- void *user_data),
- void *set_value_user_data) {
- int i;
- for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- if (call->status[i].is_set) {
- set_value(call->status[i].code, set_value_user_data);
- return;
- }
- }
- if (call->is_client) {
- set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
- } else {
- set_value(GRPC_STATUS_OK, set_value_user_data);
- }
-}
-
static void set_status_from_error(grpc_call *call, status_source source,
grpc_error *error) {
intptr_t status;
@@ -1361,6 +1377,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
int num_completion_callbacks_needed = 1;
grpc_call_error error = GRPC_CALL_OK;
+ // sent_initial_metadata guards against variable reuse.
+ grpc_metadata compression_md;
+
GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
@@ -1406,8 +1425,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
goto done_with_error;
}
/* process compression level */
- grpc_metadata compression_md;
- memset(&compression_md, 0, sizeof(grpc_metadata));
+ memset(&compression_md, 0, sizeof(compression_md));
size_t additional_metadata_count = 0;
grpc_compression_level effective_compression_level;
bool level_set = false;
@@ -1608,7 +1626,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
bctl->recv_final_op = 1;
stream_op.recv_trailing_metadata =
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
- stream_op.collect_stats = &call->stats.transport_stream_stats;
+ stream_op.collect_stats =
+ &call->final_info.stats.transport_stream_stats;
break;
case GRPC_OP_RECV_CLOSE_ON_SERVER:
/* Flag validation: currently allow no flags */
@@ -1630,7 +1649,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
bctl->recv_final_op = 1;
stream_op.recv_trailing_metadata =
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
- stream_op.collect_stats = &call->stats.transport_stream_stats;
+ stream_op.collect_stats =
+ &call->final_info.stats.transport_stream_stats;
break;
}
}
diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h
index 7eff7b8883..4c62974346 100644
--- a/src/core/lib/surface/channel.h
+++ b/src/core/lib/surface/channel.h
@@ -42,6 +42,14 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
grpc_channel_stack_type channel_stack_type,
grpc_transport *optional_transport);
+/** Create a call given a grpc_channel, in order to call \a method.
+ Progress is tied to activity on \a pollset_set. The returned call object is
+ meant to be used with \a grpc_call_start_batch_and_execute, which relies on
+ callbacks to signal completions. \a method and \a host need
+ only live through the invocation of this function. If \a parent_call is
+ non-NULL, it must be a server-side call. It will be used to propagate
+ properties from the server call to this new client call, depending on the
+ value of \a propagation_mask (see propagation_bits.h for possible values) */
grpc_call *grpc_channel_create_pollset_set_call(
grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
grpc_pollset_set *pollset_set, const char *method, const char *host,
diff --git a/src/core/lib/surface/channel_init.h b/src/core/lib/surface/channel_init.h
index 3a18a61ddb..b53f2aefb9 100644
--- a/src/core/lib/surface/channel_init.h
+++ b/src/core/lib/surface/channel_init.h
@@ -40,6 +40,10 @@
#define GRPC_CHANNEL_INIT_BUILTIN_PRIORITY 10000
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/// This module provides a way for plugins (and the grpc core library itself)
/// to register mutators for channel stacks.
/// It also provides a universal entry path to run those mutators to build
@@ -84,4 +88,8 @@ bool grpc_channel_init_create_stack(grpc_exec_ctx *exec_ctx,
grpc_channel_stack_builder *builder,
grpc_channel_stack_type type);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_INIT_H */
diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c
index 5ea4cba5d1..19b78369dd 100644
--- a/src/core/lib/surface/lame_client.c
+++ b/src/core/lib/surface/lame_client.c
@@ -107,11 +107,14 @@ static void lame_start_transport_op(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_UNREF(op->disconnect_with_error);
}
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_call_element_args *args) {}
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
+ return GRPC_ERROR_NONE;
+}
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- const grpc_call_stats *stats,
+ const grpc_call_final_info *final_info,
void *and_free_memory) {
gpr_free(and_free_memory);
}
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index 2f108af48a..64afcecc07 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -272,7 +272,7 @@ static void shutdown_cleanup(grpc_exec_ctx *exec_ctx, void *arg,
}
static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
- int send_goaway, grpc_error *send_disconnect) {
+ bool send_goaway, grpc_error *send_disconnect) {
grpc_transport_op op;
struct shutdown_cleanup_args *sc;
grpc_channel_element *elem;
@@ -293,7 +293,7 @@ static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx,
channel_broadcaster *cb,
- int send_goaway,
+ bool send_goaway,
grpc_error *force_disconnect) {
size_t i;
@@ -856,8 +856,9 @@ static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd,
}
}
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
memset(calld, 0, sizeof(call_data));
@@ -869,10 +870,12 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
server_on_recv_initial_metadata, elem);
server_ref(chand->server);
+ return GRPC_ERROR_NONE;
}
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- const grpc_call_stats *stats, void *ignored) {
+ const grpc_call_final_info *final_info,
+ void *ignored) {
channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
@@ -1249,7 +1252,8 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
l->destroy(&exec_ctx, server, l->arg, &l->destroy_done);
}
- channel_broadcaster_shutdown(&exec_ctx, &broadcaster, 1, 0);
+ channel_broadcaster_shutdown(&exec_ctx, &broadcaster, true /* send_goaway */,
+ GRPC_ERROR_NONE);
done:
grpc_exec_ctx_finish(&exec_ctx);
@@ -1265,7 +1269,7 @@ void grpc_server_cancel_all_calls(grpc_server *server) {
channel_broadcaster_init(server, &broadcaster);
gpr_mu_unlock(&server->mu_global);
- channel_broadcaster_shutdown(&exec_ctx, &broadcaster, 0,
+ channel_broadcaster_shutdown(&exec_ctx, &broadcaster, false /* send_goaway */,
GRPC_ERROR_CREATE("Cancelling all calls"));
grpc_exec_ctx_finish(&exec_ctx);
}
diff --git a/src/core/lib/transport/byte_stream.h b/src/core/lib/transport/byte_stream.h
index 95519a9eaf..e64dce6283 100644
--- a/src/core/lib/transport/byte_stream.h
+++ b/src/core/lib/transport/byte_stream.h
@@ -59,13 +59,9 @@ struct grpc_byte_stream {
* on_complete will not be called), 0 if the bytes will be available
* asynchronously.
*
- * on entry, *remaining can be set as a hint as to the maximum number
+ * max_size_hint can be set as a hint as to the maximum number
* of bytes that would be acceptable to read.
*
- * fills *buffer, *length, *remaining with the bytes, length of bytes
- * and length of data remaining to be read before either returning 1
- * or calling on_complete.
- *
* once a slice is returned into *slice, it is owned by the caller.
*/
int grpc_byte_stream_next(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h
index 6d82f4d681..2b0921c8d7 100644
--- a/src/core/lib/transport/metadata.h
+++ b/src/core/lib/transport/metadata.h
@@ -37,6 +37,10 @@
#include <grpc/support/slice.h>
#include <grpc/support/useful.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* This file provides a mechanism for tracking metadata through the grpc stack.
It's not intended for consumption outside of the library.
@@ -164,4 +168,8 @@ void grpc_mdctx_global_shutdown(void);
extern gpr_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(
gpr_slice input);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_H */
diff --git a/src/core/lib/transport/metadata_batch.c b/src/core/lib/transport/metadata_batch.c
index e4398abeb7..84b5a74d51 100644
--- a/src/core/lib/transport/metadata_batch.c
+++ b/src/core/lib/transport/metadata_batch.c
@@ -33,6 +33,7 @@
#include "src/core/lib/transport/metadata_batch.h"
+#include <stdbool.h>
#include <string.h>
#include <grpc/support/alloc.h>
@@ -187,7 +188,7 @@ void grpc_metadata_batch_clear(grpc_metadata_batch *batch) {
grpc_metadata_batch_filter(batch, no_metadata_for_you, NULL);
}
-int grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) {
+bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) {
return batch->list.head == NULL &&
gpr_time_cmp(gpr_inf_future(batch->deadline.clock_type),
batch->deadline) == 0;
diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h
index 7af823f7ca..0424b4db98 100644
--- a/src/core/lib/transport/metadata_batch.h
+++ b/src/core/lib/transport/metadata_batch.h
@@ -34,12 +34,18 @@
#ifndef GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
#define GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
+#include <stdbool.h>
+
#include <grpc/grpc.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/slice.h>
#include <grpc/support/time.h>
#include "src/core/lib/transport/metadata.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef struct grpc_linked_mdelem {
grpc_mdelem *md;
struct grpc_linked_mdelem *next;
@@ -64,7 +70,7 @@ typedef struct grpc_metadata_batch {
void grpc_metadata_batch_init(grpc_metadata_batch *batch);
void grpc_metadata_batch_destroy(grpc_metadata_batch *batch);
void grpc_metadata_batch_clear(grpc_metadata_batch *batch);
-int grpc_metadata_batch_is_empty(grpc_metadata_batch *batch);
+bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch);
/* Returns the transport size of the batch. */
size_t grpc_metadata_batch_size(grpc_metadata_batch *batch);
@@ -125,4 +131,8 @@ void grpc_metadata_batch_assert_ok(grpc_metadata_batch *comd);
} while (0)
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H */
diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c
index c5f16e530d..8f3e5b5b40 100644
--- a/src/core/lib/transport/static_metadata.c
+++ b/src/core/lib/transport/static_metadata.c
@@ -45,21 +45,21 @@ grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 4, 8, 6, 2, 4, 8, 6, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 4, 8, 6, 2, 4, 8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] =
- {11, 35, 10, 35, 12, 35, 12, 49, 13, 35, 14, 35, 15, 35, 16, 35, 17, 35,
- 19, 35, 20, 35, 21, 35, 24, 35, 25, 35, 26, 35, 27, 35, 28, 35, 29, 35,
- 30, 18, 30, 35, 31, 35, 32, 35, 36, 35, 37, 35, 38, 35, 39, 35, 42, 33,
- 42, 34, 42, 48, 42, 53, 42, 54, 42, 55, 42, 56, 43, 33, 43, 48, 43, 53,
- 46, 0, 46, 1, 46, 2, 50, 35, 57, 35, 58, 35, 59, 35, 60, 35, 61, 35,
- 62, 35, 63, 35, 64, 35, 65, 35, 66, 35, 67, 40, 67, 69, 67, 72, 68, 80,
- 68, 81, 70, 35, 71, 35, 73, 35, 74, 35, 75, 35, 76, 35, 77, 41, 77, 51,
- 77, 52, 78, 35, 79, 35, 82, 3, 82, 4, 82, 5, 82, 6, 82, 7, 82, 8,
- 82, 9, 83, 35, 84, 85, 86, 35, 87, 35, 88, 35, 89, 35, 90, 35};
+ {11, 33, 10, 33, 12, 33, 12, 49, 13, 33, 14, 33, 15, 33, 16, 33, 17, 33,
+ 19, 33, 20, 33, 21, 33, 22, 33, 23, 33, 24, 33, 25, 33, 26, 33, 27, 33,
+ 28, 18, 28, 33, 29, 33, 30, 33, 34, 33, 35, 33, 36, 33, 37, 33, 40, 31,
+ 40, 32, 40, 48, 40, 53, 40, 54, 40, 55, 40, 56, 42, 31, 42, 48, 42, 53,
+ 45, 0, 45, 1, 45, 2, 50, 33, 57, 33, 58, 33, 59, 33, 60, 33, 61, 33,
+ 62, 33, 63, 33, 64, 33, 65, 33, 66, 33, 67, 33, 68, 38, 68, 70, 68, 73,
+ 69, 81, 69, 82, 71, 33, 72, 33, 74, 33, 75, 33, 76, 33, 77, 33, 78, 39,
+ 78, 51, 78, 52, 79, 33, 80, 33, 83, 3, 83, 4, 83, 5, 83, 6, 83, 7,
+ 83, 8, 83, 9, 84, 33, 85, 86, 87, 33, 88, 33, 89, 33, 90, 33, 91, 33};
const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = {
"0",
@@ -84,8 +84,6 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = {
":authority",
"authorization",
"cache-control",
- "census-bin",
- "census-binary-bin",
"content-disposition",
"content-encoding",
"content-language",
@@ -105,11 +103,13 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = {
"GET",
"grpc",
"grpc-accept-encoding",
+ "grpc-census-bin",
"grpc-encoding",
"grpc-internal-encoding-request",
"grpc-message",
"grpc-status",
"grpc-timeout",
+ "grpc-tracing-bin",
"gzip",
"gzip, deflate",
"host",
@@ -126,7 +126,8 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = {
"if-unmodified-since",
"last-modified",
"link",
- "load-reporting",
+ "load-reporting-initial",
+ "load-reporting-trailing",
"location",
"max-forwards",
":method",
diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h
index 5ff0d2f3bc..b51bacac50 100644
--- a/src/core/lib/transport/static_metadata.h
+++ b/src/core/lib/transport/static_metadata.h
@@ -44,7 +44,7 @@
#include "src/core/lib/transport/metadata.h"
-#define GRPC_STATIC_MDSTR_COUNT 91
+#define GRPC_STATIC_MDSTR_COUNT 92
extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
/* "0" */
#define GRPC_MDSTR_0 (&grpc_static_mdstr_table[0])
@@ -90,58 +90,58 @@ extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
#define GRPC_MDSTR_AUTHORIZATION (&grpc_static_mdstr_table[20])
/* "cache-control" */
#define GRPC_MDSTR_CACHE_CONTROL (&grpc_static_mdstr_table[21])
-/* "census-bin" */
-#define GRPC_MDSTR_CENSUS_BIN (&grpc_static_mdstr_table[22])
-/* "census-binary-bin" */
-#define GRPC_MDSTR_CENSUS_BINARY_BIN (&grpc_static_mdstr_table[23])
/* "content-disposition" */
-#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[24])
+#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[22])
/* "content-encoding" */
-#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[25])
+#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[23])
/* "content-language" */
-#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[26])
+#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[24])
/* "content-length" */
-#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[27])
+#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[25])
/* "content-location" */
-#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[28])
+#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[26])
/* "content-range" */
-#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[29])
+#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[27])
/* "content-type" */
-#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[30])
+#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[28])
/* "cookie" */
-#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[31])
+#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[29])
/* "date" */
-#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[32])
+#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[30])
/* "deflate" */
-#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[33])
+#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[31])
/* "deflate,gzip" */
-#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_mdstr_table[34])
+#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_mdstr_table[32])
/* "" */
-#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[35])
+#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[33])
/* "etag" */
-#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[36])
+#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[34])
/* "expect" */
-#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[37])
+#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[35])
/* "expires" */
-#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[38])
+#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[36])
/* "from" */
-#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[39])
+#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[37])
/* "GET" */
-#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[40])
+#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[38])
/* "grpc" */
-#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[41])
+#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[39])
/* "grpc-accept-encoding" */
-#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[42])
+#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[40])
+/* "grpc-census-bin" */
+#define GRPC_MDSTR_GRPC_CENSUS_BIN (&grpc_static_mdstr_table[41])
/* "grpc-encoding" */
-#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[43])
+#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[42])
/* "grpc-internal-encoding-request" */
-#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[44])
+#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[43])
/* "grpc-message" */
-#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[45])
+#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[44])
/* "grpc-status" */
-#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[46])
+#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[45])
/* "grpc-timeout" */
-#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[47])
+#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[46])
+/* "grpc-tracing-bin" */
+#define GRPC_MDSTR_GRPC_TRACING_BIN (&grpc_static_mdstr_table[47])
/* "gzip" */
#define GRPC_MDSTR_GZIP (&grpc_static_mdstr_table[48])
/* "gzip, deflate" */
@@ -175,62 +175,64 @@ extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
#define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_mdstr_table[62])
/* "link" */
#define GRPC_MDSTR_LINK (&grpc_static_mdstr_table[63])
-/* "load-reporting" */
-#define GRPC_MDSTR_LOAD_REPORTING (&grpc_static_mdstr_table[64])
+/* "load-reporting-initial" */
+#define GRPC_MDSTR_LOAD_REPORTING_INITIAL (&grpc_static_mdstr_table[64])
+/* "load-reporting-trailing" */
+#define GRPC_MDSTR_LOAD_REPORTING_TRAILING (&grpc_static_mdstr_table[65])
/* "location" */
-#define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[65])
+#define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[66])
/* "max-forwards" */
-#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_mdstr_table[66])
+#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_mdstr_table[67])
/* ":method" */
-#define GRPC_MDSTR_METHOD (&grpc_static_mdstr_table[67])
+#define GRPC_MDSTR_METHOD (&grpc_static_mdstr_table[68])
/* ":path" */
-#define GRPC_MDSTR_PATH (&grpc_static_mdstr_table[68])
+#define GRPC_MDSTR_PATH (&grpc_static_mdstr_table[69])
/* "POST" */
-#define GRPC_MDSTR_POST (&grpc_static_mdstr_table[69])
+#define GRPC_MDSTR_POST (&grpc_static_mdstr_table[70])
/* "proxy-authenticate" */
-#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[70])
+#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[71])
/* "proxy-authorization" */
-#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[71])
+#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[72])
/* "PUT" */
-#define GRPC_MDSTR_PUT (&grpc_static_mdstr_table[72])
+#define GRPC_MDSTR_PUT (&grpc_static_mdstr_table[73])
/* "range" */
-#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[73])
+#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[74])
/* "referer" */
-#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[74])
+#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[75])
/* "refresh" */
-#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[75])
+#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[76])
/* "retry-after" */
-#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[76])
+#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[77])
/* ":scheme" */
-#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[77])
+#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[78])
/* "server" */
-#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[78])
+#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[79])
/* "set-cookie" */
-#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[79])
+#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[80])
/* "/" */
-#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[80])
+#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[81])
/* "/index.html" */
-#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[81])
+#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[82])
/* ":status" */
-#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[82])
+#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[83])
/* "strict-transport-security" */
-#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[83])
+#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[84])
/* "te" */
-#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[84])
+#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[85])
/* "trailers" */
-#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[85])
+#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[86])
/* "transfer-encoding" */
-#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[86])
+#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[87])
/* "user-agent" */
-#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[87])
+#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[88])
/* "vary" */
-#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[88])
+#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[89])
/* "via" */
-#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[89])
+#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[90])
/* "www-authenticate" */
-#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[90])
+#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[91])
-#define GRPC_STATIC_MDELEM_COUNT 80
+#define GRPC_STATIC_MDELEM_COUNT 81
extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
/* "accept-charset": "" */
@@ -335,73 +337,76 @@ extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
#define GRPC_MDELEM_LAST_MODIFIED_EMPTY (&grpc_static_mdelem_table[45])
/* "link": "" */
#define GRPC_MDELEM_LINK_EMPTY (&grpc_static_mdelem_table[46])
-/* "load-reporting": "" */
-#define GRPC_MDELEM_LOAD_REPORTING_EMPTY (&grpc_static_mdelem_table[47])
+/* "load-reporting-initial": "" */
+#define GRPC_MDELEM_LOAD_REPORTING_INITIAL_EMPTY (&grpc_static_mdelem_table[47])
+/* "load-reporting-trailing": "" */
+#define GRPC_MDELEM_LOAD_REPORTING_TRAILING_EMPTY \
+ (&grpc_static_mdelem_table[48])
/* "location": "" */
-#define GRPC_MDELEM_LOCATION_EMPTY (&grpc_static_mdelem_table[48])
+#define GRPC_MDELEM_LOCATION_EMPTY (&grpc_static_mdelem_table[49])
/* "max-forwards": "" */
-#define GRPC_MDELEM_MAX_FORWARDS_EMPTY (&grpc_static_mdelem_table[49])
+#define GRPC_MDELEM_MAX_FORWARDS_EMPTY (&grpc_static_mdelem_table[50])
/* ":method": "GET" */
-#define GRPC_MDELEM_METHOD_GET (&grpc_static_mdelem_table[50])
+#define GRPC_MDELEM_METHOD_GET (&grpc_static_mdelem_table[51])
/* ":method": "POST" */
-#define GRPC_MDELEM_METHOD_POST (&grpc_static_mdelem_table[51])
+#define GRPC_MDELEM_METHOD_POST (&grpc_static_mdelem_table[52])
/* ":method": "PUT" */
-#define GRPC_MDELEM_METHOD_PUT (&grpc_static_mdelem_table[52])
+#define GRPC_MDELEM_METHOD_PUT (&grpc_static_mdelem_table[53])
/* ":path": "/" */
-#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[53])
+#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[54])
/* ":path": "/index.html" */
-#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[54])
+#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[55])
/* "proxy-authenticate": "" */
-#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[55])
+#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[56])
/* "proxy-authorization": "" */
-#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[56])
+#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[57])
/* "range": "" */
-#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[57])
+#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[58])
/* "referer": "" */
-#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[58])
+#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[59])
/* "refresh": "" */
-#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[59])
+#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[60])
/* "retry-after": "" */
-#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[60])
+#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[61])
/* ":scheme": "grpc" */
-#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[61])
+#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[62])
/* ":scheme": "http" */
-#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[62])
+#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[63])
/* ":scheme": "https" */
-#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[63])
+#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[64])
/* "server": "" */
-#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[64])
+#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[65])
/* "set-cookie": "" */
-#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[65])
+#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[66])
/* ":status": "200" */
-#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[66])
+#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[67])
/* ":status": "204" */
-#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[67])
+#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[68])
/* ":status": "206" */
-#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[68])
+#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[69])
/* ":status": "304" */
-#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[69])
+#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[70])
/* ":status": "400" */
-#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[70])
+#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[71])
/* ":status": "404" */
-#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[71])
+#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[72])
/* ":status": "500" */
-#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[72])
+#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[73])
/* "strict-transport-security": "" */
#define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \
- (&grpc_static_mdelem_table[73])
+ (&grpc_static_mdelem_table[74])
/* "te": "trailers" */
-#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[74])
+#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[75])
/* "transfer-encoding": "" */
-#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[75])
+#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[76])
/* "user-agent": "" */
-#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[76])
+#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[77])
/* "vary": "" */
-#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[77])
+#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[78])
/* "via": "" */
-#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[78])
+#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[79])
/* "www-authenticate": "" */
-#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[79])
+#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[80])
extern const uint8_t
grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2];
diff --git a/src/core/ext/transport/chttp2/transport/timeout_encoding.c b/src/core/lib/transport/timeout_encoding.c
index b7f7912493..b58ebbd0a8 100644
--- a/src/core/ext/transport/chttp2/transport/timeout_encoding.c
+++ b/src/core/lib/transport/timeout_encoding.c
@@ -31,7 +31,7 @@
*
*/
-#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
+#include "src/core/lib/transport/timeout_encoding.h"
#include <stdio.h>
#include <string.h>
@@ -117,7 +117,7 @@ static void enc_micros(char *buffer, int64_t x) {
}
}
-void grpc_chttp2_encode_timeout(gpr_timespec timeout, char *buffer) {
+void grpc_http2_encode_timeout(gpr_timespec timeout, char *buffer) {
if (timeout.tv_sec < 0) {
enc_tiny(buffer);
} else if (timeout.tv_sec == 0) {
@@ -136,7 +136,7 @@ static int is_all_whitespace(const char *p) {
return *p == 0;
}
-int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout) {
+int grpc_http2_decode_timeout(const char *buffer, gpr_timespec *timeout) {
int32_t x = 0;
const uint8_t *p = (const uint8_t *)buffer;
int have_digit = 0;
diff --git a/src/core/ext/transport/chttp2/transport/timeout_encoding.h b/src/core/lib/transport/timeout_encoding.h
index df2324c791..92f02f6ecd 100644
--- a/src/core/ext/transport/chttp2/transport/timeout_encoding.h
+++ b/src/core/lib/transport/timeout_encoding.h
@@ -31,17 +31,17 @@
*
*/
-#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_TIMEOUT_ENCODING_H
-#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_TIMEOUT_ENCODING_H
+#ifndef GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H
+#define GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H
#include <grpc/support/time.h>
#include "src/core/lib/support/string.h"
-#define GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE (GPR_LTOA_MIN_BUFSIZE + 1)
+#define GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE (GPR_LTOA_MIN_BUFSIZE + 1)
-/* Encode/decode timeouts to the GRPC over HTTP2 format;
+/* Encode/decode timeouts to the GRPC over HTTP/2 format;
encoding may round up arbitrarily */
-void grpc_chttp2_encode_timeout(gpr_timespec timeout, char *buffer);
-int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout);
+void grpc_http2_encode_timeout(gpr_timespec timeout, char *buffer);
+int grpc_http2_decode_timeout(const char *buffer, gpr_timespec *timeout);
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_TIMEOUT_ENCODING_H */
+#endif /* GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H */
diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h
index 08c0a237c9..1705e6e582 100644
--- a/src/core/lib/transport/transport.h
+++ b/src/core/lib/transport/transport.h
@@ -43,6 +43,10 @@
#include "src/core/lib/transport/byte_stream.h"
#include "src/core/lib/transport/metadata_batch.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* forward declarations */
typedef struct grpc_transport grpc_transport;
@@ -138,7 +142,7 @@ typedef struct grpc_transport_stream_op {
/** If != GRPC_ERROR_NONE, cancel this stream */
grpc_error *cancel_error;
- /** If != GRPC_ERROR, send grpc-status, grpc-message, and close this
+ /** If != GRPC_ERROR_NONE, send grpc-status, grpc-message, and close this
stream for both reading and writing */
grpc_error *close_error;
@@ -158,7 +162,7 @@ typedef struct grpc_transport_op {
/** 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;
+ bool send_goaway;
/** what should the goaway contain? */
grpc_status_code goaway_status;
gpr_slice *goaway_message;
@@ -268,4 +272,8 @@ void grpc_transport_destroy(grpc_exec_ctx *exec_ctx, grpc_transport *transport);
char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx,
grpc_transport *transport);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_TRANSPORT_TRANSPORT_H */
diff --git a/src/core/plugin_registry/grpc_plugin_registry.c b/src/core/plugin_registry/grpc_plugin_registry.c
index 905cd59e23..7a7a9ce477 100644
--- a/src/core/plugin_registry/grpc_plugin_registry.c
+++ b/src/core/plugin_registry/grpc_plugin_registry.c
@@ -37,6 +37,8 @@ extern void grpc_chttp2_plugin_init(void);
extern void grpc_chttp2_plugin_shutdown(void);
extern void grpc_client_config_init(void);
extern void grpc_client_config_shutdown(void);
+extern void grpc_lb_policy_grpclb_init(void);
+extern void grpc_lb_policy_grpclb_shutdown(void);
extern void grpc_lb_policy_pick_first_init(void);
extern void grpc_lb_policy_pick_first_shutdown(void);
extern void grpc_lb_policy_round_robin_init(void);
@@ -55,6 +57,8 @@ void grpc_register_built_in_plugins(void) {
grpc_chttp2_plugin_shutdown);
grpc_register_plugin(grpc_client_config_init,
grpc_client_config_shutdown);
+ grpc_register_plugin(grpc_lb_policy_grpclb_init,
+ grpc_lb_policy_grpclb_shutdown);
grpc_register_plugin(grpc_lb_policy_pick_first_init,
grpc_lb_policy_pick_first_shutdown);
grpc_register_plugin(grpc_lb_policy_round_robin_init,
diff --git a/src/core/plugin_registry/grpc_unsecure_plugin_registry.c b/src/core/plugin_registry/grpc_unsecure_plugin_registry.c
index 7995078725..ad4ddf0ff4 100644
--- a/src/core/plugin_registry/grpc_unsecure_plugin_registry.c
+++ b/src/core/plugin_registry/grpc_unsecure_plugin_registry.c
@@ -43,6 +43,8 @@ extern void grpc_resolver_sockaddr_init(void);
extern void grpc_resolver_sockaddr_shutdown(void);
extern void grpc_load_reporting_plugin_init(void);
extern void grpc_load_reporting_plugin_shutdown(void);
+extern void grpc_lb_policy_grpclb_init(void);
+extern void grpc_lb_policy_grpclb_shutdown(void);
extern void grpc_lb_policy_pick_first_init(void);
extern void grpc_lb_policy_pick_first_shutdown(void);
extern void grpc_lb_policy_round_robin_init(void);
@@ -61,6 +63,8 @@ void grpc_register_built_in_plugins(void) {
grpc_resolver_sockaddr_shutdown);
grpc_register_plugin(grpc_load_reporting_plugin_init,
grpc_load_reporting_plugin_shutdown);
+ grpc_register_plugin(grpc_lb_policy_grpclb_init,
+ grpc_lb_policy_grpclb_shutdown);
grpc_register_plugin(grpc_lb_policy_pick_first_init,
grpc_lb_policy_pick_first_shutdown);
grpc_register_plugin(grpc_lb_policy_round_robin_init,
diff --git a/src/cpp/common/channel_filter.cc b/src/cpp/common/channel_filter.cc
new file mode 100644
index 0000000000..25cd49cb7c
--- /dev/null
+++ b/src/cpp/common/channel_filter.cc
@@ -0,0 +1,112 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <string.h>
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/cpp/common/channel_filter.h"
+
+namespace grpc {
+
+// MetadataBatch
+
+grpc_linked_mdelem *MetadataBatch::AddMetadata(const string &key,
+ const string &value) {
+ grpc_linked_mdelem *storage = new grpc_linked_mdelem;
+ memset(storage, 0, sizeof(grpc_linked_mdelem));
+ storage->md = grpc_mdelem_from_strings(key.c_str(), value.c_str());
+ grpc_metadata_batch_link_head(batch_, storage);
+ return storage;
+}
+
+// ChannelData
+
+void ChannelData::StartTransportOp(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem,
+ TransportOp *op) {
+ grpc_channel_next_op(exec_ctx, elem, op->op());
+}
+
+// CallData
+
+void CallData::StartTransportStreamOp(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ TransportStreamOp *op) {
+ grpc_call_next_op(exec_ctx, elem, op->op());
+}
+
+void CallData::SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_polling_entity *pollent) {
+ grpc_call_stack_ignore_set_pollset_or_pollset_set(exec_ctx, elem, pollent);
+}
+
+char *CallData::GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
+ return grpc_call_next_get_peer(exec_ctx, elem);
+}
+
+// internal code used by RegisterChannelFilter()
+
+namespace internal {
+
+// Note: Implicitly initialized to nullptr due to static lifetime.
+std::vector<FilterRecord> *channel_filters;
+
+namespace {
+
+bool MaybeAddFilter(grpc_channel_stack_builder *builder, void *arg) {
+ const FilterRecord &filter = *(FilterRecord *)arg;
+ if (filter.include_filter) {
+ const grpc_channel_args *args =
+ grpc_channel_stack_builder_get_channel_arguments(builder);
+ if (!filter.include_filter(*args)) return true;
+ }
+ return grpc_channel_stack_builder_prepend_filter(builder, &filter.filter,
+ nullptr, nullptr);
+}
+
+} // namespace
+
+void ChannelFilterPluginInit() {
+ for (size_t i = 0; i < channel_filters->size(); ++i) {
+ FilterRecord &filter = (*channel_filters)[i];
+ grpc_channel_init_register_stage(filter.stack_type, filter.priority,
+ MaybeAddFilter, (void *)&filter);
+ }
+}
+
+void ChannelFilterPluginShutdown() {}
+
+} // namespace internal
+
+} // namespace grpc
diff --git a/src/cpp/common/channel_filter.h b/src/cpp/common/channel_filter.h
new file mode 100644
index 0000000000..3fbacd824c
--- /dev/null
+++ b/src/cpp/common/channel_filter.h
@@ -0,0 +1,386 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPCXX_CHANNEL_FILTER_H
+#define GRPCXX_CHANNEL_FILTER_H
+
+#include <grpc++/impl/codegen/config.h>
+#include <grpc/census.h>
+#include <grpc/grpc.h>
+#include <grpc/impl/codegen/alloc.h>
+
+#include <functional>
+#include <vector>
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "src/core/lib/transport/metadata_batch.h"
+
+/// An interface to define filters.
+///
+/// To define a filter, implement a subclass of each of \c CallData and
+/// \c ChannelData. Then register the filter using something like this:
+/// \code{.cpp}
+/// RegisterChannelFilter<MyChannelDataSubclass, MyCallDataSubclass>(
+/// "name-of-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr);
+/// \endcode
+
+namespace grpc {
+
+/// A C++ wrapper for the \c grpc_metadata_batch struct.
+class MetadataBatch {
+ public:
+ /// Borrows a pointer to \a batch, but does NOT take ownership.
+ /// The caller must ensure that \a batch continues to exist for as
+ /// long as the MetadataBatch object does.
+ explicit MetadataBatch(grpc_metadata_batch *batch) : batch_(batch) {}
+
+ grpc_metadata_batch *batch() const { return batch_; }
+
+ /// Adds metadata and returns the newly allocated storage.
+ /// The caller takes ownership of the result, which must exist for the
+ /// lifetime of the gRPC call.
+ grpc_linked_mdelem *AddMetadata(const string &key, const string &value);
+
+ class const_iterator : public std::iterator<std::bidirectional_iterator_tag,
+ const grpc_mdelem> {
+ public:
+ const grpc_mdelem &operator*() const { return *elem_->md; }
+ const grpc_mdelem *operator->() const { return elem_->md; }
+
+ const_iterator &operator++() {
+ elem_ = elem_->next;
+ return *this;
+ }
+ const_iterator operator++(int) {
+ const_iterator tmp(*this);
+ operator++();
+ return tmp;
+ }
+ const_iterator &operator--() {
+ elem_ = elem_->prev;
+ return *this;
+ }
+ const_iterator operator--(int) {
+ const_iterator tmp(*this);
+ operator--();
+ return tmp;
+ }
+
+ bool operator==(const const_iterator &other) const {
+ return elem_ == other.elem_;
+ }
+ bool operator!=(const const_iterator &other) const {
+ return elem_ != other.elem_;
+ }
+
+ private:
+ friend class MetadataBatch;
+ explicit const_iterator(grpc_linked_mdelem *elem) : elem_(elem) {}
+
+ grpc_linked_mdelem *elem_;
+ };
+
+ const_iterator begin() const { return const_iterator(batch_->list.head); }
+ const_iterator end() const { return const_iterator(nullptr); }
+
+ private:
+ grpc_metadata_batch *batch_; // Not owned.
+};
+
+/// A C++ wrapper for the \c grpc_transport_op struct.
+class TransportOp {
+ public:
+ /// Borrows a pointer to \a op, but does NOT take ownership.
+ /// The caller must ensure that \a op continues to exist for as
+ /// long as the TransportOp object does.
+ explicit TransportOp(grpc_transport_op *op) : op_(op) {}
+
+ grpc_transport_op *op() const { return op_; }
+
+ // TODO(roth): Add a C++ wrapper for grpc_error?
+ grpc_error *disconnect_with_error() const {
+ return op_->disconnect_with_error;
+ }
+ bool send_goaway() const { return op_->send_goaway; }
+
+ // TODO(roth): Add methods for additional fields as needed.
+
+ private:
+ grpc_transport_op *op_; // Not owned.
+};
+
+/// A C++ wrapper for the \c grpc_transport_stream_op struct.
+class TransportStreamOp {
+ public:
+ /// Borrows a pointer to \a op, but does NOT take ownership.
+ /// The caller must ensure that \a op continues to exist for as
+ /// long as the TransportStreamOp object does.
+ explicit TransportStreamOp(grpc_transport_stream_op *op)
+ : op_(op),
+ send_initial_metadata_(op->send_initial_metadata),
+ send_trailing_metadata_(op->send_trailing_metadata),
+ recv_initial_metadata_(op->recv_initial_metadata),
+ recv_trailing_metadata_(op->recv_trailing_metadata) {}
+
+ grpc_transport_stream_op *op() const { return op_; }
+
+ grpc_closure *on_complete() const { return op_->on_complete; }
+ void set_on_complete(grpc_closure *closure) { op_->on_complete = closure; }
+
+ MetadataBatch *send_initial_metadata() {
+ return op_->send_initial_metadata == nullptr ? nullptr
+ : &send_initial_metadata_;
+ }
+ MetadataBatch *send_trailing_metadata() {
+ return op_->send_trailing_metadata == nullptr ? nullptr
+ : &send_trailing_metadata_;
+ }
+ MetadataBatch *recv_initial_metadata() {
+ return op_->recv_initial_metadata == nullptr ? nullptr
+ : &recv_initial_metadata_;
+ }
+ MetadataBatch *recv_trailing_metadata() {
+ return op_->recv_trailing_metadata == nullptr ? nullptr
+ : &recv_trailing_metadata_;
+ }
+
+ uint32_t *send_initial_metadata_flags() const {
+ return &op_->send_initial_metadata_flags;
+ }
+
+ grpc_closure *recv_initial_metadata_ready() const {
+ return op_->recv_initial_metadata_ready;
+ }
+ void set_recv_initial_metadata_ready(grpc_closure *closure) {
+ op_->recv_initial_metadata_ready = closure;
+ }
+
+ grpc_byte_stream *send_message() const { return op_->send_message; }
+ void set_send_message(grpc_byte_stream *send_message) {
+ op_->send_message = send_message;
+ }
+
+ /// To be called only on clients and servers, respectively.
+ grpc_client_security_context *client_security_context() const {
+ return (grpc_client_security_context *)op_->context[GRPC_CONTEXT_SECURITY]
+ .value;
+ }
+ grpc_server_security_context *server_security_context() const {
+ return (grpc_server_security_context *)op_->context[GRPC_CONTEXT_SECURITY]
+ .value;
+ }
+
+ census_context *get_census_context() const {
+ return (census_context *)op_->context[GRPC_CONTEXT_TRACING].value;
+ }
+
+ private:
+ grpc_transport_stream_op *op_; // Not owned.
+ MetadataBatch send_initial_metadata_;
+ MetadataBatch send_trailing_metadata_;
+ MetadataBatch recv_initial_metadata_;
+ MetadataBatch recv_trailing_metadata_;
+};
+
+/// Represents channel data.
+class ChannelData {
+ public:
+ virtual ~ChannelData() {
+ if (peer_) gpr_free((void *)peer_);
+ }
+
+ /// Caller does NOT take ownership of result.
+ const char *peer() const { return peer_; }
+
+ // TODO(roth): Find a way to avoid passing elem into these methods.
+ virtual void StartTransportOp(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem, TransportOp *op);
+
+ protected:
+ /// Takes ownership of \a peer.
+ ChannelData(const grpc_channel_args &args, const char *peer) : peer_(peer) {}
+
+ private:
+ const char *peer_;
+};
+
+/// Represents call data.
+class CallData {
+ public:
+ virtual ~CallData() {}
+
+ /// Initializes the call data.
+ virtual grpc_error *Init() { return GRPC_ERROR_NONE; }
+
+ // TODO(roth): Find a way to avoid passing elem into these methods.
+
+ /// Starts a new stream operation.
+ virtual void StartTransportStreamOp(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ TransportStreamOp *op);
+
+ /// Sets a pollset or pollset set.
+ virtual void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_polling_entity *pollent);
+
+ /// Gets the peer name.
+ virtual char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
+
+ protected:
+ explicit CallData(const ChannelData &) {}
+};
+
+namespace internal {
+
+// Defines static members for passing to C core.
+// Members of this class correspond to the members of the C
+// grpc_channel_filter struct.
+template <typename ChannelDataType, typename CallDataType>
+class ChannelFilter GRPC_FINAL {
+ public:
+ static const size_t channel_data_size = sizeof(ChannelDataType);
+
+ static void InitChannelElement(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem,
+ grpc_channel_element_args *args) {
+ const char *peer =
+ args->optional_transport
+ ? grpc_transport_get_peer(exec_ctx, args->optional_transport)
+ : nullptr;
+ // Construct the object in the already-allocated memory.
+ new (elem->channel_data) ChannelDataType(*args->channel_args, peer);
+ }
+
+ static void DestroyChannelElement(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem) {
+ reinterpret_cast<ChannelDataType *>(elem->channel_data)->~ChannelDataType();
+ }
+
+ static void StartTransportOp(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem,
+ grpc_transport_op *op) {
+ ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data;
+ TransportOp op_wrapper(op);
+ channel_data->StartTransportOp(exec_ctx, elem, &op_wrapper);
+ }
+
+ static const size_t call_data_size = sizeof(CallDataType);
+
+ static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
+ const ChannelDataType &channel_data =
+ *(ChannelDataType *)elem->channel_data;
+ // Construct the object in the already-allocated memory.
+ CallDataType *call_data = new (elem->call_data) CallDataType(channel_data);
+ return call_data->Init();
+ }
+
+ static void DestroyCallElement(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ const grpc_call_final_info *final_info,
+ void *and_free_memory) {
+ reinterpret_cast<CallDataType *>(elem->call_data)->~CallDataType();
+ }
+
+ static void StartTransportStreamOp(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_transport_stream_op *op) {
+ CallDataType *call_data = (CallDataType *)elem->call_data;
+ TransportStreamOp op_wrapper(op);
+ call_data->StartTransportStreamOp(exec_ctx, elem, &op_wrapper);
+ }
+
+ static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_polling_entity *pollent) {
+ CallDataType *call_data = (CallDataType *)elem->call_data;
+ call_data->SetPollsetOrPollsetSet(exec_ctx, elem, pollent);
+ }
+
+ static char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
+ CallDataType *call_data = (CallDataType *)elem->call_data;
+ return call_data->GetPeer(exec_ctx, elem);
+ }
+};
+
+struct FilterRecord {
+ grpc_channel_stack_type stack_type;
+ int priority;
+ std::function<bool(const grpc_channel_args &)> include_filter;
+ grpc_channel_filter filter;
+};
+extern std::vector<FilterRecord> *channel_filters;
+
+void ChannelFilterPluginInit();
+void ChannelFilterPluginShutdown();
+
+} // namespace internal
+
+/// Registers a new filter.
+/// Must be called by only one thread at a time.
+/// The \a include_filter argument specifies a function that will be called
+/// to determine at run-time whether or not to add the filter. If the
+/// value is nullptr, the filter will be added unconditionally.
+template <typename ChannelDataType, typename CallDataType>
+void RegisterChannelFilter(
+ const char *name, grpc_channel_stack_type stack_type, int priority,
+ std::function<bool(const grpc_channel_args &)> include_filter) {
+ // If we haven't been called before, initialize channel_filters and
+ // call grpc_register_plugin().
+ if (internal::channel_filters == nullptr) {
+ grpc_register_plugin(internal::ChannelFilterPluginInit,
+ internal::ChannelFilterPluginShutdown);
+ internal::channel_filters = new std::vector<internal::FilterRecord>();
+ }
+ // Add an entry to channel_filters. The filter will be added when the
+ // C-core initialization code calls ChannelFilterPluginInit().
+ typedef internal::ChannelFilter<ChannelDataType, CallDataType> FilterType;
+ internal::FilterRecord filter_record = {
+ stack_type,
+ priority,
+ include_filter,
+ {FilterType::StartTransportStreamOp, FilterType::StartTransportOp,
+ FilterType::call_data_size, FilterType::InitCallElement,
+ FilterType::SetPollsetOrPollsetSet, FilterType::DestroyCallElement,
+ FilterType::channel_data_size, FilterType::InitChannelElement,
+ FilterType::DestroyChannelElement, FilterType::GetPeer, name}};
+ internal::channel_filters->push_back(filter_record);
+}
+
+} // namespace grpc
+
+#endif // GRPCXX_CHANNEL_FILTER_H
diff --git a/src/cpp/ext/proto_server_reflection.h b/src/cpp/ext/proto_server_reflection.h
index 23c130513d..f66f3c2c9a 100644
--- a/src/cpp/ext/proto_server_reflection.h
+++ b/src/cpp/ext/proto_server_reflection.h
@@ -30,13 +30,31 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
+
+/*
+ - If the generated header `grpc++/ext/reflection.grpc.pb.h` needs to be
+ installed, target `grpc++_reflection` in `build.yaml` should use the
+ filegroup `grpc++_reflection_proto`, and GRPC_NO_GENERATED_CODE should not
+ be defined.
+ - If the server reflection library needs to generate `reflection.grpc.pb.h`
+ from `reflection.proto` at compile time, the generated header
+ `grpc++/ext/reflection.grpc.pb.h` should not be installed. In this case,
+ target `grpc++_reflection` should depend on `grpc++_reflection_codegen`, and
+ GRPC_NO_GENERATED_CODE should be defined.
+*/
+
#ifndef GRPC_INTERNAL_CPP_EXT_PROTO_SERVER_REFLECTION_H
#define GRPC_INTERNAL_CPP_EXT_PROTO_SERVER_REFLECTION_H
#include <unordered_set>
#include <vector>
+// GRPC_NO_GENERATED_CODE indicates generated pb files should not be used
+#ifdef GRPC_NO_GENERATED_CODE
+#include "src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h"
+#else
#include <grpc++/ext/reflection.grpc.pb.h>
+#endif // GRPC_NO_GENERATED_CODE
#include <grpc++/grpc++.h>
namespace grpc {
diff --git a/src/cpp/ext/reflection.pb.cc b/src/cpp/ext/reflection.pb.cc
index b73a65d0a0..a84494f9a9 100644
--- a/src/cpp/ext/reflection.pb.cc
+++ b/src/cpp/ext/reflection.pb.cc
@@ -98,6 +98,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
+void protobuf_AssignDesc_reflection_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_reflection_2eproto() {
protobuf_AddDesc_reflection_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -253,6 +254,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_reflection_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -296,6 +298,7 @@ void protobuf_ShutdownFile_reflection_2eproto() {
delete ErrorResponse_reflection_;
}
+void protobuf_AddDesc_reflection_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_reflection_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -366,16 +369,6 @@ struct StaticDescriptorInitializer_reflection_2eproto {
}
} static_descriptor_initializer_reflection_2eproto_;
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -684,8 +677,8 @@ void ServerReflectionRequest::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_end:grpc.reflection.v1alpha.ServerReflectionRequest)
}
-::google::protobuf::uint8* ServerReflectionRequest::SerializeWithCachedSizesToArray(
- ::google::protobuf::uint8* target) const {
+::google::protobuf::uint8* ServerReflectionRequest::InternalSerializeWithCachedSizesToArray(
+ bool deterministic, ::google::protobuf::uint8* target) const {
// @@protoc_insertion_point(serialize_to_array_start:grpc.reflection.v1alpha.ServerReflectionRequest)
// optional string host = 1;
if (this->host().size() > 0) {
@@ -723,8 +716,8 @@ void ServerReflectionRequest::SerializeWithCachedSizes(
// optional .grpc.reflection.v1alpha.ExtensionRequest file_containing_extension = 5;
if (has_file_containing_extension()) {
target = ::google::protobuf::internal::WireFormatLite::
- WriteMessageNoVirtualToArray(
- 5, *message_request_.file_containing_extension_, target);
+ InternalWriteMessageNoVirtualToArray(
+ 5, *message_request_.file_containing_extension_, false, target);
}
// optional string all_extension_numbers_of_type = 6;
@@ -812,7 +805,9 @@ int ServerReflectionRequest::ByteSize() const {
void ServerReflectionRequest::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:grpc.reflection.v1alpha.ServerReflectionRequest)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const ServerReflectionRequest* source =
::google::protobuf::internal::DynamicCastToGenerated<const ServerReflectionRequest>(
&from);
@@ -827,7 +822,9 @@ void ServerReflectionRequest::MergeFrom(const ::google::protobuf::Message& from)
void ServerReflectionRequest::MergeFrom(const ServerReflectionRequest& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:grpc.reflection.v1alpha.ServerReflectionRequest)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
switch (from.message_request_case()) {
case kFileByFilename: {
set_file_by_filename(from.file_by_filename());
@@ -1486,8 +1483,8 @@ void ExtensionRequest::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_end:grpc.reflection.v1alpha.ExtensionRequest)
}
-::google::protobuf::uint8* ExtensionRequest::SerializeWithCachedSizesToArray(
- ::google::protobuf::uint8* target) const {
+::google::protobuf::uint8* ExtensionRequest::InternalSerializeWithCachedSizesToArray(
+ bool deterministic, ::google::protobuf::uint8* target) const {
// @@protoc_insertion_point(serialize_to_array_start:grpc.reflection.v1alpha.ExtensionRequest)
// optional string containing_type = 1;
if (this->containing_type().size() > 0) {
@@ -1535,7 +1532,9 @@ int ExtensionRequest::ByteSize() const {
void ExtensionRequest::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:grpc.reflection.v1alpha.ExtensionRequest)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const ExtensionRequest* source =
::google::protobuf::internal::DynamicCastToGenerated<const ExtensionRequest>(
&from);
@@ -1550,7 +1549,9 @@ void ExtensionRequest::MergeFrom(const ::google::protobuf::Message& from) {
void ExtensionRequest::MergeFrom(const ExtensionRequest& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:grpc.reflection.v1alpha.ExtensionRequest)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.containing_type().size() > 0) {
containing_type_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.containing_type_);
@@ -1937,8 +1938,8 @@ void ServerReflectionResponse::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_end:grpc.reflection.v1alpha.ServerReflectionResponse)
}
-::google::protobuf::uint8* ServerReflectionResponse::SerializeWithCachedSizesToArray(
- ::google::protobuf::uint8* target) const {
+::google::protobuf::uint8* ServerReflectionResponse::InternalSerializeWithCachedSizesToArray(
+ bool deterministic, ::google::protobuf::uint8* target) const {
// @@protoc_insertion_point(serialize_to_array_start:grpc.reflection.v1alpha.ServerReflectionResponse)
// optional string valid_host = 1;
if (this->valid_host().size() > 0) {
@@ -1954,36 +1955,36 @@ void ServerReflectionResponse::SerializeWithCachedSizes(
// optional .grpc.reflection.v1alpha.ServerReflectionRequest original_request = 2;
if (this->has_original_request()) {
target = ::google::protobuf::internal::WireFormatLite::
- WriteMessageNoVirtualToArray(
- 2, *this->original_request_, target);
+ InternalWriteMessageNoVirtualToArray(
+ 2, *this->original_request_, false, target);
}
// optional .grpc.reflection.v1alpha.FileDescriptorResponse file_descriptor_response = 4;
if (has_file_descriptor_response()) {
target = ::google::protobuf::internal::WireFormatLite::
- WriteMessageNoVirtualToArray(
- 4, *message_response_.file_descriptor_response_, target);
+ InternalWriteMessageNoVirtualToArray(
+ 4, *message_response_.file_descriptor_response_, false, target);
}
// optional .grpc.reflection.v1alpha.ExtensionNumberResponse all_extension_numbers_response = 5;
if (has_all_extension_numbers_response()) {
target = ::google::protobuf::internal::WireFormatLite::
- WriteMessageNoVirtualToArray(
- 5, *message_response_.all_extension_numbers_response_, target);
+ InternalWriteMessageNoVirtualToArray(
+ 5, *message_response_.all_extension_numbers_response_, false, target);
}
// optional .grpc.reflection.v1alpha.ListServiceResponse list_services_response = 6;
if (has_list_services_response()) {
target = ::google::protobuf::internal::WireFormatLite::
- WriteMessageNoVirtualToArray(
- 6, *message_response_.list_services_response_, target);
+ InternalWriteMessageNoVirtualToArray(
+ 6, *message_response_.list_services_response_, false, target);
}
// optional .grpc.reflection.v1alpha.ErrorResponse error_response = 7;
if (has_error_response()) {
target = ::google::protobuf::internal::WireFormatLite::
- WriteMessageNoVirtualToArray(
- 7, *message_response_.error_response_, target);
+ InternalWriteMessageNoVirtualToArray(
+ 7, *message_response_.error_response_, false, target);
}
// @@protoc_insertion_point(serialize_to_array_end:grpc.reflection.v1alpha.ServerReflectionResponse)
@@ -2049,7 +2050,9 @@ int ServerReflectionResponse::ByteSize() const {
void ServerReflectionResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:grpc.reflection.v1alpha.ServerReflectionResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const ServerReflectionResponse* source =
::google::protobuf::internal::DynamicCastToGenerated<const ServerReflectionResponse>(
&from);
@@ -2064,7 +2067,9 @@ void ServerReflectionResponse::MergeFrom(const ::google::protobuf::Message& from
void ServerReflectionResponse::MergeFrom(const ServerReflectionResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:grpc.reflection.v1alpha.ServerReflectionResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
switch (from.message_response_case()) {
case kFileDescriptorResponse: {
mutable_file_descriptor_response()->::grpc::reflection::v1alpha::FileDescriptorResponse::MergeFrom(from.file_descriptor_response());
@@ -2550,8 +2555,8 @@ void FileDescriptorResponse::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_end:grpc.reflection.v1alpha.FileDescriptorResponse)
}
-::google::protobuf::uint8* FileDescriptorResponse::SerializeWithCachedSizesToArray(
- ::google::protobuf::uint8* target) const {
+::google::protobuf::uint8* FileDescriptorResponse::InternalSerializeWithCachedSizesToArray(
+ bool deterministic, ::google::protobuf::uint8* target) const {
// @@protoc_insertion_point(serialize_to_array_start:grpc.reflection.v1alpha.FileDescriptorResponse)
// repeated bytes file_descriptor_proto = 1;
for (int i = 0; i < this->file_descriptor_proto_size(); i++) {
@@ -2582,7 +2587,9 @@ int FileDescriptorResponse::ByteSize() const {
void FileDescriptorResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:grpc.reflection.v1alpha.FileDescriptorResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const FileDescriptorResponse* source =
::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorResponse>(
&from);
@@ -2597,7 +2604,9 @@ void FileDescriptorResponse::MergeFrom(const ::google::protobuf::Message& from)
void FileDescriptorResponse::MergeFrom(const FileDescriptorResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:grpc.reflection.v1alpha.FileDescriptorResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
file_descriptor_proto_.MergeFrom(from.file_descriptor_proto_);
}
@@ -2863,8 +2872,8 @@ void ExtensionNumberResponse::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_end:grpc.reflection.v1alpha.ExtensionNumberResponse)
}
-::google::protobuf::uint8* ExtensionNumberResponse::SerializeWithCachedSizesToArray(
- ::google::protobuf::uint8* target) const {
+::google::protobuf::uint8* ExtensionNumberResponse::InternalSerializeWithCachedSizesToArray(
+ bool deterministic, ::google::protobuf::uint8* target) const {
// @@protoc_insertion_point(serialize_to_array_start:grpc.reflection.v1alpha.ExtensionNumberResponse)
// optional string base_type_name = 1;
if (this->base_type_name().size() > 0) {
@@ -2931,7 +2940,9 @@ int ExtensionNumberResponse::ByteSize() const {
void ExtensionNumberResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:grpc.reflection.v1alpha.ExtensionNumberResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const ExtensionNumberResponse* source =
::google::protobuf::internal::DynamicCastToGenerated<const ExtensionNumberResponse>(
&from);
@@ -2946,7 +2957,9 @@ void ExtensionNumberResponse::MergeFrom(const ::google::protobuf::Message& from)
void ExtensionNumberResponse::MergeFrom(const ExtensionNumberResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:grpc.reflection.v1alpha.ExtensionNumberResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
extension_number_.MergeFrom(from.extension_number_);
if (from.base_type_name().size() > 0) {
@@ -3199,14 +3212,14 @@ void ListServiceResponse::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_end:grpc.reflection.v1alpha.ListServiceResponse)
}
-::google::protobuf::uint8* ListServiceResponse::SerializeWithCachedSizesToArray(
- ::google::protobuf::uint8* target) const {
+::google::protobuf::uint8* ListServiceResponse::InternalSerializeWithCachedSizesToArray(
+ bool deterministic, ::google::protobuf::uint8* target) const {
// @@protoc_insertion_point(serialize_to_array_start:grpc.reflection.v1alpha.ListServiceResponse)
// repeated .grpc.reflection.v1alpha.ServiceResponse service = 1;
for (unsigned int i = 0, n = this->service_size(); i < n; i++) {
target = ::google::protobuf::internal::WireFormatLite::
- WriteMessageNoVirtualToArray(
- 1, this->service(i), target);
+ InternalWriteMessageNoVirtualToArray(
+ 1, this->service(i), false, target);
}
// @@protoc_insertion_point(serialize_to_array_end:grpc.reflection.v1alpha.ListServiceResponse)
@@ -3233,7 +3246,9 @@ int ListServiceResponse::ByteSize() const {
void ListServiceResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:grpc.reflection.v1alpha.ListServiceResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const ListServiceResponse* source =
::google::protobuf::internal::DynamicCastToGenerated<const ListServiceResponse>(
&from);
@@ -3248,7 +3263,9 @@ void ListServiceResponse::MergeFrom(const ::google::protobuf::Message& from) {
void ListServiceResponse::MergeFrom(const ListServiceResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:grpc.reflection.v1alpha.ListServiceResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
service_.MergeFrom(from.service_);
}
@@ -3459,8 +3476,8 @@ void ServiceResponse::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_end:grpc.reflection.v1alpha.ServiceResponse)
}
-::google::protobuf::uint8* ServiceResponse::SerializeWithCachedSizesToArray(
- ::google::protobuf::uint8* target) const {
+::google::protobuf::uint8* ServiceResponse::InternalSerializeWithCachedSizesToArray(
+ bool deterministic, ::google::protobuf::uint8* target) const {
// @@protoc_insertion_point(serialize_to_array_start:grpc.reflection.v1alpha.ServiceResponse)
// optional string name = 1;
if (this->name().size() > 0) {
@@ -3496,7 +3513,9 @@ int ServiceResponse::ByteSize() const {
void ServiceResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:grpc.reflection.v1alpha.ServiceResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const ServiceResponse* source =
::google::protobuf::internal::DynamicCastToGenerated<const ServiceResponse>(
&from);
@@ -3511,7 +3530,9 @@ void ServiceResponse::MergeFrom(const ::google::protobuf::Message& from) {
void ServiceResponse::MergeFrom(const ServiceResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:grpc.reflection.v1alpha.ServiceResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.name().size() > 0) {
name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
@@ -3762,8 +3783,8 @@ void ErrorResponse::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_end:grpc.reflection.v1alpha.ErrorResponse)
}
-::google::protobuf::uint8* ErrorResponse::SerializeWithCachedSizesToArray(
- ::google::protobuf::uint8* target) const {
+::google::protobuf::uint8* ErrorResponse::InternalSerializeWithCachedSizesToArray(
+ bool deterministic, ::google::protobuf::uint8* target) const {
// @@protoc_insertion_point(serialize_to_array_start:grpc.reflection.v1alpha.ErrorResponse)
// optional int32 error_code = 1;
if (this->error_code() != 0) {
@@ -3811,7 +3832,9 @@ int ErrorResponse::ByteSize() const {
void ErrorResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:grpc.reflection.v1alpha.ErrorResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const ErrorResponse* source =
::google::protobuf::internal::DynamicCastToGenerated<const ErrorResponse>(
&from);
@@ -3826,7 +3849,9 @@ void ErrorResponse::MergeFrom(const ::google::protobuf::Message& from) {
void ErrorResponse::MergeFrom(const ErrorResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:grpc.reflection.v1alpha.ErrorResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.error_code() != 0) {
set_error_code(from.error_code());
}
diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc
index 43117fd1e9..1ca6a2b906 100644
--- a/src/cpp/server/server_context.cc
+++ b/src/cpp/server/server_context.cc
@@ -129,7 +129,8 @@ ServerContext::ServerContext()
deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)),
call_(nullptr),
cq_(nullptr),
- sent_initial_metadata_(false) {}
+ sent_initial_metadata_(false),
+ compression_level_set_(false) {}
ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
size_t metadata_count)
@@ -139,7 +140,8 @@ ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
deadline_(deadline),
call_(nullptr),
cq_(nullptr),
- sent_initial_metadata_(false) {
+ sent_initial_metadata_(false),
+ compression_level_set_(false) {
for (size_t i = 0; i < metadata_count; i++) {
client_metadata_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
metadata[i].key,
@@ -194,15 +196,6 @@ bool ServerContext::IsCancelled() const {
}
}
-void ServerContext::set_compression_level(grpc_compression_level level) {
- // TODO(dgq): get rid of grpc_call_compression_for_level and propagate the
- // compression level by adding a new argument to
- // CallOpSendInitialMetadata::SendInitialMetadata.
- const grpc_compression_algorithm algorithm_for_level =
- grpc_call_compression_for_level(call_, level);
- set_compression_algorithm(algorithm_for_level);
-}
-
void ServerContext::set_compression_algorithm(
grpc_compression_algorithm algorithm) {
char* algorithm_name = NULL;
diff --git a/src/cpp/util/byte_buffer.cc b/src/cpp/util/byte_buffer.cc
index c2cd20ee07..91ed66b766 100644
--- a/src/cpp/util/byte_buffer.cc
+++ b/src/cpp/util/byte_buffer.cc
@@ -37,12 +37,19 @@
namespace grpc {
ByteBuffer::ByteBuffer(const Slice* slices, size_t nslices) {
- // TODO(yangg) maybe expose some core API to simplify this
- std::vector<gpr_slice> c_slices(nslices);
- for (size_t i = 0; i < nslices; i++) {
- c_slices[i] = slices[i].slice_;
- }
- buffer_ = grpc_raw_byte_buffer_create(c_slices.data(), nslices);
+ // The following assertions check that the representation of a grpc::Slice is
+ // identical to that of a gpr_slice: it has a gpr_slice field, and nothing
+ // else.
+ static_assert(std::is_same<decltype(slices[0].slice_), gpr_slice>::value,
+ "Slice must have same representation as gpr_slice");
+ static_assert(sizeof(Slice) == sizeof(gpr_slice),
+ "Slice must have same representation as gpr_slice");
+ // The const_cast is legal if grpc_raw_byte_buffer_create() does no more
+ // than its advertised side effect of increasing the reference count of the
+ // slices it processes, and such an increase does not affect the semantics
+ // seen by the caller of this constructor.
+ buffer_ = grpc_raw_byte_buffer_create(
+ reinterpret_cast<gpr_slice*>(const_cast<Slice*>(slices)), nslices);
}
ByteBuffer::~ByteBuffer() {
@@ -95,4 +102,10 @@ ByteBuffer& ByteBuffer::operator=(const ByteBuffer& buf) {
return *this;
}
+void ByteBuffer::Swap(ByteBuffer* other) {
+ grpc_byte_buffer* tmp = other->buffer_;
+ other->buffer_ = buffer_;
+ buffer_ = tmp;
+}
+
} // namespace grpc
diff --git a/src/csharp/.nuget/packages.config b/src/csharp/.nuget/packages.config
deleted file mode 100644
index 6154b3561f..0000000000
--- a/src/csharp/.nuget/packages.config
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="NUnit.ConsoleRunner" version="3.2.0" />
- <package id="OpenCover" version="4.6.519" />
- <package id="ReportGenerator" version="2.4.4.0" />
-</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.csproj b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
index 1fa14fc3df..7a6955311a 100644
--- a/src/csharp/Grpc.Auth/Grpc.Auth.csproj
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
@@ -39,30 +39,25 @@
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
- <Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="System" />
+ <Reference Include="System.Net" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Net.Http.WebRequest" />
+ <Reference Include="BouncyCastle.Crypto">
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
+ <Reference Include="Newtonsoft.Json">
+ <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ <Reference Include="Google.Apis.Core">
+ <HintPath>..\packages\Google.Apis.Core.1.15.0\lib\net45\Google.Apis.Core.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Core, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
+ <Reference Include="Google.Apis.Auth">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.dll</HintPath>
</Reference>
- <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+ <Reference Include="Google.Apis.Auth.PlatformServices">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
- <Reference Include="System" />
- <Reference Include="System.Net" />
- <Reference Include="System.Net.Http" />
- <Reference Include="System.Net.Http.WebRequest" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
index 4baed3704c..a1f5668e2e 100644
--- a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
@@ -15,7 +15,7 @@
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2 Auth OAuth2</tags>
<dependencies>
- <dependency id="Google.Apis.Auth" version="1.11.1" />
+ <dependency id="Google.Apis.Auth" version="1.15.0" />
<dependency id="Grpc.Core" version="$version$" />
</dependencies>
</metadata>
diff --git a/src/csharp/Grpc.Auth/packages.config b/src/csharp/Grpc.Auth/packages.config
index c20d9ceed6..738d3e6f3b 100644
--- a/src/csharp/Grpc.Auth/packages.config
+++ b/src/csharp/Grpc.Auth/packages.config
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.11.1" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.11.1" targetFramework="net45" />
+ <package id="Google.Apis.Auth" version="1.15.0" targetFramework="net45" />
+ <package id="Google.Apis.Core" version="1.15.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Auth/project.json b/src/csharp/Grpc.Auth/project.json
index 08429f1d46..30f0944693 100644
--- a/src/csharp/Grpc.Auth/project.json
+++ b/src/csharp/Grpc.Auth/project.json
@@ -23,18 +23,18 @@
},
"dependencies": {
"Grpc.Core": "1.1.0-dev",
- "Google.Apis.Auth": "1.11.1"
+ "Google.Apis.Auth": "1.15.0"
},
"frameworks": {
"net45": { },
"netstandard1.5": {
"imports": [
- "net45"
+ "portable-net45"
],
"dependencies": {
- "Microsoft.NETCore.Portable.Compatibility": "1.0.1-rc2-24027",
- "NETStandard.Library": "1.5.0-rc2-24027",
- "System.Threading.Tasks": "4.0.11-rc2-24027"
+ "Microsoft.NETCore.Portable.Compatibility": "1.0.1",
+ "NETStandard.Library": "1.6.0",
+ "System.Threading.Tasks": "4.0.11"
}
}
}
diff --git a/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs b/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs
index 064bc13cab..d7ebdb4201 100644
--- a/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs
+++ b/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs
@@ -40,7 +40,7 @@ namespace Grpc.Core.Tests
{
public class AppDomainUnloadTest
{
-#if NETSTANDARD1_5
+#if NETCOREAPP1_0
[Test]
[Ignore("Not supported for CoreCLR")]
public void AppDomainUnloadHookCanCleanupAbandonedCall()
diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
index f6c226567d..d99bf8e4e1 100644
--- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
+++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
@@ -40,7 +40,7 @@
<HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System.Interactive.Async">
- <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
+ <HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="nunitlite">
<HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
@@ -108,4 +108,4 @@
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/csharp/Grpc.Core.Tests/NUnitMain.cs b/src/csharp/Grpc.Core.Tests/NUnitMain.cs
index 24a9f846d1..870c726ac0 100644
--- a/src/csharp/Grpc.Core.Tests/NUnitMain.cs
+++ b/src/csharp/Grpc.Core.Tests/NUnitMain.cs
@@ -49,7 +49,7 @@ namespace Grpc.Core.Tests
{
// Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
-#if NETSTANDARD1_5
+#if NETCOREAPP1_0
return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
#else
return new AutoRun().Execute(args);
diff --git a/src/csharp/Grpc.Core.Tests/SanityTest.cs b/src/csharp/Grpc.Core.Tests/SanityTest.cs
index 501992c569..f1eb13dffc 100644
--- a/src/csharp/Grpc.Core.Tests/SanityTest.cs
+++ b/src/csharp/Grpc.Core.Tests/SanityTest.cs
@@ -46,7 +46,7 @@ namespace Grpc.Core.Tests
public class SanityTest
{
// TODO: make sanity test work for CoreCLR as well
-#if !NETSTANDARD1_5
+#if !NETCOREAPP1_0
/// <summary>
/// Because we depend on a native library, sometimes when things go wrong, the
/// entire NUnit test process crashes. To be able to track down problems better,
@@ -59,9 +59,10 @@ namespace Grpc.Core.Tests
public void TestsJsonUpToDate()
{
var discoveredTests = DiscoverAllTestClasses();
- string discoveredTestsJson = JsonConvert.SerializeObject(discoveredTests, Formatting.Indented);
+ var testsFromFile
+ = JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(ReadTestsJson());
- Assert.AreEqual(discoveredTestsJson, ReadTestsJson());
+ Assert.AreEqual(discoveredTests, testsFromFile);
}
/// <summary>
diff --git a/src/csharp/Grpc.Core.Tests/packages.config b/src/csharp/Grpc.Core.Tests/packages.config
index aa7d951fdc..456ffcd8d0 100644
--- a/src/csharp/Grpc.Core.Tests/packages.config
+++ b/src/csharp/Grpc.Core.Tests/packages.config
@@ -1,7 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
+ <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
<package id="NUnit" version="3.2.0" targetFramework="net45" />
<package id="NUnitLite" version="3.2.0" targetFramework="net45" />
-</packages> \ No newline at end of file
+ <package id="NUnit.ConsoleRunner" version="3.2.0" />
+ <package id="OpenCover" version="4.6.519" />
+ <package id="ReportGenerator" version="2.4.4.0" />
+</packages>
diff --git a/src/csharp/Grpc.Core.Tests/project.json b/src/csharp/Grpc.Core.Tests/project.json
index f58bcbb515..014e2262e9 100644
--- a/src/csharp/Grpc.Core.Tests/project.json
+++ b/src/csharp/Grpc.Core.Tests/project.json
@@ -14,10 +14,10 @@
},
"copyToOutput": {
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
@@ -33,10 +33,10 @@
},
"copyToOutput": {
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
@@ -54,16 +54,20 @@
},
"Newtonsoft.Json": "8.0.3",
"NUnit": "3.2.0",
- "NUnitLite": "3.2.0-*"
+ "NUnitLite": "3.2.0-*",
+ "NUnit.ConsoleRunner": "3.2.0",
+ "OpenCover": "4.6.519",
+ "ReportGenerator": "2.4.4.0"
},
"frameworks": {
"net45": { },
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027"
+ "Microsoft.NETCore.App": "1.0.0",
+ "NETStandard.Library": "1.6.0"
}
}
},
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 1952ee3712..622813fb38 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -40,7 +40,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Interactive.Async">
- <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
+ <HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -152,4 +152,4 @@
<Link>roots.pem</Link>
</EmbeddedResource>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec
index 47593f787b..a8459c4d9c 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.nuspec
+++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec
@@ -15,7 +15,7 @@
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
<dependencies>
- <dependency id="Ix-Async" version="1.2.5" />
+ <dependency id="System.Interactive.Async" version="3.0.0" />
</dependencies>
</metadata>
<files>
@@ -25,11 +25,11 @@
<file src="**\*.cs" target="src" />
<file src="Grpc.Core.targets" target="\build\net45\Grpc.Core.targets" />
<!-- without backslashes in the the source path, nuget won't copy the files -->
- <file src="..\nativelibs\windows_x86\grpc_csharp_ext.dll" target="/build/native/bin/windows_x86/grpc_csharp_ext.dll" />
- <file src="..\nativelibs\windows_x64\grpc_csharp_ext.dll" target="/build/native/bin/windows_x64/grpc_csharp_ext.dll" />
- <file src="..\nativelibs\linux_x86\libgrpc_csharp_ext.so" target="/build/native/bin/linux_x86/libgrpc_csharp_ext.so" />
- <file src="..\nativelibs\linux_x64\libgrpc_csharp_ext.so" target="/build/native/bin/linux_x64/libgrpc_csharp_ext.so" />
- <file src="..\nativelibs\macosx_x86\libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x86/libgrpc_csharp_ext.dylib" />
- <file src="..\nativelibs\macosx_x64\libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x64/libgrpc_csharp_ext.dylib" />
+ <file src="..\nativelibs\windows_x86\grpc_csharp_ext.dll" target="/runtimes/win/native/grpc_csharp_ext.x86.dll" />
+ <file src="..\nativelibs\windows_x64\grpc_csharp_ext.dll" target="/runtimes/win/native/grpc_csharp_ext.x64.dll" />
+ <file src="..\nativelibs\linux_x86\libgrpc_csharp_ext.so" target="/runtimes/linux/native/libgrpc_csharp_ext.x86.so" />
+ <file src="..\nativelibs\linux_x64\libgrpc_csharp_ext.so" target="/runtimes/linux/native/libgrpc_csharp_ext.x64.so" />
+ <file src="..\nativelibs\macosx_x86\libgrpc_csharp_ext.dylib" target="/runtimes/osx/native/libgrpc_csharp_ext.x86.dylib" />
+ <file src="..\nativelibs\macosx_x64\libgrpc_csharp_ext.dylib" target="/runtimes/osx/native/libgrpc_csharp_ext.x64.dylib" />
</files>
</package>
diff --git a/src/csharp/Grpc.Core/Grpc.Core.targets b/src/csharp/Grpc.Core/Grpc.Core.targets
index 501fc50548..3367d51a80 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.targets
+++ b/src/csharp/Grpc.Core/Grpc.Core.targets
@@ -1,29 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
- <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\windows_x86\grpc_csharp_ext.dll">
+ <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win\native\grpc_csharp_ext.x86.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- <Link>nativelibs\windows_x86\grpc_csharp_ext.dll</Link>
+ <Link>grpc_csharp_ext.x86.dll</Link>
</Content>
- <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\windows_x64\grpc_csharp_ext.dll">
+ <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win\native\grpc_csharp_ext.x64.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- <Link>nativelibs\windows_x64\grpc_csharp_ext.dll</Link>
+ <Link>grpc_csharp_ext.x64.dll</Link>
</Content>
- <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\linux_x86\libgrpc_csharp_ext.so">
+ <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\linux\native\libgrpc_csharp_ext.x86.so">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- <Link>nativelibs\linux_x86\libgrpc_csharp_ext.so</Link>
+ <Link>libgrpc_csharp_ext.x86.so</Link>
</Content>
- <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\linux_x64\libgrpc_csharp_ext.so">
+ <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\linux\native\libgrpc_csharp_ext.x64.so">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- <Link>nativelibs\linux_x64\libgrpc_csharp_ext.so</Link>
+ <Link>libgrpc_csharp_ext.x64.so</Link>
</Content>
- <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\macosx_x86\libgrpc_csharp_ext.dylib">
+ <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\osx\native\libgrpc_csharp_ext.x86.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- <Link>nativelibs\macosx_x86\libgrpc_csharp_ext.dylib</Link>
+ <Link>libgrpc_csharp_ext.x86.dylib</Link>
</Content>
- <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\macosx_x64\libgrpc_csharp_ext.dylib">
+ <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\osx\native\libgrpc_csharp_ext.x64.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- <Link>nativelibs\macosx_x64\libgrpc_csharp_ext.dylib</Link>
+ <Link>libgrpc_csharp_ext.x64.dylib</Link>
</Content>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs
index eeed699712..574e900a0e 100644
--- a/src/csharp/Grpc.Core/GrpcEnvironment.cs
+++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs
@@ -47,7 +47,6 @@ namespace Grpc.Core
/// </summary>
public class GrpcEnvironment
{
- const LogLevel DefaultLogLevel = LogLevel.Info;
const int MinDefaultThreadPoolSize = 4;
static object staticLock = new object();
@@ -58,7 +57,7 @@ namespace Grpc.Core
static readonly HashSet<Channel> registeredChannels = new HashSet<Channel>();
static readonly HashSet<Server> registeredServers = new HashSet<Server>();
- static ILogger logger = new LogLevelFilterLogger(new ConsoleLogger(), DefaultLogLevel);
+ static ILogger logger = new NullLogger();
readonly object myLock = new object();
readonly GrpcThreadPool threadPool;
diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs
index a6d7925816..509baf7cb1 100644
--- a/src/csharp/Grpc.Core/Internal/NativeExtension.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs
@@ -44,9 +44,6 @@ namespace Grpc.Core.Internal
/// </summary>
internal sealed class NativeExtension
{
- const string NativeLibrariesDir = "nativelibs";
- const string DnxStyleNativeLibrariesDir = "../../build/native/bin/";
-
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeExtension>();
static readonly object staticLock = new object();
static volatile NativeExtension instance;
@@ -98,20 +95,25 @@ namespace Grpc.Core.Internal
private static UnmanagedLibrary Load()
{
// TODO: allow customizing path to native extension (possibly through exposing a GrpcEnvironment property).
-
- var libraryFlavor = string.Format("{0}_{1}", GetPlatformString(), GetArchitectureString());
-
+ // See https://github.com/grpc/grpc/pull/7303 for one option.
var assemblyDirectory = Path.GetDirectoryName(GetAssemblyPath());
// With old-style VS projects, the native libraries get copied using a .targets rule to the build output folder
// alongside the compiled assembly.
- var classicPath = Path.Combine(assemblyDirectory, NativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename());
+ // With dotnet cli projects, the native libraries (just the required ones) are similarly copied to the built output folder,
+ // through the magic of Microsoft.NETCore.Platforms.
+ var classicPath = Path.Combine(assemblyDirectory, GetNativeLibraryFilename());
// DNX-style project.json projects will use Grpc.Core assembly directly in the location where it got restored
// by nuget. We locate the native libraries based on known structure of Grpc.Core nuget package.
- var dnxStylePath = Path.Combine(assemblyDirectory, DnxStyleNativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename());
- return new UnmanagedLibrary(new string[] {classicPath, dnxStylePath});
+ // TODO: Support .NET Core applications, which act slightly differently. We may be okay if "dotnet publish"
+ // is used, but "dotnet run" leaves the native libraries in-package, while copying assemblies.
+ string platform = GetPlatformString();
+ string relativeDirectory = string.Format("../../runtimes/{0}/native", platform);
+ var dnxStylePath = Path.Combine(assemblyDirectory, relativeDirectory, GetNativeLibraryFilename());
+ string[] paths = new[] { classicPath, dnxStylePath };
+ return new UnmanagedLibrary(paths);
}
private static string GetAssemblyPath()
@@ -147,7 +149,7 @@ namespace Grpc.Core.Internal
{
if (PlatformApis.IsWindows)
{
- return "windows";
+ return "win";
}
if (PlatformApis.IsLinux)
{
@@ -155,7 +157,7 @@ namespace Grpc.Core.Internal
}
if (PlatformApis.IsMacOSX)
{
- return "macosx";
+ return "osx";
}
throw new InvalidOperationException("Unsupported platform.");
}
@@ -176,17 +178,18 @@ namespace Grpc.Core.Internal
// platform specific file name of the extension library
private static string GetNativeLibraryFilename()
{
+ string architecture = GetArchitectureString();
if (PlatformApis.IsWindows)
{
- return "grpc_csharp_ext.dll";
+ return string.Format("grpc_csharp_ext.{0}.dll", architecture);
}
if (PlatformApis.IsLinux)
{
- return "libgrpc_csharp_ext.so";
+ return string.Format("libgrpc_csharp_ext.{0}.so", architecture);
}
if (PlatformApis.IsMacOSX)
{
- return "libgrpc_csharp_ext.dylib";
+ return string.Format("libgrpc_csharp_ext.{0}.dylib", architecture);
}
throw new InvalidOperationException("Unsupported platform.");
}
diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
index 65607ed120..f457c9dbf1 100644
--- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
@@ -159,215 +159,107 @@ namespace Grpc.Core.Internal
public NativeMethods(UnmanagedLibrary library)
{
- if (PlatformApis.IsLinux || PlatformApis.IsMacOSX)
- {
- this.grpcsharp_init = GetMethodDelegate<Delegates.grpcsharp_init_delegate>(library);
- this.grpcsharp_shutdown = GetMethodDelegate<Delegates.grpcsharp_shutdown_delegate>(library);
- this.grpcsharp_version_string = GetMethodDelegate<Delegates.grpcsharp_version_string_delegate>(library);
-
- this.grpcsharp_batch_context_create = GetMethodDelegate<Delegates.grpcsharp_batch_context_create_delegate>(library);
- this.grpcsharp_batch_context_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_initial_metadata_delegate>(library);
- this.grpcsharp_batch_context_recv_message_length = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_length_delegate>(library);
- this.grpcsharp_batch_context_recv_message_to_buffer = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_to_buffer_delegate>(library);
- this.grpcsharp_batch_context_recv_status_on_client_status = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate>(library);
- this.grpcsharp_batch_context_recv_status_on_client_details = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate>(library);
- this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate>(library);
- this.grpcsharp_batch_context_server_rpc_new_call = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_call_delegate>(library);
- this.grpcsharp_batch_context_server_rpc_new_method = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_method_delegate>(library);
- this.grpcsharp_batch_context_server_rpc_new_host = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_host_delegate>(library);
- this.grpcsharp_batch_context_server_rpc_new_deadline = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_deadline_delegate>(library);
- this.grpcsharp_batch_context_server_rpc_new_request_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_request_metadata_delegate>(library);
- this.grpcsharp_batch_context_recv_close_on_server_cancelled = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate>(library);
- this.grpcsharp_batch_context_destroy = GetMethodDelegate<Delegates.grpcsharp_batch_context_destroy_delegate>(library);
-
- this.grpcsharp_composite_call_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_call_credentials_create_delegate>(library);
- this.grpcsharp_call_credentials_release = GetMethodDelegate<Delegates.grpcsharp_call_credentials_release_delegate>(library);
-
- this.grpcsharp_call_cancel = GetMethodDelegate<Delegates.grpcsharp_call_cancel_delegate>(library);
- this.grpcsharp_call_cancel_with_status = GetMethodDelegate<Delegates.grpcsharp_call_cancel_with_status_delegate>(library);
- this.grpcsharp_call_start_unary = GetMethodDelegate<Delegates.grpcsharp_call_start_unary_delegate>(library);
- this.grpcsharp_call_start_client_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_client_streaming_delegate>(library);
- this.grpcsharp_call_start_server_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_server_streaming_delegate>(library);
- this.grpcsharp_call_start_duplex_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_duplex_streaming_delegate>(library);
- this.grpcsharp_call_send_message = GetMethodDelegate<Delegates.grpcsharp_call_send_message_delegate>(library);
- this.grpcsharp_call_send_close_from_client = GetMethodDelegate<Delegates.grpcsharp_call_send_close_from_client_delegate>(library);
- this.grpcsharp_call_send_status_from_server = GetMethodDelegate<Delegates.grpcsharp_call_send_status_from_server_delegate>(library);
- this.grpcsharp_call_recv_message = GetMethodDelegate<Delegates.grpcsharp_call_recv_message_delegate>(library);
- this.grpcsharp_call_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_recv_initial_metadata_delegate>(library);
- this.grpcsharp_call_start_serverside = GetMethodDelegate<Delegates.grpcsharp_call_start_serverside_delegate>(library);
- this.grpcsharp_call_send_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_send_initial_metadata_delegate>(library);
- this.grpcsharp_call_set_credentials = GetMethodDelegate<Delegates.grpcsharp_call_set_credentials_delegate>(library);
- this.grpcsharp_call_get_peer = GetMethodDelegate<Delegates.grpcsharp_call_get_peer_delegate>(library);
- this.grpcsharp_call_destroy = GetMethodDelegate<Delegates.grpcsharp_call_destroy_delegate>(library);
-
- this.grpcsharp_channel_args_create = GetMethodDelegate<Delegates.grpcsharp_channel_args_create_delegate>(library);
- this.grpcsharp_channel_args_set_string = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_string_delegate>(library);
- this.grpcsharp_channel_args_set_integer = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_integer_delegate>(library);
- this.grpcsharp_channel_args_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_args_destroy_delegate>(library);
-
- this.grpcsharp_override_default_ssl_roots = GetMethodDelegate<Delegates.grpcsharp_override_default_ssl_roots>(library);
- this.grpcsharp_ssl_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_credentials_create_delegate>(library);
- this.grpcsharp_composite_channel_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_channel_credentials_create_delegate>(library);
- this.grpcsharp_channel_credentials_release = GetMethodDelegate<Delegates.grpcsharp_channel_credentials_release_delegate>(library);
-
- this.grpcsharp_insecure_channel_create = GetMethodDelegate<Delegates.grpcsharp_insecure_channel_create_delegate>(library);
- this.grpcsharp_secure_channel_create = GetMethodDelegate<Delegates.grpcsharp_secure_channel_create_delegate>(library);
- this.grpcsharp_channel_create_call = GetMethodDelegate<Delegates.grpcsharp_channel_create_call_delegate>(library);
- this.grpcsharp_channel_check_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_check_connectivity_state_delegate>(library);
- this.grpcsharp_channel_watch_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_watch_connectivity_state_delegate>(library);
- this.grpcsharp_channel_get_target = GetMethodDelegate<Delegates.grpcsharp_channel_get_target_delegate>(library);
- this.grpcsharp_channel_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_destroy_delegate>(library);
-
- this.grpcsharp_sizeof_grpc_event = GetMethodDelegate<Delegates.grpcsharp_sizeof_grpc_event_delegate>(library);
-
- this.grpcsharp_completion_queue_create = GetMethodDelegate<Delegates.grpcsharp_completion_queue_create_delegate>(library);
- this.grpcsharp_completion_queue_shutdown = GetMethodDelegate<Delegates.grpcsharp_completion_queue_shutdown_delegate>(library);
- this.grpcsharp_completion_queue_next = GetMethodDelegate<Delegates.grpcsharp_completion_queue_next_delegate>(library);
- this.grpcsharp_completion_queue_pluck = GetMethodDelegate<Delegates.grpcsharp_completion_queue_pluck_delegate>(library);
- this.grpcsharp_completion_queue_destroy = GetMethodDelegate<Delegates.grpcsharp_completion_queue_destroy_delegate>(library);
-
- this.gprsharp_free = GetMethodDelegate<Delegates.gprsharp_free_delegate>(library);
-
- this.grpcsharp_metadata_array_create = GetMethodDelegate<Delegates.grpcsharp_metadata_array_create_delegate>(library);
- this.grpcsharp_metadata_array_add = GetMethodDelegate<Delegates.grpcsharp_metadata_array_add_delegate>(library);
- this.grpcsharp_metadata_array_count = GetMethodDelegate<Delegates.grpcsharp_metadata_array_count_delegate>(library);
- this.grpcsharp_metadata_array_get_key = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_key_delegate>(library);
- this.grpcsharp_metadata_array_get_value = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_delegate>(library);
- this.grpcsharp_metadata_array_get_value_length = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_length_delegate>(library);
- this.grpcsharp_metadata_array_destroy_full = GetMethodDelegate<Delegates.grpcsharp_metadata_array_destroy_full_delegate>(library);
-
- this.grpcsharp_redirect_log = GetMethodDelegate<Delegates.grpcsharp_redirect_log_delegate>(library);
-
- this.grpcsharp_metadata_credentials_create_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate>(library);
- this.grpcsharp_metadata_credentials_notify_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate>(library);
-
- this.grpcsharp_ssl_server_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_server_credentials_create_delegate>(library);
- this.grpcsharp_server_credentials_release = GetMethodDelegate<Delegates.grpcsharp_server_credentials_release_delegate>(library);
-
- this.grpcsharp_server_create = GetMethodDelegate<Delegates.grpcsharp_server_create_delegate>(library);
- this.grpcsharp_server_register_completion_queue = GetMethodDelegate<Delegates.grpcsharp_server_register_completion_queue_delegate>(library);
- this.grpcsharp_server_add_insecure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_insecure_http2_port_delegate>(library);
- this.grpcsharp_server_add_secure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_secure_http2_port_delegate>(library);
- this.grpcsharp_server_start = GetMethodDelegate<Delegates.grpcsharp_server_start_delegate>(library);
- this.grpcsharp_server_request_call = GetMethodDelegate<Delegates.grpcsharp_server_request_call_delegate>(library);
- this.grpcsharp_server_cancel_all_calls = GetMethodDelegate<Delegates.grpcsharp_server_cancel_all_calls_delegate>(library);
- this.grpcsharp_server_shutdown_and_notify_callback = GetMethodDelegate<Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate>(library);
- this.grpcsharp_server_destroy = GetMethodDelegate<Delegates.grpcsharp_server_destroy_delegate>(library);
-
- this.gprsharp_now = GetMethodDelegate<Delegates.gprsharp_now_delegate>(library);
- this.gprsharp_inf_future = GetMethodDelegate<Delegates.gprsharp_inf_future_delegate>(library);
- this.gprsharp_inf_past = GetMethodDelegate<Delegates.gprsharp_inf_past_delegate>(library);
- this.gprsharp_convert_clock_type = GetMethodDelegate<Delegates.gprsharp_convert_clock_type_delegate>(library);
- this.gprsharp_sizeof_timespec = GetMethodDelegate<Delegates.gprsharp_sizeof_timespec_delegate>(library);
-
- this.grpcsharp_test_callback = GetMethodDelegate<Delegates.grpcsharp_test_callback_delegate>(library);
- this.grpcsharp_test_nop = GetMethodDelegate<Delegates.grpcsharp_test_nop_delegate>(library);
- }
- else
- {
- // Windows or fallback
- this.grpcsharp_init = PInvokeMethods.grpcsharp_init;
- this.grpcsharp_shutdown = PInvokeMethods.grpcsharp_shutdown;
- this.grpcsharp_version_string = PInvokeMethods.grpcsharp_version_string;
-
- this.grpcsharp_batch_context_create = PInvokeMethods.grpcsharp_batch_context_create;
- this.grpcsharp_batch_context_recv_initial_metadata = PInvokeMethods.grpcsharp_batch_context_recv_initial_metadata;
- this.grpcsharp_batch_context_recv_message_length = PInvokeMethods.grpcsharp_batch_context_recv_message_length;
- this.grpcsharp_batch_context_recv_message_to_buffer = PInvokeMethods.grpcsharp_batch_context_recv_message_to_buffer;
- this.grpcsharp_batch_context_recv_status_on_client_status = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_status;
- this.grpcsharp_batch_context_recv_status_on_client_details = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_details;
- this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_trailing_metadata;
- this.grpcsharp_batch_context_server_rpc_new_call = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_call;
- this.grpcsharp_batch_context_server_rpc_new_method = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_method;
- this.grpcsharp_batch_context_server_rpc_new_host = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_host;
- this.grpcsharp_batch_context_server_rpc_new_deadline = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_deadline;
- this.grpcsharp_batch_context_server_rpc_new_request_metadata = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_request_metadata;
- this.grpcsharp_batch_context_recv_close_on_server_cancelled = PInvokeMethods.grpcsharp_batch_context_recv_close_on_server_cancelled;
- this.grpcsharp_batch_context_destroy = PInvokeMethods.grpcsharp_batch_context_destroy;
-
- this.grpcsharp_composite_call_credentials_create = PInvokeMethods.grpcsharp_composite_call_credentials_create;
- this.grpcsharp_call_credentials_release = PInvokeMethods.grpcsharp_call_credentials_release;
-
- this.grpcsharp_call_cancel = PInvokeMethods.grpcsharp_call_cancel;
- this.grpcsharp_call_cancel_with_status = PInvokeMethods.grpcsharp_call_cancel_with_status;
- this.grpcsharp_call_start_unary = PInvokeMethods.grpcsharp_call_start_unary;
- this.grpcsharp_call_start_client_streaming = PInvokeMethods.grpcsharp_call_start_client_streaming;
- this.grpcsharp_call_start_server_streaming = PInvokeMethods.grpcsharp_call_start_server_streaming;
- this.grpcsharp_call_start_duplex_streaming = PInvokeMethods.grpcsharp_call_start_duplex_streaming;
- this.grpcsharp_call_send_message = PInvokeMethods.grpcsharp_call_send_message;
- this.grpcsharp_call_send_close_from_client = PInvokeMethods.grpcsharp_call_send_close_from_client;
- this.grpcsharp_call_send_status_from_server = PInvokeMethods.grpcsharp_call_send_status_from_server;
- this.grpcsharp_call_recv_message = PInvokeMethods.grpcsharp_call_recv_message;
- this.grpcsharp_call_recv_initial_metadata = PInvokeMethods.grpcsharp_call_recv_initial_metadata;
- this.grpcsharp_call_start_serverside = PInvokeMethods.grpcsharp_call_start_serverside;
- this.grpcsharp_call_send_initial_metadata = PInvokeMethods.grpcsharp_call_send_initial_metadata;
- this.grpcsharp_call_set_credentials = PInvokeMethods.grpcsharp_call_set_credentials;
- this.grpcsharp_call_get_peer = PInvokeMethods.grpcsharp_call_get_peer;
- this.grpcsharp_call_destroy = PInvokeMethods.grpcsharp_call_destroy;
-
- this.grpcsharp_channel_args_create = PInvokeMethods.grpcsharp_channel_args_create;
- this.grpcsharp_channel_args_set_string = PInvokeMethods.grpcsharp_channel_args_set_string;
- this.grpcsharp_channel_args_set_integer = PInvokeMethods.grpcsharp_channel_args_set_integer;
- this.grpcsharp_channel_args_destroy = PInvokeMethods.grpcsharp_channel_args_destroy;
-
- this.grpcsharp_override_default_ssl_roots = PInvokeMethods.grpcsharp_override_default_ssl_roots;
- this.grpcsharp_ssl_credentials_create = PInvokeMethods.grpcsharp_ssl_credentials_create;
- this.grpcsharp_composite_channel_credentials_create = PInvokeMethods.grpcsharp_composite_channel_credentials_create;
- this.grpcsharp_channel_credentials_release = PInvokeMethods.grpcsharp_channel_credentials_release;
-
- this.grpcsharp_insecure_channel_create = PInvokeMethods.grpcsharp_insecure_channel_create;
- this.grpcsharp_secure_channel_create = PInvokeMethods.grpcsharp_secure_channel_create;
- this.grpcsharp_channel_create_call = PInvokeMethods.grpcsharp_channel_create_call;
- this.grpcsharp_channel_check_connectivity_state = PInvokeMethods.grpcsharp_channel_check_connectivity_state;
- this.grpcsharp_channel_watch_connectivity_state = PInvokeMethods.grpcsharp_channel_watch_connectivity_state;
- this.grpcsharp_channel_get_target = PInvokeMethods.grpcsharp_channel_get_target;
- this.grpcsharp_channel_destroy = PInvokeMethods.grpcsharp_channel_destroy;
-
- this.grpcsharp_sizeof_grpc_event = PInvokeMethods.grpcsharp_sizeof_grpc_event;
-
- this.grpcsharp_completion_queue_create = PInvokeMethods.grpcsharp_completion_queue_create;
- this.grpcsharp_completion_queue_shutdown = PInvokeMethods.grpcsharp_completion_queue_shutdown;
- this.grpcsharp_completion_queue_next = PInvokeMethods.grpcsharp_completion_queue_next;
- this.grpcsharp_completion_queue_pluck = PInvokeMethods.grpcsharp_completion_queue_pluck;
- this.grpcsharp_completion_queue_destroy = PInvokeMethods.grpcsharp_completion_queue_destroy;
-
- this.gprsharp_free = PInvokeMethods.gprsharp_free;
-
- this.grpcsharp_metadata_array_create = PInvokeMethods.grpcsharp_metadata_array_create;
- this.grpcsharp_metadata_array_add = PInvokeMethods.grpcsharp_metadata_array_add;
- this.grpcsharp_metadata_array_count = PInvokeMethods.grpcsharp_metadata_array_count;
- this.grpcsharp_metadata_array_get_key = PInvokeMethods.grpcsharp_metadata_array_get_key;
- this.grpcsharp_metadata_array_get_value = PInvokeMethods.grpcsharp_metadata_array_get_value;
- this.grpcsharp_metadata_array_get_value_length = PInvokeMethods.grpcsharp_metadata_array_get_value_length;
- this.grpcsharp_metadata_array_destroy_full = PInvokeMethods.grpcsharp_metadata_array_destroy_full;
-
- this.grpcsharp_redirect_log = PInvokeMethods.grpcsharp_redirect_log;
-
- this.grpcsharp_metadata_credentials_create_from_plugin = PInvokeMethods.grpcsharp_metadata_credentials_create_from_plugin;
- this.grpcsharp_metadata_credentials_notify_from_plugin = PInvokeMethods.grpcsharp_metadata_credentials_notify_from_plugin;
-
- this.grpcsharp_ssl_server_credentials_create = PInvokeMethods.grpcsharp_ssl_server_credentials_create;
- this.grpcsharp_server_credentials_release = PInvokeMethods.grpcsharp_server_credentials_release;
-
- this.grpcsharp_server_create = PInvokeMethods.grpcsharp_server_create;
- this.grpcsharp_server_register_completion_queue = PInvokeMethods.grpcsharp_server_register_completion_queue;
- this.grpcsharp_server_add_insecure_http2_port = PInvokeMethods.grpcsharp_server_add_insecure_http2_port;
- this.grpcsharp_server_add_secure_http2_port = PInvokeMethods.grpcsharp_server_add_secure_http2_port;
- this.grpcsharp_server_start = PInvokeMethods.grpcsharp_server_start;
- this.grpcsharp_server_request_call = PInvokeMethods.grpcsharp_server_request_call;
- this.grpcsharp_server_cancel_all_calls = PInvokeMethods.grpcsharp_server_cancel_all_calls;
- this.grpcsharp_server_shutdown_and_notify_callback = PInvokeMethods.grpcsharp_server_shutdown_and_notify_callback;
- this.grpcsharp_server_destroy = PInvokeMethods.grpcsharp_server_destroy;
-
- this.gprsharp_now = PInvokeMethods.gprsharp_now;
- this.gprsharp_inf_future = PInvokeMethods.gprsharp_inf_future;
- this.gprsharp_inf_past = PInvokeMethods.gprsharp_inf_past;
- this.gprsharp_convert_clock_type = PInvokeMethods.gprsharp_convert_clock_type;
- this.gprsharp_sizeof_timespec = PInvokeMethods.gprsharp_sizeof_timespec;
-
- this.grpcsharp_test_callback = PInvokeMethods.grpcsharp_test_callback;
- this.grpcsharp_test_nop = PInvokeMethods.grpcsharp_test_nop;
- }
+ this.grpcsharp_init = GetMethodDelegate<Delegates.grpcsharp_init_delegate>(library);
+ this.grpcsharp_shutdown = GetMethodDelegate<Delegates.grpcsharp_shutdown_delegate>(library);
+ this.grpcsharp_version_string = GetMethodDelegate<Delegates.grpcsharp_version_string_delegate>(library);
+
+ this.grpcsharp_batch_context_create = GetMethodDelegate<Delegates.grpcsharp_batch_context_create_delegate>(library);
+ this.grpcsharp_batch_context_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_initial_metadata_delegate>(library);
+ this.grpcsharp_batch_context_recv_message_length = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_length_delegate>(library);
+ this.grpcsharp_batch_context_recv_message_to_buffer = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_to_buffer_delegate>(library);
+ this.grpcsharp_batch_context_recv_status_on_client_status = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate>(library);
+ this.grpcsharp_batch_context_recv_status_on_client_details = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate>(library);
+ this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate>(library);
+ this.grpcsharp_batch_context_server_rpc_new_call = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_call_delegate>(library);
+ this.grpcsharp_batch_context_server_rpc_new_method = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_method_delegate>(library);
+ this.grpcsharp_batch_context_server_rpc_new_host = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_host_delegate>(library);
+ this.grpcsharp_batch_context_server_rpc_new_deadline = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_deadline_delegate>(library);
+ this.grpcsharp_batch_context_server_rpc_new_request_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_request_metadata_delegate>(library);
+ this.grpcsharp_batch_context_recv_close_on_server_cancelled = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate>(library);
+ this.grpcsharp_batch_context_destroy = GetMethodDelegate<Delegates.grpcsharp_batch_context_destroy_delegate>(library);
+
+ this.grpcsharp_composite_call_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_call_credentials_create_delegate>(library);
+ this.grpcsharp_call_credentials_release = GetMethodDelegate<Delegates.grpcsharp_call_credentials_release_delegate>(library);
+
+ this.grpcsharp_call_cancel = GetMethodDelegate<Delegates.grpcsharp_call_cancel_delegate>(library);
+ this.grpcsharp_call_cancel_with_status = GetMethodDelegate<Delegates.grpcsharp_call_cancel_with_status_delegate>(library);
+ this.grpcsharp_call_start_unary = GetMethodDelegate<Delegates.grpcsharp_call_start_unary_delegate>(library);
+ this.grpcsharp_call_start_client_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_client_streaming_delegate>(library);
+ this.grpcsharp_call_start_server_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_server_streaming_delegate>(library);
+ this.grpcsharp_call_start_duplex_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_duplex_streaming_delegate>(library);
+ this.grpcsharp_call_send_message = GetMethodDelegate<Delegates.grpcsharp_call_send_message_delegate>(library);
+ this.grpcsharp_call_send_close_from_client = GetMethodDelegate<Delegates.grpcsharp_call_send_close_from_client_delegate>(library);
+ this.grpcsharp_call_send_status_from_server = GetMethodDelegate<Delegates.grpcsharp_call_send_status_from_server_delegate>(library);
+ this.grpcsharp_call_recv_message = GetMethodDelegate<Delegates.grpcsharp_call_recv_message_delegate>(library);
+ this.grpcsharp_call_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_recv_initial_metadata_delegate>(library);
+ this.grpcsharp_call_start_serverside = GetMethodDelegate<Delegates.grpcsharp_call_start_serverside_delegate>(library);
+ this.grpcsharp_call_send_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_send_initial_metadata_delegate>(library);
+ this.grpcsharp_call_set_credentials = GetMethodDelegate<Delegates.grpcsharp_call_set_credentials_delegate>(library);
+ this.grpcsharp_call_get_peer = GetMethodDelegate<Delegates.grpcsharp_call_get_peer_delegate>(library);
+ this.grpcsharp_call_destroy = GetMethodDelegate<Delegates.grpcsharp_call_destroy_delegate>(library);
+
+ this.grpcsharp_channel_args_create = GetMethodDelegate<Delegates.grpcsharp_channel_args_create_delegate>(library);
+ this.grpcsharp_channel_args_set_string = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_string_delegate>(library);
+ this.grpcsharp_channel_args_set_integer = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_integer_delegate>(library);
+ this.grpcsharp_channel_args_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_args_destroy_delegate>(library);
+
+ this.grpcsharp_override_default_ssl_roots = GetMethodDelegate<Delegates.grpcsharp_override_default_ssl_roots>(library);
+ this.grpcsharp_ssl_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_credentials_create_delegate>(library);
+ this.grpcsharp_composite_channel_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_channel_credentials_create_delegate>(library);
+ this.grpcsharp_channel_credentials_release = GetMethodDelegate<Delegates.grpcsharp_channel_credentials_release_delegate>(library);
+
+ this.grpcsharp_insecure_channel_create = GetMethodDelegate<Delegates.grpcsharp_insecure_channel_create_delegate>(library);
+ this.grpcsharp_secure_channel_create = GetMethodDelegate<Delegates.grpcsharp_secure_channel_create_delegate>(library);
+ this.grpcsharp_channel_create_call = GetMethodDelegate<Delegates.grpcsharp_channel_create_call_delegate>(library);
+ this.grpcsharp_channel_check_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_check_connectivity_state_delegate>(library);
+ this.grpcsharp_channel_watch_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_watch_connectivity_state_delegate>(library);
+ this.grpcsharp_channel_get_target = GetMethodDelegate<Delegates.grpcsharp_channel_get_target_delegate>(library);
+ this.grpcsharp_channel_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_destroy_delegate>(library);
+
+ this.grpcsharp_sizeof_grpc_event = GetMethodDelegate<Delegates.grpcsharp_sizeof_grpc_event_delegate>(library);
+
+ this.grpcsharp_completion_queue_create = GetMethodDelegate<Delegates.grpcsharp_completion_queue_create_delegate>(library);
+ this.grpcsharp_completion_queue_shutdown = GetMethodDelegate<Delegates.grpcsharp_completion_queue_shutdown_delegate>(library);
+ this.grpcsharp_completion_queue_next = GetMethodDelegate<Delegates.grpcsharp_completion_queue_next_delegate>(library);
+ this.grpcsharp_completion_queue_pluck = GetMethodDelegate<Delegates.grpcsharp_completion_queue_pluck_delegate>(library);
+ this.grpcsharp_completion_queue_destroy = GetMethodDelegate<Delegates.grpcsharp_completion_queue_destroy_delegate>(library);
+
+ this.gprsharp_free = GetMethodDelegate<Delegates.gprsharp_free_delegate>(library);
+
+ this.grpcsharp_metadata_array_create = GetMethodDelegate<Delegates.grpcsharp_metadata_array_create_delegate>(library);
+ this.grpcsharp_metadata_array_add = GetMethodDelegate<Delegates.grpcsharp_metadata_array_add_delegate>(library);
+ this.grpcsharp_metadata_array_count = GetMethodDelegate<Delegates.grpcsharp_metadata_array_count_delegate>(library);
+ this.grpcsharp_metadata_array_get_key = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_key_delegate>(library);
+ this.grpcsharp_metadata_array_get_value = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_delegate>(library);
+ this.grpcsharp_metadata_array_get_value_length = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_length_delegate>(library);
+ this.grpcsharp_metadata_array_destroy_full = GetMethodDelegate<Delegates.grpcsharp_metadata_array_destroy_full_delegate>(library);
+
+ this.grpcsharp_redirect_log = GetMethodDelegate<Delegates.grpcsharp_redirect_log_delegate>(library);
+
+ this.grpcsharp_metadata_credentials_create_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate>(library);
+ this.grpcsharp_metadata_credentials_notify_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate>(library);
+
+ this.grpcsharp_ssl_server_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_server_credentials_create_delegate>(library);
+ this.grpcsharp_server_credentials_release = GetMethodDelegate<Delegates.grpcsharp_server_credentials_release_delegate>(library);
+
+ this.grpcsharp_server_create = GetMethodDelegate<Delegates.grpcsharp_server_create_delegate>(library);
+ this.grpcsharp_server_register_completion_queue = GetMethodDelegate<Delegates.grpcsharp_server_register_completion_queue_delegate>(library);
+ this.grpcsharp_server_add_insecure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_insecure_http2_port_delegate>(library);
+ this.grpcsharp_server_add_secure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_secure_http2_port_delegate>(library);
+ this.grpcsharp_server_start = GetMethodDelegate<Delegates.grpcsharp_server_start_delegate>(library);
+ this.grpcsharp_server_request_call = GetMethodDelegate<Delegates.grpcsharp_server_request_call_delegate>(library);
+ this.grpcsharp_server_cancel_all_calls = GetMethodDelegate<Delegates.grpcsharp_server_cancel_all_calls_delegate>(library);
+ this.grpcsharp_server_shutdown_and_notify_callback = GetMethodDelegate<Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate>(library);
+ this.grpcsharp_server_destroy = GetMethodDelegate<Delegates.grpcsharp_server_destroy_delegate>(library);
+
+ this.gprsharp_now = GetMethodDelegate<Delegates.gprsharp_now_delegate>(library);
+ this.gprsharp_inf_future = GetMethodDelegate<Delegates.gprsharp_inf_future_delegate>(library);
+ this.gprsharp_inf_past = GetMethodDelegate<Delegates.gprsharp_inf_past_delegate>(library);
+ this.gprsharp_convert_clock_type = GetMethodDelegate<Delegates.gprsharp_convert_clock_type_delegate>(library);
+ this.gprsharp_sizeof_timespec = GetMethodDelegate<Delegates.gprsharp_sizeof_timespec_delegate>(library);
+
+ this.grpcsharp_test_callback = GetMethodDelegate<Delegates.grpcsharp_test_callback_delegate>(library);
+ this.grpcsharp_test_nop = GetMethodDelegate<Delegates.grpcsharp_test_nop_delegate>(library);
}
/// <summary>
@@ -516,317 +408,5 @@ namespace Grpc.Core.Internal
public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback);
public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr);
}
-
- /// <summary>
- /// Default PInvoke bindings for native methods that are used on Windows.
- /// Alternatively, they can also be used as a fallback on Mono
- /// (if libgrpc_csharp_ext is installed on your system, or is made accessible through e.g. LD_LIBRARY_PATH environment variable
- /// or using Mono's dllMap feature).
- /// </summary>
- private class PInvokeMethods
- {
- // Environment
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_init();
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_shutdown();
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern IntPtr grpcsharp_version_string(); // returns not-owned const char*
-
- // BatchContextSafeHandle
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern BatchContextSafeHandle grpcsharp_batch_context_create();
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_batch_context_recv_message_to_buffer(BatchContextSafeHandle ctx, byte[] buffer, UIntPtr bufferLen);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx); // returns const char*
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallSafeHandle grpcsharp_batch_context_server_rpc_new_call(BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern IntPtr grpcsharp_batch_context_server_rpc_new_method(BatchContextSafeHandle ctx); // returns const char*
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern IntPtr grpcsharp_batch_context_server_rpc_new_host(BatchContextSafeHandle ctx); // returns const char*
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern Timespec grpcsharp_batch_context_server_rpc_new_deadline(BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern IntPtr grpcsharp_batch_context_server_rpc_new_request_metadata(BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_batch_context_destroy(IntPtr ctx);
-
- // CallCredentialsSafeHandle
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_call_credentials_release(IntPtr credentials);
-
- // CallSafeHandle
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_cancel(CallSafeHandle call);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call,
- BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call,
- BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call,
- BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen,
- MetadataArraySafeHandle metadataArray, WriteFlags writeFlags);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call,
- BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_send_message(CallSafeHandle call,
- BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call,
- BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call,
- BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata,
- byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call,
- BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call,
- BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call,
- BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call,
- BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_call_destroy(IntPtr call);
-
- // ChannelArgsSafeHandle
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs);
-
- [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
- public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value);
-
- [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
- public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_channel_args_destroy(IntPtr args);
-
- // ChannelCredentialsSafeHandle
-
- [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
- public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts);
-
- [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
- public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_channel_credentials_release(IntPtr credentials);
-
- // ChannelSafeHandle
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState,
- Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_channel_destroy(IntPtr channel);
-
- // CompletionQueueEvent
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern int grpcsharp_sizeof_grpc_event();
-
- // CompletionQueueSafeHandle
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create();
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_completion_queue_destroy(IntPtr cq);
-
- // CStringSafeHandle
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void gprsharp_free(IntPtr ptr);
-
- // MetadataArraySafeHandle
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity);
-
- [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
- public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern UIntPtr grpcsharp_metadata_array_get_value_length(IntPtr metadataArray, UIntPtr index);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array);
-
- // NativeLogRedirector
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_redirect_log(GprLogDelegate callback);
-
- // NativeMetadataCredentialsPlugin
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor);
-
- [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
- public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails);
-
- // ServerCredentialsSafeHandle
-
- [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
- public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, bool forceClientAuth);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_server_credentials_release(IntPtr credentials);
-
- // ServerSafeHandle
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_server_start(ServerSafeHandle server);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern void grpcsharp_server_destroy(IntPtr server);
-
- // Timespec
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern Timespec gprsharp_now(ClockType clockType);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern Timespec gprsharp_inf_future(ClockType clockType);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern Timespec gprsharp_inf_past(ClockType clockType);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern int gprsharp_sizeof_timespec();
-
- // Testing
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback);
-
- [DllImport("grpc_csharp_ext.dll")]
- public static extern IntPtr grpcsharp_test_nop(IntPtr ptr);
- }
}
}
diff --git a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs
index 5a80746101..dc629bd714 100644
--- a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs
+++ b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs
@@ -82,6 +82,32 @@ namespace Grpc.Core.Internal
/// <returns></returns>
public IntPtr LoadSymbol(string symbolName)
{
+ if (PlatformApis.IsWindows)
+ {
+ // See http://stackoverflow.com/questions/10473310 for background on this.
+ if (PlatformApis.Is64Bit)
+ {
+ return Windows.GetProcAddress(this.handle, symbolName);
+ }
+ else
+ {
+ // Yes, we could potentially predict the size... but it's a lot simpler to just try
+ // all the candidates. Most functions have a suffix of @0, @4 or @8 so we won't be trying
+ // many options - and if it takes a little bit longer to fail if we've really got the wrong
+ // library, that's not a big problem. This is only called once per function in the native library.
+ symbolName = "_" + symbolName + "@";
+ for (int stackSize = 0; stackSize < 128; stackSize += 4)
+ {
+ IntPtr candidate = Windows.GetProcAddress(this.handle, symbolName + stackSize);
+ if (candidate != IntPtr.Zero)
+ {
+ return candidate;
+ }
+ }
+ // Fail.
+ return IntPtr.Zero;
+ }
+ }
if (PlatformApis.IsLinux)
{
if (PlatformApis.IsMono)
@@ -142,13 +168,18 @@ namespace Grpc.Core.Internal
return path;
}
}
- throw new FileNotFoundException(String.Format("Error loading native library. Not found in any of the possible locations {0}", libraryPathAlternatives));
+ throw new FileNotFoundException(
+ String.Format("Error loading native library. Not found in any of the possible locations: {0}",
+ string.Join(",", libraryPathAlternatives)));
}
private static class Windows
{
[DllImport("kernel32.dll")]
internal static extern IntPtr LoadLibrary(string filename);
+
+ [DllImport("kernel32.dll")]
+ internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
}
private static class Linux
diff --git a/src/csharp/Grpc.Core/NativeDeps.Linux.targets b/src/csharp/Grpc.Core/NativeDeps.Linux.targets
index a3848c6f2e..e0c9132b1d 100644
--- a/src/csharp/Grpc.Core/NativeDeps.Linux.targets
+++ b/src/csharp/Grpc.Core/NativeDeps.Linux.targets
@@ -3,7 +3,7 @@
<ItemGroup>
<Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.so">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- <Link>nativelibs\linux_x64\libgrpc_csharp_ext.so</Link>
+ <Link>libgrpc_csharp_ext.x64.so</Link>
</Content>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/NativeDeps.Mac.targets b/src/csharp/Grpc.Core/NativeDeps.Mac.targets
index c3c6264fd3..e22c7384fc 100644
--- a/src/csharp/Grpc.Core/NativeDeps.Mac.targets
+++ b/src/csharp/Grpc.Core/NativeDeps.Mac.targets
@@ -3,7 +3,7 @@
<ItemGroup>
<Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- <Link>nativelibs\macosx_x86\libgrpc_csharp_ext.dylib</Link>
+ <Link>libgrpc_csharp_ext.x86.dylib</Link>
</Content>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/NativeDeps.Windows.targets b/src/csharp/Grpc.Core/NativeDeps.Windows.targets
index f6a3405e29..93db0935bc 100644
--- a/src/csharp/Grpc.Core/NativeDeps.Windows.targets
+++ b/src/csharp/Grpc.Core/NativeDeps.Windows.targets
@@ -3,7 +3,7 @@
<ItemGroup>
<Content Include="..\..\..\vsprojects\$(NativeDependenciesConfiguration)\grpc_csharp_ext.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- <Link>nativelibs\windows_x86\grpc_csharp_ext.dll</Link>
+ <Link>grpc_csharp_ext.x86.dll</Link>
</Content>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/packages.config b/src/csharp/Grpc.Core/packages.config
index 80daf048d0..6514774021 100644
--- a/src/csharp/Grpc.Core/packages.config
+++ b/src/csharp/Grpc.Core/packages.config
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
+ <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/project.json b/src/csharp/Grpc.Core/project.json
index 4545d26aa5..f7e21a25dd 100644
--- a/src/csharp/Grpc.Core/project.json
+++ b/src/csharp/Grpc.Core/project.json
@@ -14,12 +14,12 @@
"files": {
"mappings": {
"build/net45/": "Grpc.Core.targets",
- "build/native/bin/windows_x86/": "../nativelibs/windows_x86/grpc_csharp_ext.dll",
- "build/native/bin/windows_x64/": "../nativelibs/windows_x64/grpc_csharp_ext.dll",
- "build/native/bin/linux_x86/": "../nativelibs/linux_x86/libgrpc_csharp_ext.so",
- "build/native/bin/linux_x64/": "../nativelibs/linux_x64/libgrpc_csharp_ext.so",
- "build/native/bin/macosx_x86/": "../nativelibs/macosx_x86/libgrpc_csharp_ext.dylib",
- "build/native/bin/macosx_x64/": "../nativelibs/macosx_x64/libgrpc_csharp_ext.dylib"
+ "runtimes/win/native/grpc_csharp_ext.x86.dll": "../nativelibs/windows_x86/grpc_csharp_ext.dll",
+ "runtimes/win/native/grpc_csharp_ext.x64.dll": "../nativelibs/windows_x64/grpc_csharp_ext.dll",
+ "runtimes/linux/native/libgrpc_csharp_ext.x86.so": "../nativelibs/linux_x86/libgrpc_csharp_ext.so",
+ "runtimes/linux/native/libgrpc_csharp_ext.x64.so": "../nativelibs/linux_x64/libgrpc_csharp_ext.so",
+ "runtimes/osx/native/libgrpc_csharp_ext.x86.dylib": "../nativelibs/macosx_x86/libgrpc_csharp_ext.dylib",
+ "runtimes/osx/native/libgrpc_csharp_ext.x64.dylib": "../nativelibs/macosx_x64/libgrpc_csharp_ext.dylib"
}
}
},
@@ -31,7 +31,7 @@
"xmlDoc": true
},
"dependencies": {
- "Ix-Async": "1.2.5"
+ "System.Interactive.Async": "3.0.0"
},
"frameworks": {
"net45": { },
@@ -40,8 +40,8 @@
"portable-net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027",
- "System.Threading.Thread": "4.0.0-rc2-24027"
+ "NETStandard.Library": "1.6.0",
+ "System.Threading.Thread": "4.0.0"
}
}
}
diff --git a/src/csharp/Grpc.Examples.MathClient/packages.config b/src/csharp/Grpc.Examples.MathClient/packages.config
new file mode 100644
index 0000000000..79ece06bef
--- /dev/null
+++ b/src/csharp/Grpc.Examples.MathClient/packages.config
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+</packages>
diff --git a/src/csharp/Grpc.Examples.MathClient/project.json b/src/csharp/Grpc.Examples.MathClient/project.json
index b865cd5011..ad319478ab 100644
--- a/src/csharp/Grpc.Examples.MathClient/project.json
+++ b/src/csharp/Grpc.Examples.MathClient/project.json
@@ -14,10 +14,10 @@
},
"copyToOutput": {
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
@@ -33,10 +33,10 @@
},
"copyToOutput": {
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
@@ -55,12 +55,13 @@
},
"frameworks": {
"net45": { },
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027"
+ "Microsoft.NETCore.App": "1.0.0",
+ "NETStandard.Library": "1.6.0"
}
}
}
diff --git a/src/csharp/Grpc.Examples.MathServer/packages.config b/src/csharp/Grpc.Examples.MathServer/packages.config
new file mode 100644
index 0000000000..79ece06bef
--- /dev/null
+++ b/src/csharp/Grpc.Examples.MathServer/packages.config
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+</packages>
diff --git a/src/csharp/Grpc.Examples.MathServer/project.json b/src/csharp/Grpc.Examples.MathServer/project.json
index b865cd5011..ad319478ab 100644
--- a/src/csharp/Grpc.Examples.MathServer/project.json
+++ b/src/csharp/Grpc.Examples.MathServer/project.json
@@ -14,10 +14,10 @@
},
"copyToOutput": {
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
@@ -33,10 +33,10 @@
},
"copyToOutput": {
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
@@ -55,12 +55,13 @@
},
"frameworks": {
"net45": { },
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027"
+ "Microsoft.NETCore.App": "1.0.0",
+ "NETStandard.Library": "1.6.0"
}
}
}
diff --git a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
index 4c7d89309a..c8801a9413 100644
--- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
+++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
@@ -43,7 +43,7 @@
<HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System.Interactive.Async">
- <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
+ <HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="nunitlite">
<HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
@@ -75,4 +75,4 @@
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/csharp/Grpc.Examples.Tests/NUnitMain.cs b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs
index 1a522cab93..7ba1074d44 100644
--- a/src/csharp/Grpc.Examples.Tests/NUnitMain.cs
+++ b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs
@@ -49,7 +49,7 @@ namespace Grpc.Examples.Tests
{
// Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
-#if NETSTANDARD1_5
+#if NETCOREAPP1_0
return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
#else
return new AutoRun().Execute(args);
diff --git a/src/csharp/Grpc.Examples.Tests/packages.config b/src/csharp/Grpc.Examples.Tests/packages.config
index 668601af8e..cc473eb34c 100644
--- a/src/csharp/Grpc.Examples.Tests/packages.config
+++ b/src/csharp/Grpc.Examples.Tests/packages.config
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
- <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
+ <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
<package id="NUnit" version="3.2.0" targetFramework="net45" />
<package id="NUnitLite" version="3.2.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Examples.Tests/project.json b/src/csharp/Grpc.Examples.Tests/project.json
index cc518eb6ff..1cd1848e99 100644
--- a/src/csharp/Grpc.Examples.Tests/project.json
+++ b/src/csharp/Grpc.Examples.Tests/project.json
@@ -14,10 +14,10 @@
},
"copyToOutput": {
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
@@ -33,10 +33,10 @@
},
"copyToOutput": {
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
@@ -57,12 +57,13 @@
},
"frameworks": {
"net45": { },
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027"
+ "Microsoft.NETCore.App": "1.0.0",
+ "NETStandard.Library": "1.6.0"
}
}
}
diff --git a/src/csharp/Grpc.Examples/Grpc.Examples.csproj b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
index 3dfa84e896..4521649b6f 100644
--- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj
+++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
@@ -48,7 +48,7 @@
<Reference Include="System.Data.Linq" />
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
+ <HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -72,4 +72,4 @@
<None Include="Grpc.Examples.project.json" />
<None Include="packages.config" />
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/csharp/Grpc.Examples/packages.config b/src/csharp/Grpc.Examples/packages.config
index a70dcbd4c6..8985ae4c77 100644
--- a/src/csharp/Grpc.Examples/packages.config
+++ b/src/csharp/Grpc.Examples/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
- <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
+ <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
<package id="NUnit" version="3.2.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Examples/project.json b/src/csharp/Grpc.Examples/project.json
index 7d3f4dcbb1..98bd5d852c 100644
--- a/src/csharp/Grpc.Examples/project.json
+++ b/src/csharp/Grpc.Examples/project.json
@@ -1,6 +1,11 @@
{
"buildOptions": {
},
+ "runtimes": {
+ "win7-x64": { },
+ "debian.8-x64": { },
+ "osx.10.11-x64": { }
+ },
"dependencies": {
"Grpc.Core": {
@@ -15,12 +20,13 @@
"System.IO": ""
}
},
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027"
+ "Microsoft.NETCore.App": "1.0.0",
+ "NETStandard.Library": "1.6.0"
}
}
}
diff --git a/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs
index 44634671ce..dca61e3f96 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs
+++ b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs
@@ -49,7 +49,7 @@ namespace Grpc.HealthCheck.Tests
{
// Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
-#if NETSTANDARD1_5
+#if NETCOREAPP1_0
return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
#else
return new AutoRun().Execute(args);
diff --git a/src/csharp/Grpc.HealthCheck.Tests/project.json b/src/csharp/Grpc.HealthCheck.Tests/project.json
index fbf8d92f04..faa4400304 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/project.json
+++ b/src/csharp/Grpc.HealthCheck.Tests/project.json
@@ -14,10 +14,10 @@
},
"copyToOutput": {
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
@@ -33,10 +33,10 @@
},
"copyToOutput": {
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
@@ -57,12 +57,13 @@
},
"frameworks": {
"net45": { },
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027"
+ "Microsoft.NETCore.App": "1.0.0",
+ "NETStandard.Library": "1.6.0"
}
}
}
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
index 7db8b2d38e..e13416cc1a 100644
--- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
@@ -46,7 +46,7 @@
<Reference Include="System.Core" />
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
+ <HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -82,4 +82,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
index 7b3b391009..4ffd18ccb2 100644
--- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
@@ -16,7 +16,7 @@
<dependencies>
<dependency id="Google.Protobuf" version="$ProtobufVersion$" />
<dependency id="Grpc.Core" version="$version$" />
- <dependency id="Ix-Async" version="1.2.3" />
+ <dependency id="System.Interactive.Async" version="3.0.0" />
</dependencies>
</metadata>
<files>
diff --git a/src/csharp/Grpc.HealthCheck/packages.config b/src/csharp/Grpc.HealthCheck/packages.config
index a52d9e508f..063094f775 100644
--- a/src/csharp/Grpc.HealthCheck/packages.config
+++ b/src/csharp/Grpc.HealthCheck/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
- <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
+ <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck/project.json b/src/csharp/Grpc.HealthCheck/project.json
index 0e03e89d6a..7c062a7e40 100644
--- a/src/csharp/Grpc.HealthCheck/project.json
+++ b/src/csharp/Grpc.HealthCheck/project.json
@@ -37,7 +37,7 @@
"portable-net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027"
+ "NETStandard.Library": "1.6.0"
}
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
index 91fb3ce5bc..6816b5c5a2 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
@@ -39,30 +39,25 @@
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
- <Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="System" />
+ <Reference Include="System.Net" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Net.Http.WebRequest" />
+ <Reference Include="BouncyCastle.Crypto">
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
+ <Reference Include="Newtonsoft.Json">
+ <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ <Reference Include="Google.Apis.Core">
+ <HintPath>..\packages\Google.Apis.Core.1.15.0\lib\net45\Google.Apis.Core.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Core, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
+ <Reference Include="Google.Apis.Auth">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.dll</HintPath>
</Reference>
- <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+ <Reference Include="Google.Apis.Auth.PlatformServices">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
- <Reference Include="System" />
- <Reference Include="System.Net" />
- <Reference Include="System.Net.Http" />
- <Reference Include="System.Net.Http.WebRequest" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/packages.config b/src/csharp/Grpc.IntegrationTesting.Client/packages.config
index c20d9ceed6..738d3e6f3b 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting.Client/packages.config
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.11.1" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.11.1" targetFramework="net45" />
+ <package id="Google.Apis.Auth" version="1.15.0" targetFramework="net45" />
+ <package id="Google.Apis.Core" version="1.15.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/project.json b/src/csharp/Grpc.IntegrationTesting.Client/project.json
index 4a2846feea..287950720f 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.Client/project.json
@@ -15,10 +15,10 @@
"copyToOutput": {
"include": "data/*",
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
@@ -35,10 +35,10 @@
"copyToOutput": {
"include": "data/*",
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
@@ -57,13 +57,14 @@
},
"frameworks": {
"net45": { },
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45",
"net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027"
+ "Microsoft.NETCore.App": "1.0.0",
+ "NETStandard.Library": "1.6.0"
}
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj
index dda26a6892..593bf0939d 100644
--- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj
@@ -58,7 +58,6 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
- <None Include="app.config" />
<None Include="Grpc.IntegrationTesting.QpsWorker.project.json" />
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config b/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config
deleted file mode 100644
index e204447bb3..0000000000
--- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
- <runtime>
- <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
- <dependentAssembly>
- <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="Google.Apis.Core" publicKeyToken="4b01fa6e34db77ab" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-1.11.1.0" newVersion="1.11.1.0" />
- </dependentAssembly>
- </assemblyBinding>
- </runtime>
-</configuration> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/packages.config b/src/csharp/Grpc.IntegrationTesting.QpsWorker/packages.config
new file mode 100644
index 0000000000..79ece06bef
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/packages.config
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+</packages>
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
index 4a2846feea..287950720f 100644
--- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
@@ -15,10 +15,10 @@
"copyToOutput": {
"include": "data/*",
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
@@ -35,10 +35,10 @@
"copyToOutput": {
"include": "data/*",
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
@@ -57,13 +57,14 @@
},
"frameworks": {
"net45": { },
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45",
"net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027"
+ "Microsoft.NETCore.App": "1.0.0",
+ "NETStandard.Library": "1.6.0"
}
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
index f73d99dbd1..987387ca25 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
@@ -39,30 +39,25 @@
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
- <Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="System" />
+ <Reference Include="System.Net" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Net.Http.WebRequest" />
+ <Reference Include="BouncyCastle.Crypto">
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
+ <Reference Include="Newtonsoft.Json">
+ <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ <Reference Include="Google.Apis.Core">
+ <HintPath>..\packages\Google.Apis.Core.1.15.0\lib\net45\Google.Apis.Core.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Core, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
+ <Reference Include="Google.Apis.Auth">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.dll</HintPath>
</Reference>
- <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+ <Reference Include="Google.Apis.Auth.PlatformServices">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
- <Reference Include="System" />
- <Reference Include="System.Net" />
- <Reference Include="System.Net.Http" />
- <Reference Include="System.Net.Http.WebRequest" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/packages.config b/src/csharp/Grpc.IntegrationTesting.Server/packages.config
index c20d9ceed6..738d3e6f3b 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting.Server/packages.config
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.11.1" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.11.1" targetFramework="net45" />
+ <package id="Google.Apis.Auth" version="1.15.0" targetFramework="net45" />
+ <package id="Google.Apis.Core" version="1.15.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/project.json b/src/csharp/Grpc.IntegrationTesting.Server/project.json
index 4a2846feea..287950720f 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.Server/project.json
@@ -15,10 +15,10 @@
"copyToOutput": {
"include": "data/*",
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
@@ -35,10 +35,10 @@
"copyToOutput": {
"include": "data/*",
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
@@ -57,13 +57,14 @@
},
"frameworks": {
"net45": { },
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45",
"net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027"
+ "Microsoft.NETCore.App": "1.0.0",
+ "NETStandard.Library": "1.6.0"
}
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/packages.config b/src/csharp/Grpc.IntegrationTesting.StressClient/packages.config
new file mode 100644
index 0000000000..79ece06bef
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/packages.config
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+</packages>
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
index 4a2846feea..287950720f 100644
--- a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
@@ -15,10 +15,10 @@
"copyToOutput": {
"include": "data/*",
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
@@ -35,10 +35,10 @@
"copyToOutput": {
"include": "data/*",
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
@@ -57,13 +57,14 @@
},
"frameworks": {
"net45": { },
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45",
"net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027"
+ "Microsoft.NETCore.App": "1.0.0",
+ "NETStandard.Library": "1.6.0"
}
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs b/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs
index eb7b55a286..c17ede7561 100644
--- a/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs
@@ -49,7 +49,7 @@ namespace Grpc.IntegrationTesting
TestService.TestServiceClient unimplementedClient = new UnimplementedTestServiceClient();
// TODO: replace Moq by some mocking library with CoreCLR support.
-#if !NETSTANDARD1_5
+#if !NETCOREAPP1_0
[Test]
public void ExpandedParamOverloadCanBeMocked()
{
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index 3a0764230d..e030b21eec 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -38,9 +38,6 @@
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
- <Reference Include="CommandLine">
- <HintPath>..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll</HintPath>
- </Reference>
<Reference Include="Moq">
<HintPath>..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll</HintPath>
</Reference>
@@ -51,15 +48,6 @@
<Reference Include="BouncyCastle.Crypto">
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth">
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices">
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Core">
- <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
- </Reference>
<Reference Include="Google.Protobuf">
<HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
</Reference>
@@ -70,11 +58,23 @@
<HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System.Interactive.Async">
- <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
+ <HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="nunitlite">
<HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
</Reference>
+ <Reference Include="Google.Apis.Core">
+ <HintPath>..\packages\Google.Apis.Core.1.15.0\lib\net45\Google.Apis.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Apis.Auth">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Apis.Auth.PlatformServices">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ </Reference>
+ <Reference Include="CommandLineParser.Unofficial">
+ <HintPath>..\packages\CommandLineParser.Unofficial.2.0.275\lib\net45\CommandLineParser.Unofficial.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
@@ -149,4 +149,4 @@
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index e27fe5b3d8..79fd18b6d5 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -56,24 +56,24 @@ namespace Grpc.IntegrationTesting
{
private class ClientOptions
{
- [Option("server_host", DefaultValue = "127.0.0.1")]
+ [Option("server_host", Default = "127.0.0.1")]
public string ServerHost { get; set; }
- [Option("server_host_override", DefaultValue = TestCredentials.DefaultHostOverride)]
+ [Option("server_host_override", Default = TestCredentials.DefaultHostOverride)]
public string ServerHostOverride { get; set; }
[Option("server_port", Required = true)]
public int ServerPort { get; set; }
- [Option("test_case", DefaultValue = "large_unary")]
+ [Option("test_case", Default = "large_unary")]
public string TestCase { get; set; }
// Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls)
- [Option("use_tls", DefaultValue = false)]
+ [Option("use_tls", Default = false)]
public bool? UseTls { get; set; }
// Deliberately using nullable bool type to allow --use_test_ca=true syntax (as opposed to --use_test_ca)
- [Option("use_test_ca", DefaultValue = false)]
+ [Option("use_test_ca", Default = false)]
public bool? UseTestCa { get; set; }
[Option("default_service_account", Required = false)]
@@ -84,19 +84,6 @@ namespace Grpc.IntegrationTesting
[Option("service_account_key_file", Required = false)]
public string ServiceAccountKeyFile { get; set; }
-
- [HelpOption]
- public string GetUsage()
- {
- var help = new HelpText
- {
- Heading = "gRPC C# interop testing client",
- AddDashesToOption = true
- };
- help.AddPreOptionsLine("Usage:");
- help.AddOptions(this);
- return help;
- }
}
ClientOptions options;
@@ -108,14 +95,13 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
- var options = new ClientOptions();
- if (!Parser.Default.ParseArguments(args, options))
- {
- Environment.Exit(1);
- }
-
- var interopClient = new InteropClient(options);
- interopClient.Run().Wait();
+ var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
+ .WithNotParsed(errors => Environment.Exit(1))
+ .WithParsed(options =>
+ {
+ var interopClient = new InteropClient(options);
+ interopClient.Run().Wait();
+ });
}
private async Task Run()
@@ -145,26 +131,16 @@ namespace Grpc.IntegrationTesting
if (options.TestCase == "jwt_token_creds")
{
-#if !NETSTANDARD1_5
var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
Assert.IsTrue(googleCredential.IsCreateScopedRequired);
credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
-#else
- // TODO(jtattermusch): implement this
- throw new NotImplementedException("Not supported on CoreCLR yet");
-#endif
}
if (options.TestCase == "compute_engine_creds")
{
-#if !NETSTANDARD1_5
var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
Assert.IsFalse(googleCredential.IsCreateScopedRequired);
credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
-#else
- // TODO(jtattermusch): implement this
- throw new NotImplementedException("Not supported on CoreCLR yet");
-#endif
}
return credentials;
}
@@ -395,7 +371,6 @@ namespace Grpc.IntegrationTesting
public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client, string oauthScope)
{
-#if !NETSTANDARD1_5
Console.WriteLine("running oauth2_auth_token");
ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope });
string oauth2Token = await credential.GetAccessTokenForRequestAsync();
@@ -413,15 +388,10 @@ namespace Grpc.IntegrationTesting
Assert.True(oauthScope.Contains(response.OauthScope));
Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Console.WriteLine("Passed!");
-#else
- // TODO(jtattermusch): implement this
- throw new NotImplementedException("Not supported on CoreCLR yet");
-#endif
}
public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string oauthScope)
{
-#if !NETSTANDARD1_5
Console.WriteLine("running per_rpc_creds");
ITokenAccess googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
@@ -435,10 +405,6 @@ namespace Grpc.IntegrationTesting
Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Console.WriteLine("Passed!");
-#else
- // TODO(jtattermusch): implement this
- throw new NotImplementedException("Not supported on CoreCLR yet");
-#endif
}
public static async Task RunCancelAfterBeginAsync(TestService.TestServiceClient client)
@@ -731,17 +697,12 @@ namespace Grpc.IntegrationTesting
// extracts the client_email field from service account file used for auth test cases
private static string GetEmailFromServiceAccountFile()
{
-#if !NETSTANDARD1_5
string keyFile = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");
Assert.IsNotNull(keyFile);
var jobject = JObject.Parse(File.ReadAllText(keyFile));
string email = jobject.GetValue("client_email").Value<string>();
Assert.IsTrue(email.Length > 0); // spec requires nonempty client email.
return email;
-#else
- // TODO(jtattermusch): implement this
- throw new NotImplementedException("Not supported on CoreCLR yet");
-#endif
}
private static Metadata CreateTestMetadata()
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
index cd47e31c2b..4118f99c2b 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
@@ -51,25 +51,12 @@ namespace Grpc.IntegrationTesting
{
private class ServerOptions
{
- [Option("port", DefaultValue = 8070)]
+ [Option("port", Default = 8070)]
public int Port { get; set; }
// Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls)
- [Option("use_tls", DefaultValue = false)]
+ [Option("use_tls", Default = false)]
public bool? UseTls { get; set; }
-
- [HelpOption]
- public string GetUsage()
- {
- var help = new HelpText
- {
- Heading = "gRPC C# interop testing server",
- AddDashesToOption = true
- };
- help.AddPreOptionsLine("Usage:");
- help.AddOptions(this);
- return help;
- }
}
ServerOptions options;
@@ -81,14 +68,13 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
- var options = new ServerOptions();
- if (!Parser.Default.ParseArguments(args, options))
- {
- Environment.Exit(1);
- }
-
- var interopServer = new InteropServer(options);
- interopServer.Run();
+ var parserResult = Parser.Default.ParseArguments<ServerOptions>(args)
+ .WithNotParsed(errors => Environment.Exit(1))
+ .WithParsed(options =>
+ {
+ var interopServer = new InteropServer(options);
+ interopServer.Run();
+ });
}
private void Run()
diff --git a/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs
index 100ff0b5de..21c8adb45c 100644
--- a/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs
+++ b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs
@@ -49,7 +49,7 @@ namespace Grpc.IntegrationTesting
{
// Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
-#if NETSTANDARD1_5
+#if NETCOREAPP1_0
return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
#else
return new AutoRun().Execute(args);
diff --git a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
index a7c9fa894d..865556c242 100644
--- a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
+++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
@@ -52,21 +52,8 @@ namespace Grpc.IntegrationTesting
{
private class ServerOptions
{
- [Option("driver_port", DefaultValue = 0)]
+ [Option("driver_port", Default = 0)]
public int DriverPort { get; set; }
-
- [HelpOption]
- public string GetUsage()
- {
- var help = new HelpText
- {
- Heading = "gRPC C# performance testing worker",
- AddDashesToOption = true
- };
- help.AddPreOptionsLine("Usage:");
- help.AddOptions(this);
- return help;
- }
}
ServerOptions options;
@@ -78,14 +65,13 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
- var options = new ServerOptions();
- if (!Parser.Default.ParseArguments(args, options))
- {
- Environment.Exit(1);
- }
-
- var workerServer = new QpsWorker(options);
- workerServer.RunAsync().Wait();
+ var parserResult = Parser.Default.ParseArguments<ServerOptions>(args)
+ .WithNotParsed((x) => Environment.Exit(1))
+ .WithParsed(options =>
+ {
+ var workerServer = new QpsWorker(options);
+ workerServer.RunAsync().Wait();
+ });
}
private async Task RunAsync()
diff --git a/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
index 74ee040ae4..750613b078 100644
--- a/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
@@ -54,36 +54,23 @@ namespace Grpc.IntegrationTesting
private class ClientOptions
{
- [Option("server_addresses", DefaultValue = "localhost:8080")]
+ [Option("server_addresses", Default = "localhost:8080")]
public string ServerAddresses { get; set; }
- [Option("test_cases", DefaultValue = "large_unary:100")]
+ [Option("test_cases", Default = "large_unary:100")]
public string TestCases { get; set; }
- [Option("test_duration_secs", DefaultValue = -1)]
+ [Option("test_duration_secs", Default = -1)]
public int TestDurationSecs { get; set; }
- [Option("num_channels_per_server", DefaultValue = 1)]
+ [Option("num_channels_per_server", Default = 1)]
public int NumChannelsPerServer { get; set; }
- [Option("num_stubs_per_channel", DefaultValue = 1)]
+ [Option("num_stubs_per_channel", Default = 1)]
public int NumStubsPerChannel { get; set; }
- [Option("metrics_port", DefaultValue = 8081)]
+ [Option("metrics_port", Default = 8081)]
public int MetricsPort { get; set; }
-
- [HelpOption]
- public string GetUsage()
- {
- var help = new HelpText
- {
- Heading = "gRPC C# stress test client",
- AddDashesToOption = true
- };
- help.AddPreOptionsLine("Usage:");
- help.AddOptions(this);
- return help;
- }
}
ClientOptions options;
@@ -105,23 +92,21 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
- var options = new ClientOptions();
- if (!Parser.Default.ParseArguments(args, options))
- {
- Environment.Exit(1);
- }
-
- GrpcPreconditions.CheckArgument(options.NumChannelsPerServer > 0);
- GrpcPreconditions.CheckArgument(options.NumStubsPerChannel > 0);
+ var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
+ .WithNotParsed((x) => Environment.Exit(1))
+ .WithParsed(options => {
+ GrpcPreconditions.CheckArgument(options.NumChannelsPerServer > 0);
+ GrpcPreconditions.CheckArgument(options.NumStubsPerChannel > 0);
- var serverAddresses = options.ServerAddresses.Split(',');
- GrpcPreconditions.CheckArgument(serverAddresses.Length > 0, "You need to provide at least one server address");
+ var serverAddresses = options.ServerAddresses.Split(',');
+ GrpcPreconditions.CheckArgument(serverAddresses.Length > 0, "You need to provide at least one server address");
- var testCases = ParseWeightedTestCases(options.TestCases);
- GrpcPreconditions.CheckArgument(testCases.Count > 0, "You need to provide at least one test case");
+ var testCases = ParseWeightedTestCases(options.TestCases);
+ GrpcPreconditions.CheckArgument(testCases.Count > 0, "You need to provide at least one test case");
- var interopClient = new StressTestClient(options, serverAddresses.ToList(), testCases);
- interopClient.Run().Wait();
+ var interopClient = new StressTestClient(options, serverAddresses.ToList(), testCases);
+ interopClient.Run().Wait();
+ });
}
async Task Run()
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index 3161c5b755..8bf9dd4937 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="CommandLineParser" version="1.9.71" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.11.1" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.11.1" targetFramework="net45" />
+ <package id="CommandLineParser.Unofficial" version="2.0.275" targetFramework="net45" />
+ <package id="Google.Apis.Auth" version="1.15.0" targetFramework="net45" />
+ <package id="Google.Apis.Core" version="1.15.0" targetFramework="net45" />
<package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
- <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
+ <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
<package id="Moq" version="4.2.1510.2205" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
<package id="NUnit" version="3.2.0" targetFramework="net45" />
diff --git a/src/csharp/Grpc.IntegrationTesting/project.json b/src/csharp/Grpc.IntegrationTesting/project.json
index 6297600ddc..9d706510b2 100644
--- a/src/csharp/Grpc.IntegrationTesting/project.json
+++ b/src/csharp/Grpc.IntegrationTesting/project.json
@@ -15,10 +15,10 @@
"copyToOutput": {
"include": "data/*",
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
@@ -35,10 +35,10 @@
"copyToOutput": {
"include": "data/*",
"mappings": {
- "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
- "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so",
- "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
+ "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
+ "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
@@ -58,7 +58,7 @@
"target": "project"
},
"Google.Protobuf": "3.0.0-beta3",
- "CommandLineParser": "1.9.71",
+ "CommandLineParser.Unofficial": "2.0.275",
"NUnit": "3.2.0",
"NUnitLite": "3.2.0-*"
},
@@ -72,14 +72,15 @@
"System.IO": ""
}
},
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45",
"net45"
],
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24027",
- "System.Linq.Expressions": "4.0.11-rc2-24027"
+ "Microsoft.NETCore.App": "1.0.0",
+ "NETStandard.Library": "1.6.0",
+ "System.Linq.Expressions": "4.1.0"
}
}
}
diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat
index f05c0241b6..b92189c840 100644
--- a/src/csharp/build_packages.bat
+++ b/src/csharp/build_packages.bat
@@ -31,10 +31,7 @@
@rem Current package versions
set VERSION=1.1.0-dev
-set PROTOBUF_VERSION=3.0.0-beta3
-
-@rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well.
-set VERSION_WITH_BETA=%VERSION%-beta
+set PROTOBUF_VERSION=3.0.0
@rem Adjust the location of nuget.exe
set NUGET=C:\nuget\nuget.exe
@@ -58,7 +55,6 @@ xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* pr
@rem Fetch all dependencies
%NUGET% restore ..\..\vsprojects\grpc_csharp_ext.sln || goto :error
-%NUGET% restore Grpc.sln || goto :error
setlocal
@@ -73,7 +69,7 @@ endlocal
%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error
%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% || goto :error
-%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION_WITH_BETA% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
+%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
%NUGET% pack Grpc.nuspec -Version %VERSION% || goto :error
%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% || goto :error
diff --git a/src/node/ext/call_credentials.cc b/src/node/ext/call_credentials.cc
index 3c8f0c56da..81fc552fd1 100644
--- a/src/node/ext/call_credentials.cc
+++ b/src/node/ext/call_credentials.cc
@@ -68,6 +68,8 @@ using v8::Value;
Nan::Callback *CallCredentials::constructor;
Persistent<FunctionTemplate> CallCredentials::fun_tpl;
+static Callback *plugin_callback;
+
CallCredentials::CallCredentials(grpc_call_credentials *credentials)
: wrapped_credentials(credentials) {}
@@ -88,6 +90,11 @@ void CallCredentials::Init(Local<Object> exports) {
Nan::New<FunctionTemplate>(CreateFromPlugin)).ToLocalChecked());
Nan::Set(exports, Nan::New("CallCredentials").ToLocalChecked(), ctr);
constructor = new Nan::Callback(ctr);
+
+ Local<FunctionTemplate> callback_tpl =
+ Nan::New<FunctionTemplate>(PluginCallback);
+ plugin_callback = new Callback(
+ Nan::GetFunction(callback_tpl).ToLocalChecked());
}
bool CallCredentials::HasInstance(Local<Value> val) {
@@ -195,23 +202,28 @@ NAN_METHOD(PluginCallback) {
return Nan::ThrowTypeError(
"The callback's third argument must be an object");
}
+ if (!info[3]->IsObject()) {
+ return Nan::ThrowTypeError(
+ "The callback's fourth argument must be an object");
+ }
shared_ptr<Resources> resources(new Resources);
grpc_status_code code = static_cast<grpc_status_code>(
Nan::To<uint32_t>(info[0]).FromJust());
Utf8String details_utf8_str(info[1]);
char *details = *details_utf8_str;
grpc_metadata_array array;
+ Local<Object> callback_data = Nan::To<Object>(info[3]).ToLocalChecked();
if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(),
&array, resources)){
return Nan::ThrowError("Failed to parse metadata");
}
grpc_credentials_plugin_metadata_cb cb =
reinterpret_cast<grpc_credentials_plugin_metadata_cb>(
- Nan::Get(info.Callee(),
+ Nan::Get(callback_data,
Nan::New("cb").ToLocalChecked()
).ToLocalChecked().As<External>()->Value());
void *user_data =
- Nan::Get(info.Callee(),
+ Nan::Get(callback_data,
Nan::New("user_data").ToLocalChecked()
).ToLocalChecked().As<External>()->Value();
cb(user_data, array.metadata, array.count, code, details);
@@ -227,17 +239,17 @@ NAUV_WORK_CB(SendPluginCallback) {
while (!callbacks.empty()) {
plugin_callback_data *data = callbacks.front();
callbacks.pop_front();
- // Attach cb and user_data to plugin_callback so that it can access them later
- v8::Local<v8::Function> plugin_callback = Nan::GetFunction(
- Nan::New<v8::FunctionTemplate>(PluginCallback)).ToLocalChecked();
- Nan::Set(plugin_callback, Nan::New("cb").ToLocalChecked(),
+ Local<Object> callback_data = Nan::New<Object>();
+ Nan::Set(callback_data, Nan::New("cb").ToLocalChecked(),
Nan::New<v8::External>(reinterpret_cast<void*>(data->cb)));
- Nan::Set(plugin_callback, Nan::New("user_data").ToLocalChecked(),
+ Nan::Set(callback_data, Nan::New("user_data").ToLocalChecked(),
Nan::New<v8::External>(data->user_data));
- const int argc = 2;
+ const int argc = 3;
v8::Local<v8::Value> argv[argc] = {
Nan::New(data->service_url).ToLocalChecked(),
- plugin_callback
+ callback_data,
+ // Get Local<Function> from Nan::Callback*
+ **plugin_callback
};
Nan::Callback *callback = state->callback;
callback->Call(argc, argv);
diff --git a/src/node/health_check/package.json b/src/node/health_check/package.json
index 67f5301df7..e673359809 100644
--- a/src/node/health_check/package.json
+++ b/src/node/health_check/package.json
@@ -15,15 +15,15 @@
}
],
"dependencies": {
- "grpc": "^0.15.0",
+ "grpc": "^1.1.0-dev",
"lodash": "^3.9.3",
- "google-protobuf": "^3.0.0-alpha.5"
+ "google-protobuf": "^3.0.0"
},
- "files": {
+ "files": [
"LICENSE",
"health.js",
"v1"
- },
+ ],
"main": "src/node/index.js",
"license": "BSD-3-Clause"
}
diff --git a/src/node/src/credentials.js b/src/node/src/credentials.js
index b746d0625d..51ff1da01e 100644
--- a/src/node/src/credentials.js
+++ b/src/node/src/credentials.js
@@ -71,6 +71,8 @@ var Metadata = require('./metadata.js');
var common = require('./common.js');
+var _ = require('lodash');
+
/**
* Create an SSL Credentials object. If using a client-side certificate, both
* the second and third arguments must be passed.
@@ -92,13 +94,14 @@ exports.createSsl = ChannelCredentials.createSsl;
* @return {CallCredentials} The credentials object
*/
exports.createFromMetadataGenerator = function(metadata_generator) {
- return CallCredentials.createFromPlugin(function(service_url, callback) {
+ return CallCredentials.createFromPlugin(function(service_url, cb_data,
+ callback) {
metadata_generator({service_url: service_url}, function(error, metadata) {
var code = grpc.status.OK;
var message = '';
if (error) {
message = error.message;
- if (error.hasOwnProperty('code')) {
+ if (error.hasOwnProperty('code') && _.isFinite(error.code)) {
code = error.code;
} else {
code = grpc.status.UNAUTHENTICATED;
@@ -107,7 +110,7 @@ exports.createFromMetadataGenerator = function(metadata_generator) {
metadata = new Metadata();
}
}
- callback(code, message, metadata._getCoreRepresentation());
+ callback(code, message, metadata._getCoreRepresentation(), cb_data);
});
});
};
diff --git a/src/node/test/credentials_test.js b/src/node/test/credentials_test.js
index 0a21572582..305843f665 100644
--- a/src/node/test/credentials_test.js
+++ b/src/node/test/credentials_test.js
@@ -71,7 +71,10 @@ var fakeSuccessfulGoogleCredentials = {
var fakeFailingGoogleCredentials = {
getRequestMetadata: function(service_url, callback) {
setTimeout(function() {
- callback(new Error('Authentication failure'));
+ // Google credentials currently adds string error codes to auth errors
+ var error = new Error('Authentication failure');
+ error.code = 'ENOENT';
+ callback(error);
}, 0);
}
};
diff --git a/src/node/tools/bin/protoc.js b/src/node/tools/bin/protoc.js
index 53fc5dc428..7f8356867a 100755
--- a/src/node/tools/bin/protoc.js
+++ b/src/node/tools/bin/protoc.js
@@ -47,7 +47,11 @@ var exe_ext = process.platform === 'win32' ? '.exe' : '';
var protoc = path.resolve(__dirname, 'protoc' + exe_ext);
-var child_process = execFile(protoc, process.argv.slice(2), function(error, stdout, stderr) {
+var plugin = path.resolve(__dirname, 'grpc_node_plugin' + exe_ext);
+
+var args = ['--plugin=protoc-gen-grpc=' + plugin].concat(process.argv.slice(2));
+
+var child_process = execFile(protoc, args, function(error, stdout, stderr) {
if (error) {
throw error;
}
diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
index 72cadb9319..07d62d2047 100644
--- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
+++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
@@ -36,8 +36,8 @@ Pod::Spec.new do |s|
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them.
s.name = '!ProtoCompiler-gRPCPlugin'
- v = '0.14.0'
- s.version = v
+ v = '1.0.0-pre1'
+ s.version = "#{v}.2" # .2 to depend on protoc 3.0.0
s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
s.description = <<-DESC
This podspec only downloads the gRPC protoc plugin so that local pods generating protos can use
@@ -82,7 +82,7 @@ Pod::Spec.new do |s|
s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' }
repo = 'grpc/grpc'
- release = 'release-0_14_1'
+ release = "objective-c-v#{v}"
file = "grpc_objective_c_plugin-#{v}-macos-x86_64.zip"
s.source = {
:http => "https://github.com/#{repo}/releases/download/#{release}/#{file}",
@@ -96,7 +96,7 @@ Pod::Spec.new do |s|
s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin.
- s.dependency '!ProtoCompiler', '3.0.0-beta-3.1'
+ s.dependency '!ProtoCompiler', '3.0.0'
# For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.1'
s.osx.deployment_target = '10.9'
diff --git a/src/objective-c/!ProtoCompiler.podspec b/src/objective-c/!ProtoCompiler.podspec
index 5e59b25aee..5018dedc06 100644
--- a/src/objective-c/!ProtoCompiler.podspec
+++ b/src/objective-c/!ProtoCompiler.podspec
@@ -36,7 +36,7 @@ Pod::Spec.new do |s|
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them.
s.name = '!ProtoCompiler'
- v = '3.0.0-beta-3.1'
+ v = '3.0.0'
s.version = v
s.summary = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files'
s.description = <<-DESC
@@ -97,10 +97,9 @@ Pod::Spec.new do |s|
s.authors = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' }
repo = 'google/protobuf'
- release = "v#{v}"
file = "protoc-#{v}-osx-x86_64.zip"
s.source = {
- :http => "https://github.com/#{repo}/releases/download/#{release}/#{file}",
+ :http => "https://github.com/#{repo}/releases/download/v#{v}/#{file}",
# TODO(jcanizales): Add sha1 or sha256
# :sha1 => '??',
}
@@ -109,7 +108,7 @@ Pod::Spec.new do |s|
'google/**/*.proto' # Well-known protobuf types
# Restrict the protobuf runtime version to the one supported by this version of protoc.
- s.dependency 'Protobuf', v
+ s.dependency 'Protobuf', '~> 3.0'
# For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.1'
s.osx.deployment_target = '10.9'
@@ -121,7 +120,7 @@ Pod::Spec.new do |s|
repo_root = '../..'
plugin = 'grpc_objective_c_plugin'
s.prepare_command = <<-CMD
- if [ ! -f protoc ]; then
+ if [ ! -f bin/protoc ]; then
cd #{repo_root}
# This will build protoc from the Protobuf submodule of gRPC, and put it in
# #{repo_root}/bins/opt/protobuf.
@@ -130,7 +129,9 @@ Pod::Spec.new do |s|
# _we do not want_. Find a way for this to always build from source.
make #{plugin}
cd -
+ else
+ mv bin/protoc .
+ mv include/google .
fi
CMD
-
end
diff --git a/src/objective-c/BoringSSL.podspec b/src/objective-c/BoringSSL.podspec
index 42b4434d0d..b759997c11 100644
--- a/src/objective-c/BoringSSL.podspec
+++ b/src/objective-c/BoringSSL.podspec
@@ -31,7 +31,7 @@
Pod::Spec.new do |s|
s.name = 'BoringSSL'
- version = '4.0'
+ version = '5.0'
s.version = version
s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.'
# Adapted from the homepage:
@@ -67,8 +67,11 @@ Pod::Spec.new do |s|
# "The name and email addresses of the library maintainers, not the Podspec maintainer."
s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite'
- s.source = { :git => 'https://boringssl.googlesource.com/boringssl',
- :tag => "version_for_cocoapods_#{version}" }
+ s.source = {
+ :git => 'https://boringssl.googlesource.com/boringssl',
+ :tag => "version_for_cocoapods_#{version}",
+ # :commit => '8d343b44bbab829d1a28fdef650ca95f7db4412e',
+ }
name = 'openssl'
@@ -219,7 +222,7 @@ Pod::Spec.new do |s|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
- /* This file was generated by err_data_generate.go. */
+ /* This file was generated by err_data_generate.go. */
#include <openssl/base.h>
#include <openssl/err.h>
@@ -385,42 +388,42 @@ Pod::Spec.new do |s|
0x28340c19,
0x283480ac,
0x283500ea,
- 0x2c322775,
- 0x2c32a783,
- 0x2c332795,
- 0x2c33a7a7,
- 0x2c3427bb,
- 0x2c34a7cd,
- 0x2c3527e8,
- 0x2c35a7fa,
- 0x2c36280d,
+ 0x2c3227cb,
+ 0x2c32a7d9,
+ 0x2c3327eb,
+ 0x2c33a7fd,
+ 0x2c342811,
+ 0x2c34a823,
+ 0x2c35283e,
+ 0x2c35a850,
+ 0x2c362863,
0x2c36832d,
- 0x2c37281a,
- 0x2c37a82c,
- 0x2c38283f,
- 0x2c38a856,
- 0x2c392864,
- 0x2c39a874,
- 0x2c3a2886,
- 0x2c3aa89a,
- 0x2c3b28ab,
- 0x2c3ba8ca,
- 0x2c3c28de,
- 0x2c3ca8f4,
- 0x2c3d290d,
- 0x2c3da92a,
- 0x2c3e293b,
- 0x2c3ea949,
- 0x2c3f2961,
- 0x2c3fa979,
- 0x2c402986,
+ 0x2c372870,
+ 0x2c37a882,
+ 0x2c382895,
+ 0x2c38a8ac,
+ 0x2c3928ba,
+ 0x2c39a8ca,
+ 0x2c3a28dc,
+ 0x2c3aa8f0,
+ 0x2c3b2901,
+ 0x2c3ba920,
+ 0x2c3c2934,
+ 0x2c3ca94a,
+ 0x2c3d2963,
+ 0x2c3da980,
+ 0x2c3e2991,
+ 0x2c3ea99f,
+ 0x2c3f29b7,
+ 0x2c3fa9cf,
+ 0x2c4029dc,
0x2c4090e7,
- 0x2c412997,
- 0x2c41a9aa,
+ 0x2c4129ed,
+ 0x2c41aa00,
0x2c4210c0,
- 0x2c42a9bb,
+ 0x2c42aa11,
0x2c430720,
- 0x2c43a8bc,
+ 0x2c43a912,
0x30320000,
0x30328015,
0x3033001f,
@@ -594,145 +597,148 @@ Pod::Spec.new do |s|
0x404619e8,
0x40469a08,
0x40471a16,
- 0x40479a2a,
- 0x40481a3f,
- 0x40489a58,
- 0x40491a6f,
- 0x40499a89,
- 0x404a1aa0,
- 0x404a9abe,
- 0x404b1ad6,
- 0x404b9aed,
- 0x404c1b03,
- 0x404c9b15,
- 0x404d1b36,
- 0x404d9b58,
- 0x404e1b6c,
- 0x404e9b79,
- 0x404f1b90,
- 0x404f9ba0,
- 0x40501bca,
- 0x40509bde,
- 0x40511bf9,
- 0x40519c09,
- 0x40521c20,
- 0x40529c32,
- 0x40531c4a,
- 0x40539c5d,
- 0x40541c72,
- 0x40549c95,
- 0x40551ca3,
- 0x40559cc0,
- 0x40561ccd,
- 0x40569ce6,
- 0x40571cfe,
- 0x40579d11,
- 0x40581d26,
- 0x40589d38,
- 0x40591d48,
- 0x40599d61,
- 0x405a1d75,
- 0x405a9d85,
- 0x405b1d9d,
- 0x405b9dae,
- 0x405c1dc1,
- 0x405c9dd2,
- 0x405d1ddf,
- 0x405d9df6,
- 0x405e1e16,
+ 0x40479a3d,
+ 0x40481a52,
+ 0x40489a6b,
+ 0x40491a82,
+ 0x40499a9c,
+ 0x404a1ab3,
+ 0x404a9ad1,
+ 0x404b1ae9,
+ 0x404b9b00,
+ 0x404c1b16,
+ 0x404c9b28,
+ 0x404d1b49,
+ 0x404d9b6b,
+ 0x404e1b7f,
+ 0x404e9b8c,
+ 0x404f1ba3,
+ 0x404f9bb3,
+ 0x40501bdd,
+ 0x40509bf1,
+ 0x40511c0c,
+ 0x40519c1c,
+ 0x40521c33,
+ 0x40529c45,
+ 0x40531c5d,
+ 0x40539c70,
+ 0x40541c85,
+ 0x40549ca8,
+ 0x40551cb6,
+ 0x40559cd3,
+ 0x40561ce0,
+ 0x40569cf9,
+ 0x40571d11,
+ 0x40579d24,
+ 0x40581d39,
+ 0x40589d4b,
+ 0x40591d7a,
+ 0x40599d93,
+ 0x405a1da7,
+ 0x405a9db7,
+ 0x405b1dcf,
+ 0x405b9de0,
+ 0x405c1df3,
+ 0x405c9e04,
+ 0x405d1e11,
+ 0x405d9e28,
+ 0x405e1e48,
0x405e8a95,
- 0x405f1e37,
- 0x405f9e44,
- 0x40601e52,
- 0x40609e74,
- 0x40611e9c,
- 0x40619eb1,
- 0x40621ec8,
- 0x40629ed9,
- 0x40631eea,
- 0x40639eff,
- 0x40641f16,
- 0x40649f27,
- 0x40651f42,
- 0x40659f59,
- 0x40661f71,
- 0x40669f9b,
- 0x40671fc6,
- 0x40679fe7,
- 0x40681ffa,
- 0x4068a01b,
- 0x4069204d,
- 0x4069a07b,
- 0x406a209c,
- 0x406aa0bc,
- 0x406b2244,
- 0x406ba267,
- 0x406c227d,
- 0x406ca4a9,
- 0x406d24d8,
- 0x406da500,
- 0x406e2519,
- 0x406ea531,
- 0x406f2550,
- 0x406fa565,
- 0x40702578,
- 0x4070a595,
+ 0x405f1e69,
+ 0x405f9e76,
+ 0x40601e84,
+ 0x40609ea6,
+ 0x40611ece,
+ 0x40619ee3,
+ 0x40621efa,
+ 0x40629f0b,
+ 0x40631f1c,
+ 0x40639f31,
+ 0x40641f48,
+ 0x40649f59,
+ 0x40651f74,
+ 0x40659f8b,
+ 0x40661fa3,
+ 0x40669fcd,
+ 0x40671ff8,
+ 0x4067a019,
+ 0x4068202c,
+ 0x4068a04d,
+ 0x4069207f,
+ 0x4069a0ad,
+ 0x406a20ce,
+ 0x406aa0ee,
+ 0x406b2276,
+ 0x406ba299,
+ 0x406c22af,
+ 0x406ca4db,
+ 0x406d250a,
+ 0x406da532,
+ 0x406e254b,
+ 0x406ea563,
+ 0x406f2582,
+ 0x406fa597,
+ 0x407025aa,
+ 0x4070a5c7,
0x40710800,
- 0x4071a5a7,
- 0x407225ba,
- 0x4072a5d3,
- 0x407325eb,
+ 0x4071a5d9,
+ 0x407225ec,
+ 0x4072a605,
+ 0x4073261d,
0x4073936d,
- 0x407425ff,
- 0x4074a619,
- 0x4075262a,
- 0x4075a63e,
- 0x4076264c,
+ 0x40742631,
+ 0x4074a64b,
+ 0x4075265c,
+ 0x4075a670,
+ 0x4076267e,
0x407691aa,
- 0x40772671,
- 0x4077a693,
- 0x407826ae,
- 0x4078a6c3,
- 0x407926da,
- 0x4079a6f0,
- 0x407a26fc,
- 0x407aa70f,
- 0x407b2724,
- 0x407ba736,
- 0x407c274b,
- 0x407ca754,
- 0x407d2036,
- 0x407d9bb0,
- 0x41f4216f,
- 0x41f92201,
- 0x41fe20f4,
- 0x41fea2d0,
- 0x41ff23c1,
- 0x42032188,
- 0x420821aa,
- 0x4208a1e6,
- 0x420920d8,
- 0x4209a220,
- 0x420a212f,
- 0x420aa10f,
- 0x420b214f,
- 0x420ba1c8,
- 0x420c23dd,
- 0x420ca29d,
- 0x420d22b7,
- 0x420da2ee,
- 0x42122308,
- 0x421723a4,
- 0x4217a34a,
- 0x421c236c,
- 0x421f2327,
- 0x422123f4,
- 0x42262387,
- 0x422b248d,
- 0x422ba456,
- 0x422c2475,
- 0x422ca430,
- 0x422d240f,
+ 0x407726a3,
+ 0x4077a6c5,
+ 0x407826e0,
+ 0x4078a719,
+ 0x40792730,
+ 0x4079a746,
+ 0x407a2752,
+ 0x407aa765,
+ 0x407b277a,
+ 0x407ba78c,
+ 0x407c27a1,
+ 0x407ca7aa,
+ 0x407d2068,
+ 0x407d9bc3,
+ 0x407e26f5,
+ 0x407e9d5b,
+ 0x407f1a2a,
+ 0x41f421a1,
+ 0x41f92233,
+ 0x41fe2126,
+ 0x41fea302,
+ 0x41ff23f3,
+ 0x420321ba,
+ 0x420821dc,
+ 0x4208a218,
+ 0x4209210a,
+ 0x4209a252,
+ 0x420a2161,
+ 0x420aa141,
+ 0x420b2181,
+ 0x420ba1fa,
+ 0x420c240f,
+ 0x420ca2cf,
+ 0x420d22e9,
+ 0x420da320,
+ 0x4212233a,
+ 0x421723d6,
+ 0x4217a37c,
+ 0x421c239e,
+ 0x421f2359,
+ 0x42212426,
+ 0x422623b9,
+ 0x422b24bf,
+ 0x422ba488,
+ 0x422c24a7,
+ 0x422ca462,
+ 0x422d2441,
0x4432072b,
0x4432873a,
0x44330746,
@@ -775,69 +781,69 @@ Pod::Spec.new do |s|
0x4c3d136d,
0x4c3d937c,
0x4c3e1389,
- 0x503229cd,
- 0x5032a9dc,
- 0x503329e7,
- 0x5033a9f7,
- 0x50342a10,
- 0x5034aa2a,
- 0x50352a38,
- 0x5035aa4e,
- 0x50362a60,
- 0x5036aa76,
- 0x50372a8f,
- 0x5037aaa2,
- 0x50382aba,
- 0x5038aacb,
- 0x50392ae0,
- 0x5039aaf4,
- 0x503a2b14,
- 0x503aab2a,
- 0x503b2b42,
- 0x503bab54,
- 0x503c2b70,
- 0x503cab87,
- 0x503d2ba0,
- 0x503dabb6,
- 0x503e2bc3,
- 0x503eabd9,
- 0x503f2beb,
+ 0x50322a23,
+ 0x5032aa32,
+ 0x50332a3d,
+ 0x5033aa4d,
+ 0x50342a66,
+ 0x5034aa80,
+ 0x50352a8e,
+ 0x5035aaa4,
+ 0x50362ab6,
+ 0x5036aacc,
+ 0x50372ae5,
+ 0x5037aaf8,
+ 0x50382b10,
+ 0x5038ab21,
+ 0x50392b36,
+ 0x5039ab4a,
+ 0x503a2b6a,
+ 0x503aab80,
+ 0x503b2b98,
+ 0x503babaa,
+ 0x503c2bc6,
+ 0x503cabdd,
+ 0x503d2bf6,
+ 0x503dac0c,
+ 0x503e2c19,
+ 0x503eac2f,
+ 0x503f2c41,
0x503f8382,
- 0x50402bfe,
- 0x5040ac0e,
- 0x50412c28,
- 0x5041ac37,
- 0x50422c51,
- 0x5042ac6e,
- 0x50432c7e,
- 0x5043ac8e,
- 0x50442c9d,
+ 0x50402c54,
+ 0x5040ac64,
+ 0x50412c7e,
+ 0x5041ac8d,
+ 0x50422ca7,
+ 0x5042acc4,
+ 0x50432cd4,
+ 0x5043ace4,
+ 0x50442cf3,
0x5044843f,
- 0x50452cb1,
- 0x5045accf,
- 0x50462ce2,
- 0x5046acf8,
- 0x50472d0a,
- 0x5047ad1f,
- 0x50482d45,
- 0x5048ad53,
- 0x50492d66,
- 0x5049ad7b,
- 0x504a2d91,
- 0x504aada1,
- 0x504b2dc1,
- 0x504badd4,
- 0x504c2df7,
- 0x504cae25,
- 0x504d2e37,
- 0x504dae54,
- 0x504e2e6f,
- 0x504eae8b,
- 0x504f2e9d,
- 0x504faeb4,
- 0x50502ec3,
+ 0x50452d07,
+ 0x5045ad25,
+ 0x50462d38,
+ 0x5046ad4e,
+ 0x50472d60,
+ 0x5047ad75,
+ 0x50482d9b,
+ 0x5048ada9,
+ 0x50492dbc,
+ 0x5049add1,
+ 0x504a2de7,
+ 0x504aadf7,
+ 0x504b2e17,
+ 0x504bae2a,
+ 0x504c2e4d,
+ 0x504cae7b,
+ 0x504d2e8d,
+ 0x504daeaa,
+ 0x504e2ec5,
+ 0x504eaee1,
+ 0x504f2ef3,
+ 0x504faf0a,
+ 0x50502f19,
0x505086ef,
- 0x50512ed6,
+ 0x50512f2c,
0x58320ec9,
0x68320e8b,
0x68328c25,
@@ -1218,6 +1224,7 @@ Pod::Spec.new do |s|
"DH_PUBLIC_VALUE_LENGTH_IS_WRONG\\0"
"DH_P_TOO_LONG\\0"
"DIGEST_CHECK_FAILED\\0"
+ "DOWNGRADE_DETECTED\\0"
"DTLS_MESSAGE_TOO_BIG\\0"
"ECC_CERT_NOT_FOR_SIGNING\\0"
"EMS_STATE_INCONSISTENT\\0"
@@ -1254,6 +1261,7 @@ Pod::Spec.new do |s|
"NO_CIPHERS_AVAILABLE\\0"
"NO_CIPHERS_PASSED\\0"
"NO_CIPHER_MATCH\\0"
+ "NO_COMMON_SIGNATURE_ALGORITHMS\\0"
"NO_COMPRESSION_SPECIFIED\\0"
"NO_METHOD_SPECIFIED\\0"
"NO_P256_SUPPORT\\0"
@@ -1344,6 +1352,7 @@ Pod::Spec.new do |s|
"UNSUPPORTED_COMPRESSION_ALGORITHM\\0"
"UNSUPPORTED_ELLIPTIC_CURVE\\0"
"UNSUPPORTED_PROTOCOL\\0"
+ "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\\0"
"WRONG_CERTIFICATE_TYPE\\0"
"WRONG_CIPHER_RETURNED\\0"
"WRONG_CURVE\\0"
diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
index 646bf43b54..4a3f3fa4a1 100644
--- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
+++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
@@ -43,7 +43,10 @@
* Use the provided @c userAgentPrefix at the beginning of the HTTP User Agent string for all calls
* to the specified @c host.
*/
-+ (void)setUserAgentPrefix:(NSString *)userAgentPrefix forHost:(NSString *)host;
++ (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix forHost:(nonnull NSString *)host;
+
+/** The default response size limit is 4MB. Set this to override that default. */
++ (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host;
+ (void)closeOpenConnections DEPRECATED_MSG_ATTRIBUTE("The API for this feature is experimental, "
"and might be removed or modified at any "
diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
index bcc3b91507..7fab357e93 100644
--- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
+++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
@@ -37,15 +37,16 @@
@implementation GRPCCall (ChannelArg)
-+ (void)setUserAgentPrefix:(NSString *)userAgentPrefix forHost:(NSString *)host {
- if (!host) {
- [NSException raise:NSInvalidArgumentException
- format:@"host and userAgentPrefix must be provided."];
- }
++ (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix forHost:(nonnull NSString *)host {
GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
hostConfig.userAgentPrefix = userAgentPrefix;
}
++ (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host {
+ GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
+ hostConfig.responseSizeLimitOverride = @(limit);
+}
+
+ (void)closeOpenConnections {
[GRPCHost flushChannelCache];
}
diff --git a/src/objective-c/GRPCClient/GRPCCall+Tests.h b/src/objective-c/GRPCClient/GRPCCall+Tests.h
index ccc5723ec7..184ad09c5c 100644
--- a/src/objective-c/GRPCClient/GRPCCall+Tests.h
+++ b/src/objective-c/GRPCClient/GRPCCall+Tests.h
@@ -57,4 +57,10 @@
* more than one invocation of the methods of this category.
*/
+ (void)useInsecureConnectionsForHost:(NSString *)host;
+
+/**
+ * Resets all host configurations to their default values, and flushes all connections from the
+ * cache.
+ */
++ (void)resetHostSettings;
@end
diff --git a/src/objective-c/GRPCClient/GRPCCall+Tests.m b/src/objective-c/GRPCClient/GRPCCall+Tests.m
index b9456691bd..656cba8fec 100644
--- a/src/objective-c/GRPCClient/GRPCCall+Tests.m
+++ b/src/objective-c/GRPCClient/GRPCCall+Tests.m
@@ -61,4 +61,7 @@
hostConfig.secure = NO;
}
++ (void)resetHostSettings {
+ [GRPCHost resetAllHostSettings];
+}
@end
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h
index 40e78a92d6..5bada2dd50 100644
--- a/src/objective-c/GRPCClient/private/GRPCChannel.h
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.h
@@ -59,8 +59,8 @@ struct grpc_channel_credentials;
* Creates a secure channel to the specified @c host using Cronet as a transport mechanism.
*/
#ifdef GRPC_COMPILE_WITH_CRONET
-+ (nullable GRPCChannel *)secureCronetChannelWithHost:(NSString *)host
- channelArgs:(NSDictionary *)channelArgs;
++ (nullable GRPCChannel *)secureCronetChannelWithHost:(nonnull NSString *)host
+ channelArgs:(nonnull NSDictionary *)channelArgs;
#endif
/**
* Creates a secure channel to the specified @c host using the specified @c credentials and
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m
index 7b7b79e1c6..e49aceefe1 100644
--- a/src/objective-c/GRPCClient/private/GRPCChannel.m
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.m
@@ -47,7 +47,7 @@
#endif
#import "GRPCCompletionQueue.h"
-void freeChannelArgs(grpc_channel_args *channel_args) {
+static void FreeChannelArgs(grpc_channel_args *channel_args) {
for (size_t i = 0; i < channel_args->num_args; ++i) {
grpc_arg *arg = &channel_args->args[i];
gpr_free(arg->key);
@@ -65,7 +65,7 @@ void freeChannelArgs(grpc_channel_args *channel_args) {
* value responds to @c @selector(intValue). Otherwise, an exception will be raised. The caller of
* this function is responsible for calling @c freeChannelArgs on a non-NULL returned value.
*/
-grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) {
+static grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) {
if (!dictionary) {
return NULL;
}
@@ -115,10 +115,12 @@ grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) {
}
if (self = [super init]) {
- _channelArgs = buildChannelArgs(channelArgs);
+ _channelArgs = BuildChannelArgs(channelArgs);
_host = [host copy];
- _unmanagedChannel = grpc_cronet_secure_channel_create(cronetEngine, _host.UTF8String, _channelArgs,
- NULL);
+ _unmanagedChannel = grpc_cronet_secure_channel_create(cronetEngine,
+ _host.UTF8String,
+ _channelArgs,
+ NULL);
}
return self;
@@ -138,7 +140,7 @@ grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) {
}
if (self = [super init]) {
- _channelArgs = buildChannelArgs(channelArgs);
+ _channelArgs = BuildChannelArgs(channelArgs);
_host = [host copy];
if (secure) {
_unmanagedChannel = grpc_secure_channel_create(credentials, _host.UTF8String, _channelArgs,
@@ -155,7 +157,7 @@ grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) {
// TODO(jcanizales): Be sure to add a test with a server that closes the connection prematurely,
// as in the past that made this call to crash.
grpc_channel_destroy(_unmanagedChannel);
- freeChannelArgs(_channelArgs);
+ FreeChannelArgs(_channelArgs);
}
#ifdef GRPC_COMPILE_WITH_CRONET
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.h b/src/objective-c/GRPCClient/private/GRPCHost.h
index 350c69bf8e..c8b5dd315b 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.h
+++ b/src/objective-c/GRPCClient/private/GRPCHost.h
@@ -42,6 +42,7 @@ struct grpc_channel_credentials;
@interface GRPCHost : NSObject
+ (void)flushChannelCache;
++ (void)resetAllHostSettings;
@property(nonatomic, readonly) NSString *address;
@property(nonatomic, copy, nullable) NSString *userAgentPrefix;
@@ -53,6 +54,10 @@ struct grpc_channel_credentials;
@property(nonatomic, copy, nullable) NSString *hostNameOverride;
+/** The default response size limit is 4MB. Set this to override that default. */
+@property(nonatomic, strong, nullable) NSNumber *responseSizeLimitOverride;
+
+
- (nullable instancetype)init NS_UNAVAILABLE;
/** Host objects initialized with the same address are the same. */
+ (nullable instancetype)hostWithAddress:(NSString *)address;
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m
index 08c699f99e..477ddf51d9 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.m
+++ b/src/objective-c/GRPCClient/private/GRPCHost.m
@@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN
// TODO(jcanizales): Generate the version in a standalone header, from templates. Like
// templates/src/core/surface/version.c.template .
-#define GRPC_OBJC_VERSION_STRING @"0.13.0"
+#define GRPC_OBJC_VERSION_STRING @"1.0.0-pre1"
static NSMutableDictionary *kHostCache;
@@ -113,6 +113,12 @@ static NSMutableDictionary *kHostCache;
}
}
++ (void)resetAllHostSettings {
+ @synchronized (kHostCache) {
+ kHostCache = [NSMutableDictionary dictionary];
+ }
+}
+
- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path
completionQueue:(GRPCCompletionQueue *)queue {
GRPCChannel *channel;
@@ -209,6 +215,10 @@ static NSMutableDictionary *kHostCache;
if (_secure && _hostNameOverride) {
args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = _hostNameOverride;
}
+
+ if (_responseSizeLimitOverride) {
+ args[@GRPC_ARG_MAX_MESSAGE_LENGTH] = _responseSizeLimitOverride;
+ }
return args;
}
diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m
index e7232f2683..83d1b655e8 100644
--- a/src/objective-c/ProtoRPC/ProtoRPC.m
+++ b/src/objective-c/ProtoRPC/ProtoRPC.m
@@ -33,7 +33,11 @@
#import "ProtoRPC.h"
-#import <Protobuf/GPBProtocolBuffers.h>
+#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS
+ #import <Protobuf/GPBProtocolBuffers.h>
+#else
+ #import <GPBProtocolBuffers.h>
+#endif
#import <RxLibrary/GRXWriteable.h>
#import <RxLibrary/GRXWriter+Transformations.h>
diff --git a/src/objective-c/README.md b/src/objective-c/README.md
index a0ca5f448a..909b12bab2 100644
--- a/src/objective-c/README.md
+++ b/src/objective-c/README.md
@@ -48,7 +48,7 @@ Pod::Spec.new do |s|
src = '.'
# We'll use protoc with the gRPC plugin.
- s.dependency '!ProtoCompiler-gRPCPlugin', '~> 0.14'
+ s.dependency '!ProtoCompiler-gRPCPlugin', '~> 1.0.0-pre1.2'
# Pods directory corresponding to this app's Podfile, relative to the location of this podspec.
pods_root = '<path to your Podfile>/Pods'
diff --git a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
index 6e783fb5ad..974a6765c7 100644
--- a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
+++ b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
@@ -11,7 +11,7 @@ Pod::Spec.new do |s|
s.osx.deployment_target = '10.9'
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
- s.dependency "!ProtoCompiler-gRPCPlugin", "~> 0.14"
+ s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0.0-pre1.2"
repo_root = '../../../..'
bin_dir = "#{repo_root}/bins/$CONFIG"
diff --git a/src/objective-c/examples/RemoteTestClient/empty.proto b/src/objective-c/examples/RemoteTestClient/empty.proto
deleted file mode 100644
index a678048289..0000000000
--- a/src/objective-c/examples/RemoteTestClient/empty.proto
+++ /dev/null
@@ -1,44 +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.
-
-syntax = "proto3";
-
-package grpc.testing;
-
-option objc_class_prefix = "RMT";
-
-// An empty message that you can re-use to avoid defining duplicated empty
-// messages in your project. A typical example is to use it as argument or the
-// return value of a service API. For instance:
-//
-// service Foo {
-// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { };
-// };
-//
-message Empty {}
diff --git a/src/objective-c/examples/RemoteTestClient/test.proto b/src/objective-c/examples/RemoteTestClient/test.proto
index 514c3b8095..5c359c5c12 100644
--- a/src/objective-c/examples/RemoteTestClient/test.proto
+++ b/src/objective-c/examples/RemoteTestClient/test.proto
@@ -31,7 +31,7 @@
// of unary/streaming requests/responses.
syntax = "proto3";
-import "empty.proto";
+import "google/protobuf/empty.proto";
import "messages.proto";
package grpc.testing;
@@ -42,7 +42,7 @@ option objc_class_prefix = "RMT";
// performance with various types of payload.
service TestService {
// One empty request followed by one empty response.
- rpc EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty);
+ rpc EmptyCall(google.protobuf.Empty) returns (google.protobuf.Empty);
// One request followed by one response.
rpc UnaryCall(SimpleRequest) returns (SimpleResponse);
diff --git a/src/objective-c/examples/Sample/Podfile b/src/objective-c/examples/Sample/Podfile
index 8740b2f963..f6f0c00d5d 100644
--- a/src/objective-c/examples/Sample/Podfile
+++ b/src/objective-c/examples/Sample/Podfile
@@ -3,6 +3,8 @@ platform :ios, '8.0'
install! 'cocoapods', :deterministic_uuids => false
+use_frameworks! if ENV['FRAMEWORKS'] == 'YES'
+
# Location of gRPC's repo root relative to this file.
GRPC_LOCAL_SRC = '../../../..'
diff --git a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj
index 5c2a6d14f9..ab7159cda2 100644
--- a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj
+++ b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj
@@ -7,7 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
- 426A5020E0E158A101BCA1D9 /* libPods-Sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C20055928615A6F8434E26B4 /* libPods-Sample.a */; };
+ 3F035697392F601049D3DDE1 /* Pods_Sample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */; };
6369A2701A9322E20015FC5C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A26F1A9322E20015FC5C /* main.m */; };
6369A2731A9322E20015FC5C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2721A9322E20015FC5C /* AppDelegate.m */; };
6369A2761A9322E20015FC5C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2751A9322E20015FC5C /* ViewController.m */; };
@@ -26,7 +26,7 @@
6369A2751A9322E20015FC5C /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
6369A2781A9322E20015FC5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
6369A27A1A9322E20015FC5C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
- C20055928615A6F8434E26B4 /* libPods-Sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Sample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Sample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E3C01DF315C4E7433BCEC6E6 /* Pods-Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -35,7 +35,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 426A5020E0E158A101BCA1D9 /* libPods-Sample.a in Frameworks */,
+ 3F035697392F601049D3DDE1 /* Pods_Sample.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -95,7 +95,7 @@
C4C2C5219053E079C9EFB930 /* Frameworks */ = {
isa = PBXGroup;
children = (
- C20055928615A6F8434E26B4 /* libPods-Sample.a */,
+ CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -129,7 +129,7 @@
6369A2621A9322E20015FC5C /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0610;
+ LastUpgradeCheck = 0730;
ORGANIZATIONNAME = gRPC;
TargetAttributes = {
6369A2691A9322E20015FC5C = {
@@ -260,6 +260,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -325,6 +326,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = Sample/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
@@ -336,6 +338,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = Sample/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
diff --git a/src/objective-c/examples/Sample/Sample/Info.plist b/src/objective-c/examples/Sample/Sample/Info.plist
index 4436635ab4..2cdf09dc2f 100644
--- a/src/objective-c/examples/Sample/Sample/Info.plist
+++ b/src/objective-c/examples/Sample/Sample/Info.plist
@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
- <string>org.grpc.$(PRODUCT_NAME:rfc1034identifier)</string>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
diff --git a/src/objective-c/examples/Sample/Sample/ViewController.m b/src/objective-c/examples/Sample/Sample/ViewController.m
index 433a8a2ba3..70244ee62d 100644
--- a/src/objective-c/examples/Sample/Sample/ViewController.m
+++ b/src/objective-c/examples/Sample/Sample/ViewController.m
@@ -66,9 +66,9 @@
// Same example call using the generic gRPC client library:
- ProtoMethod *method = [[ProtoMethod alloc] initWithPackage:@"grpc.testing"
- service:@"TestService"
- method:@"UnaryCall"];
+ GRPCProtoMethod *method = [[GRPCProtoMethod alloc] initWithPackage:@"grpc.testing"
+ service:@"TestService"
+ method:@"UnaryCall"];
GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]];
diff --git a/src/objective-c/examples/SwiftSample/Info.plist b/src/objective-c/examples/SwiftSample/Info.plist
index 10f0450b34..2cdf09dc2f 100644
--- a/src/objective-c/examples/SwiftSample/Info.plist
+++ b/src/objective-c/examples/SwiftSample/Info.plist
@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
- <string>io.grpc.$(PRODUCT_NAME:rfc1034identifier)</string>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
diff --git a/src/objective-c/examples/SwiftSample/Podfile b/src/objective-c/examples/SwiftSample/Podfile
index 2f783340f5..b08a346ae2 100644
--- a/src/objective-c/examples/SwiftSample/Podfile
+++ b/src/objective-c/examples/SwiftSample/Podfile
@@ -3,6 +3,8 @@ platform :ios, '8.0'
install! 'cocoapods', :deterministic_uuids => false
+use_frameworks!
+
# Location of gRPC's repo root relative to this file.
GRPC_LOCAL_SRC = '../../../..'
diff --git a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj
index 2a1b30f2cf..afc3da7116 100644
--- a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj
+++ b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj
@@ -7,11 +7,11 @@
objects = {
/* Begin PBXBuildFile section */
+ 2C0B024CB798839E17F76126 /* Pods_SwiftSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */; };
633BFFC81B950B210007E424 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC71B950B210007E424 /* AppDelegate.swift */; };
633BFFCA1B950B210007E424 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC91B950B210007E424 /* ViewController.swift */; };
633BFFCD1B950B210007E424 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCB1B950B210007E424 /* Main.storyboard */; };
633BFFCF1B950B210007E424 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCE1B950B210007E424 /* Images.xcassets */; };
- 92EDB1408A1E1E7DDAB25D9C /* libPods-SwiftSample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -21,9 +21,8 @@
633BFFC91B950B210007E424 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
633BFFCC1B950B210007E424 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
633BFFCE1B950B210007E424 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
- 6367AD231B951655007FD3A4 /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; };
- 69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SwiftSample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A7E614A494D89D01BB395761 /* Pods-SwiftSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftSample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample.debug.xcconfig"; sourceTree = "<group>"; };
+ B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftSample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C314E3E246AF23AC29B38FCF /* Pods-SwiftSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftSample.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -32,7 +31,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 92EDB1408A1E1E7DDAB25D9C /* libPods-SwiftSample.a in Frameworks */,
+ 2C0B024CB798839E17F76126 /* Pods_SwiftSample.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -74,7 +73,6 @@
633BFFCB1B950B210007E424 /* Main.storyboard */,
633BFFCE1B950B210007E424 /* Images.xcassets */,
633BFFC51B950B210007E424 /* Supporting Files */,
- 6367AD231B951655007FD3A4 /* Bridging-Header.h */,
);
name = SwiftSample;
sourceTree = SOURCE_ROOT;
@@ -90,7 +88,7 @@
9D63A7F6423989BA306810CA /* Frameworks */ = {
isa = PBXGroup;
children = (
- 69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */,
+ B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -125,7 +123,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0710;
- LastUpgradeCheck = 0640;
+ LastUpgradeCheck = 0730;
ORGANIZATIONNAME = gRPC;
TargetAttributes = {
633BFFC11B950B210007E424 = {
@@ -256,6 +254,7 @@
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -325,8 +324,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "io.grpc.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h";
+ SWIFT_OBJC_BRIDGING_HEADER = "";
USER_HEADER_SEARCH_PATHS = "";
};
name = Debug;
@@ -338,8 +338,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "io.grpc.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h";
+ SWIFT_OBJC_BRIDGING_HEADER = "";
USER_HEADER_SEARCH_PATHS = "";
};
name = Release;
diff --git a/src/objective-c/examples/SwiftSample/ViewController.swift b/src/objective-c/examples/SwiftSample/ViewController.swift
index 2a95d2de51..66d4fa9412 100644
--- a/src/objective-c/examples/SwiftSample/ViewController.swift
+++ b/src/objective-c/examples/SwiftSample/ViewController.swift
@@ -33,6 +33,8 @@
import UIKit
+import RemoteTest
+
class ViewController: UIViewController {
override func viewDidLoad() {
@@ -60,7 +62,7 @@ class ViewController: UIViewController {
// Same but manipulating headers:
- var RPC : ProtoRPC! // Needed to convince Swift to capture by reference (__block)
+ var RPC : GRPCProtoCall! // Needed to convince Swift to capture by reference (__block)
RPC = service.RPCToUnaryCallWithRequest(request) { response, error in
if let response = response {
NSLog("2. Finished successfully with response:\n\(response)")
@@ -79,7 +81,7 @@ class ViewController: UIViewController {
// Same example call using the generic gRPC client library:
- let method = ProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall")
+ let method = GRPCProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall")
let requestsWriter = GRXWriter(value: request.data())
@@ -89,7 +91,7 @@ class ViewController: UIViewController {
call.startWithWriteable(GRXWriteable { response, error in
if let response = response as? NSData {
- NSLog("3. Received response:\n\(RMTSimpleResponse(data: response, error: nil))")
+ NSLog("3. Received response:\n\(try! RMTSimpleResponse(data: response))")
} else {
NSLog("3. Finished with error: \(error!)")
}
diff --git a/src/objective-c/tests/CoreCronetEnd2EndTests/Info.plist b/src/objective-c/tests/CoreCronetEnd2EndTests/Info.plist
new file mode 100644
index 0000000000..fbeeb96ba6
--- /dev/null
+++ b/src/objective-c/tests/CoreCronetEnd2EndTests/Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>gRPC.$(PRODUCT_NAME:rfc1034identifier)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+</dict>
+</plist>
diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m
index 1167a715bb..916a335802 100644
--- a/src/objective-c/tests/GRPCClientTests.m
+++ b/src/objective-c/tests/GRPCClientTests.m
@@ -292,15 +292,6 @@ static GRPCProtoMethod *kUnaryCallMethod;
// TODO(makarandd): Move to a different file that contains only unit tests
- (void)testExceptions {
- // Try to set userAgentPrefix for host that is nil. This should cause
- // an exception.
- @try {
- [GRPCCall setUserAgentPrefix:@"Foo" forHost:nil];
- XCTFail(@"Did not receive an exception when host is nil");
- } @catch(NSException *theException) {
- NSLog(@"Received exception as expected: %@", theException.name);
- }
-
// Try to set parameters to nil for GRPCCall. This should cause an exception
@try {
(void)[[GRPCCall alloc] initWithHost:nil
diff --git a/src/objective-c/tests/InteropTests.h b/src/objective-c/tests/InteropTests.h
index 6d54343b13..ecab606a78 100644
--- a/src/objective-c/tests/InteropTests.h
+++ b/src/objective-c/tests/InteropTests.h
@@ -46,4 +46,11 @@
* Override in a subclass to perform these tests against a specific address.
*/
+ (NSString *)host;
+
+/**
+ * Bytes of overhead of test proto responses due to encoding. This is used to excercise the behavior
+ * when responses are just above or below the max response size. For some reason, the local and
+ * remote servers enconde responses with different overhead (?), so this is defined per-subclass.
+ */
+- (int32_t)encodingOverhead;
@end
diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m
index 494743d604..f04a7e6441 100644
--- a/src/objective-c/tests/InteropTests.m
+++ b/src/objective-c/tests/InteropTests.m
@@ -80,10 +80,6 @@
#pragma mark Tests
-#ifdef GRPC_COMPILE_WITH_CRONET
-static cronet_engine *cronetEngine = NULL;
-#endif
-
@implementation InteropTests {
RMTTestService *_service;
}
@@ -92,15 +88,22 @@ static cronet_engine *cronetEngine = NULL;
return nil;
}
+- (int32_t)encodingOverhead {
+ return 0;
+}
+
- (void)setUp {
+ self.continueAfterFailure = NO;
+
+ [GRPCCall resetHostSettings];
+
_service = self.class.host ? [RMTTestService serviceWithHost:self.class.host] : nil;
#ifdef GRPC_COMPILE_WITH_CRONET
if (cronetEngine == NULL) {
// Cronet setup
[Cronet setHttp2Enabled:YES];
[Cronet start];
- cronetEngine = [Cronet getGlobalEngine];
- [GRPCCall useCronetWithEngine:cronetEngine];
+ [GRPCCall useCronetWithEngine:[Cronet getGlobalEngine]];
}
#endif
}
@@ -146,6 +149,64 @@ static cronet_engine *cronetEngine = NULL;
[self waitForExpectationsWithTimeout:16 handler:nil];
}
+- (void)test4MBResponsesAreAccepted {
+ XCTAssertNotNil(self.class.host);
+ __weak XCTestExpectation *expectation = [self expectationWithDescription:@"MaxResponseSize"];
+
+ RMTSimpleRequest *request = [RMTSimpleRequest message];
+ const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead; // 4MB - encoding overhead
+ request.responseSize = kPayloadSize;
+
+ [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
+ XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+ XCTAssertEqual(response.payload.body.length, kPayloadSize);
+ [expectation fulfill];
+ }];
+
+ [self waitForExpectationsWithTimeout:16 handler:nil];
+}
+
+- (void)testResponsesOverMaxSizeFailWithActionableMessage {
+ XCTAssertNotNil(self.class.host);
+ __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"];
+
+ RMTSimpleRequest *request = [RMTSimpleRequest message];
+ const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead + 1; // 1B over max size
+ request.responseSize = kPayloadSize;
+
+ [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
+ // TODO(jcanizales): Catch the error and rethrow it with an actionable message:
+ // - Use +[GRPCCall setResponseSizeLimit:forHost:] to set a higher limit.
+ // - If you're developing the server, consider using response streaming, or let clients filter
+ // responses by setting a google.protobuf.FieldMask in the request:
+ // https://github.com/google/protobuf/blob/master/src/google/protobuf/field_mask.proto
+ XCTAssertEqualObjects(error.localizedDescription, @"Max message size exceeded");
+ [expectation fulfill];
+ }];
+
+ [self waitForExpectationsWithTimeout:16 handler:nil];
+}
+
+- (void)testResponsesOver4MBAreAcceptedIfOptedIn {
+ XCTAssertNotNil(self.class.host);
+ __weak XCTestExpectation *expectation =
+ [self expectationWithDescription:@"HigherResponseSizeLimit"];
+
+ RMTSimpleRequest *request = [RMTSimpleRequest message];
+ const size_t kPayloadSize = 5 * 1024 * 1024; // 5MB
+ request.responseSize = kPayloadSize;
+
+ [GRPCCall setResponseSizeLimit:6 * 1024 * 1024 forHost:self.class.host];
+
+ [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
+ XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+ XCTAssertEqual(response.payload.body.length, kPayloadSize);
+ [expectation fulfill];
+ }];
+
+ [self waitForExpectationsWithTimeout:16 handler:nil];
+}
+
- (void)testClientStreamingRPC {
XCTAssertNotNil(self.class.host);
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"];
diff --git a/src/objective-c/tests/InteropTestsLocalCleartext.m b/src/objective-c/tests/InteropTestsLocalCleartext.m
index 56927a8af6..b41210f50f 100644
--- a/src/objective-c/tests/InteropTestsLocalCleartext.m
+++ b/src/objective-c/tests/InteropTestsLocalCleartext.m
@@ -47,11 +47,15 @@ static NSString * const kLocalCleartextHost = @"localhost:5050";
return kLocalCleartextHost;
}
+- (int32_t)encodingOverhead {
+ return 10; // bytes
+}
+
- (void)setUp {
+ [super setUp];
+
// Register test server as non-SSL.
[GRPCCall useInsecureConnectionsForHost:kLocalCleartextHost];
-
- [super setUp];
}
@end
diff --git a/src/objective-c/tests/InteropTestsLocalSSL.m b/src/objective-c/tests/InteropTestsLocalSSL.m
index f0f4b1d71f..1479c5896c 100644
--- a/src/objective-c/tests/InteropTestsLocalSSL.m
+++ b/src/objective-c/tests/InteropTestsLocalSSL.m
@@ -47,14 +47,18 @@ static NSString * const kLocalSSLHost = @"localhost:5051";
return kLocalSSLHost;
}
+- (int32_t)encodingOverhead {
+ return 10; // bytes
+}
+
- (void)setUp {
+ [super setUp];
+
// Register test server certificates and name.
NSBundle *bundle = [NSBundle bundleForClass:self.class];
NSString *certsPath = [bundle pathForResource:@"TestCertificates.bundle/test-certificates"
ofType:@"pem"];
[GRPCCall useTestCertsPath:certsPath testName:@"foo.test.google.fr" forHost:kLocalSSLHost];
-
- [super setUp];
}
- (void)testExceptions {
diff --git a/src/objective-c/tests/InteropTestsRemote.m b/src/objective-c/tests/InteropTestsRemote.m
index 758cc9346a..70f84753bb 100644
--- a/src/objective-c/tests/InteropTestsRemote.m
+++ b/src/objective-c/tests/InteropTestsRemote.m
@@ -47,4 +47,8 @@ static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
return kRemoteSSLHost;
}
+- (int32_t)encodingOverhead {
+ return 12; // bytes
+}
+
@end
diff --git a/src/objective-c/tests/InteropTestsRemoteWithCronet/Info.plist b/src/objective-c/tests/InteropTestsRemoteWithCronet/Info.plist
new file mode 100644
index 0000000000..ba72822e87
--- /dev/null
+++ b/src/objective-c/tests/InteropTestsRemoteWithCronet/Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+</dict>
+</plist>
diff --git a/src/objective-c/examples/SwiftSample/Bridging-Header.h b/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m
index 65f768a760..fab8ad8d25 100644
--- a/src/objective-c/examples/SwiftSample/Bridging-Header.h
+++ b/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m
@@ -31,15 +31,20 @@
*
*/
-#ifndef SwiftSample_Bridging_Header_h
-#define SwiftSample_Bridging_Header_h
+#import <GRPCClient/GRPCCall+Tests.h>
-#import <RxLibrary/GRXWriteable.h>
-#import <RxLibrary/GRXWriter.h>
-#import <RxLibrary/GRXWriter+Immediate.h>
-#import <GRPCClient/GRPCCall.h>
-#import <ProtoRPC/ProtoMethod.h>
-#import <ProtoRPC/ProtoRPC.h>
-#import <RemoteTest/Test.pbrpc.h>
+#import "InteropTests.h"
-#endif
+static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
+
+/** Tests in InteropTests.m, sending the RPCs to a remote SSL server. */
+@interface InteropTestsRemoteWithCronet : InteropTests
+@end
+
+@implementation InteropTestsRemoteWithCronet
+
++ (NSString *)host {
+ return kRemoteSSLHost;
+}
+
+@end
diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile
index 17b9740d52..17478fab12 100644
--- a/src/objective-c/tests/Podfile
+++ b/src/objective-c/tests/Podfile
@@ -14,6 +14,7 @@ GRPC_LOCAL_SRC = '../../..'
InteropTestsRemote
InteropTestsLocalSSL
InteropTestsLocalCleartext
+ InteropTestsRemoteWithCronet
).each do |target_name|
target target_name do
pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true
@@ -22,17 +23,29 @@ GRPC_LOCAL_SRC = '../../..'
pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
- pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'gRPC', :path => GRPC_LOCAL_SRC
pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC
pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC
-
pod 'RemoteTest', :path => "RemoteTestClient"
+
+ if target_name == 'InteropTestsRemoteWithCronet'
+ pod 'gRPC-Core/Cronet-Implementation', :path => GRPC_LOCAL_SRC
+ pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
+ end
end
end
+target 'CoreCronetEnd2EndTests' do
+ pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
+ pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
+ pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
+ pod 'gRPC-Core/Cronet-Interface', :path => GRPC_LOCAL_SRC
+ pod 'gRPC-Core/Cronet-Implementation', :path => GRPC_LOCAL_SRC
+ pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC
+end
+
# gRPC-Core.podspec needs to be modified to be successfully used for local development. A Podfile's
# pre_install hook lets us do that. The block passed to it runs after the podspecs are downloaded
# and before they are installed in the user project.
@@ -69,7 +82,11 @@ post_install do |installer|
target.build_configurations.each do |config|
config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'YES'
end
- if target.name == 'gRPC-Core'
+
+ # CocoaPods creates duplicated library targets of gRPC-Core when the test targets include
+ # non-default subspecs of gRPC-Core. All of these library targets start with prefix 'gRPC-Core.'
+ # and require the same error suppresion.
+ if target.name == 'gRPC-Core' or target.name.start_with?('gRPC-Core.')
target.build_configurations.each do |config|
# TODO(zyc): Remove this setting after the issue is resolved
# GPR_UNREACHABLE_CODE causes "Control may reach end of non-void
@@ -77,5 +94,15 @@ post_install do |installer|
config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO'
end
end
+
+ # Activate Cronet for the dedicated build configuration 'Cronet', which will be used solely by
+ # the test target 'InteropTestsRemoteWithCronet'
+ if target.name == 'gRPC'
+ target.build_configurations.each do |config|
+ if config.name == 'Cronet'
+ config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_COMPILE_WITH_CRONET=1'
+ end
+ end
+ end
end
end
diff --git a/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec b/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
index 7d84a5ae4d..3d28234fa2 100644
--- a/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
+++ b/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
@@ -11,7 +11,7 @@ Pod::Spec.new do |s|
s.osx.deployment_target = '10.9'
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
- s.dependency "!ProtoCompiler-gRPCPlugin", "~> 0.14"
+ s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0.0-pre1.2"
repo_root = '../../../..'
bin_dir = "#{repo_root}/bins/$CONFIG"
diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
index f9389a4977..c4a6567ae0 100644
--- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
+++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
@@ -7,11 +7,18 @@
objects = {
/* Begin PBXBuildFile section */
+ 09B76D9585ACE7403804D9DC /* libPods-InteropTestsRemoteWithCronet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */; };
0F9232F984C08643FD40C34F /* libPods-InteropTestsRemote.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DBE059B4AC7A51919467EEC0 /* libPods-InteropTestsRemote.a */; };
16A9E77B6E336B3C0B9BA6E0 /* libPods-InteropTestsLocalSSL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */; };
20DFDF829DD993A4A00D5662 /* libPods-RxLibraryUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */; };
333E8FC01C8285B7C547D799 /* libPods-InteropTestsLocalCleartext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */; };
3D7C85F6AA68C4A205E3BA16 /* libPods-Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */; };
+ 5E8A5DA71D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m */; };
+ 5E8A5DA91D3840B4000F8BC4 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; };
+ 5EE84BF41D4717E40050C6CC /* InteropTestsRemoteWithCronet.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EE84BF31D4717E40050C6CC /* InteropTestsRemoteWithCronet.m */; };
+ 5EE84BF61D4717E40050C6CC /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; };
+ 5EE84BFE1D471D400050C6CC /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */; };
+ 60D2A57ED559F34428C2EEC5 /* libPods-CoreCronetEnd2EndTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */; };
6312AE4E1B1BF49B00341DEE /* GRPCClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */; };
63423F4A1B150A5F006CF63C /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; };
635697CD1B14FC11007A7283 /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635697CC1B14FC11007A7283 /* Tests.m */; };
@@ -38,6 +45,20 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
+ 5E8A5DAA1D3840B4000F8BC4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 635697BF1B14FC11007A7283 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 635697C61B14FC11007A7283;
+ remoteInfo = Tests;
+ };
+ 5EE84BF71D4717E40050C6CC /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 635697BF1B14FC11007A7283 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 635697C61B14FC11007A7283;
+ remoteInfo = Tests;
+ };
63423F4B1B150A5F006CF63C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 635697BF1B14FC11007A7283 /* Project object */;
@@ -91,12 +112,24 @@
060EF32D7EC0DF67ED617507 /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = "<group>"; };
07D10A965323BEA7FE59A74B /* Pods-RxLibraryUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.debug.xcconfig"; sourceTree = "<group>"; };
0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
+ 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.debug.xcconfig"; sourceTree = "<group>"; };
+ 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.cronet.xcconfig"; sourceTree = "<group>"; };
+ 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; sourceTree = "<group>"; };
20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
3B0861FC805389C52DB260D4 /* Pods-RxLibraryUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.release.xcconfig"; sourceTree = "<group>"; };
+ 3F27B2E744482771EB93C394 /* Pods-InteropTestsRemoteWithCronet.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.cronet.xcconfig"; sourceTree = "<group>"; };
+ 4AD97096D13D7416DC91A72A /* Pods-CoreCronetEnd2EndTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.release.xcconfig"; sourceTree = "<group>"; };
+ 4ADEA1C8BBE10D90940AC68E /* Pods-InteropTestsRemote.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.cronet.xcconfig"; sourceTree = "<group>"; };
51A275E86C141416ED63FF76 /* Pods-InteropTestsLocalCleartext.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.release.xcconfig"; sourceTree = "<group>"; };
553BBBED24E4162D1F769D65 /* Pods-InteropTestsLocalSSL.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.debug.xcconfig"; sourceTree = "<group>"; };
+ 573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; sourceTree = "<group>"; };
5761E98978DDDF136A58CB7E /* Pods-AllTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.release.xcconfig"; sourceTree = "<group>"; };
+ 5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreCronetEnd2EndTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CoreCronetEnd2EndTests.m; sourceTree = "<group>"; };
+ 5EE84BF11D4717E40050C6CC /* InteropTestsRemoteWithCronet.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsRemoteWithCronet.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 5EE84BF31D4717E40050C6CC /* InteropTestsRemoteWithCronet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InteropTestsRemoteWithCronet.m; sourceTree = "<group>"; };
+ 5EE84BF51D4717E40050C6CC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GRPCClientTests.m; sourceTree = "<group>"; };
63423F441B150A5F006CF63C /* AllTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AllTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
63423F501B151B77006CF63C /* RxLibraryUnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RxLibraryUnitTests.m; sourceTree = "<group>"; };
@@ -113,8 +146,12 @@
63E240CC1B6C4D3A005F3B0E /* InteropTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InteropTests.h; sourceTree = "<group>"; };
63E240CD1B6C4E2B005F3B0E /* InteropTestsLocalSSL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InteropTestsLocalSSL.m; sourceTree = "<group>"; };
63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = TestCertificates.bundle; sourceTree = "<group>"; };
+ 79C68EFFCB5533475D810B79 /* Pods-RxLibraryUnitTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.cronet.xcconfig"; sourceTree = "<group>"; };
7A2E97E3F469CC2A758D77DE /* Pods-InteropTestsLocalSSL.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.release.xcconfig"; sourceTree = "<group>"; };
+ 9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemoteWithCronet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RxLibraryUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.cronet.xcconfig"; sourceTree = "<group>"; };
+ AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.release.xcconfig"; sourceTree = "<group>"; };
B94C27C06733CF98CE1B2757 /* Pods-AllTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.debug.xcconfig"; sourceTree = "<group>"; };
CAE086D5B470DA367D415AB0 /* libPods-AllTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AllTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
DBE059B4AC7A51919467EEC0 /* libPods-InteropTestsRemote.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemote.a"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -123,11 +160,32 @@
E1486220285AF123EB124008 /* Pods-InteropTestsLocalCleartext.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.debug.xcconfig"; sourceTree = "<group>"; };
E4275A759BDBDF143B9B438F /* Pods-InteropTestsRemote.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.release.xcconfig"; sourceTree = "<group>"; };
E6733B838B28453434B556E2 /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = "<group>"; };
+ E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.cronet.xcconfig"; sourceTree = "<group>"; };
+ F671D4CAD2864FB203B920B4 /* Pods-Tests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.cronet.xcconfig"; sourceTree = "<group>"; };
+ FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CoreCronetEnd2EndTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalCleartext.a"; sourceTree = BUILT_PRODUCTS_DIR; };
FF7B5489BCFE40111D768DD0 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
+ 5E8A5DA11D3840B4000F8BC4 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 5E8A5DA91D3840B4000F8BC4 /* libTests.a in Frameworks */,
+ 60D2A57ED559F34428C2EEC5 /* libPods-CoreCronetEnd2EndTests.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 5EE84BEE1D4717E40050C6CC /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 5EE84BF61D4717E40050C6CC /* libTests.a in Frameworks */,
+ 09B76D9585ACE7403804D9DC /* libPods-InteropTestsRemoteWithCronet.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
63423F411B150A5F006CF63C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -194,6 +252,8 @@
DBE059B4AC7A51919467EEC0 /* libPods-InteropTestsRemote.a */,
A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */,
20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */,
+ FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */,
+ 9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -215,15 +275,46 @@
3B0861FC805389C52DB260D4 /* Pods-RxLibraryUnitTests.release.xcconfig */,
060EF32D7EC0DF67ED617507 /* Pods-Tests.debug.xcconfig */,
E6733B838B28453434B556E2 /* Pods-Tests.release.xcconfig */,
+ 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */,
+ 4AD97096D13D7416DC91A72A /* Pods-CoreCronetEnd2EndTests.release.xcconfig */,
+ 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */,
+ AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */,
+ E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */,
+ 573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */,
+ AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */,
+ 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */,
+ 4ADEA1C8BBE10D90940AC68E /* Pods-InteropTestsRemote.cronet.xcconfig */,
+ 3F27B2E744482771EB93C394 /* Pods-InteropTestsRemoteWithCronet.cronet.xcconfig */,
+ 79C68EFFCB5533475D810B79 /* Pods-RxLibraryUnitTests.cronet.xcconfig */,
+ F671D4CAD2864FB203B920B4 /* Pods-Tests.cronet.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
+ 5E8A5DA51D3840B4000F8BC4 /* CoreCronetEnd2EndTests */ = {
+ isa = PBXGroup;
+ children = (
+ 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m */,
+ );
+ path = CoreCronetEnd2EndTests;
+ sourceTree = "<group>";
+ };
+ 5EE84BF21D4717E40050C6CC /* InteropTestsRemoteWithCronet */ = {
+ isa = PBXGroup;
+ children = (
+ 5EE84BF31D4717E40050C6CC /* InteropTestsRemoteWithCronet.m */,
+ 5EE84BF51D4717E40050C6CC /* Info.plist */,
+ );
+ path = InteropTestsRemoteWithCronet;
+ sourceTree = "<group>";
+ };
635697BE1B14FC11007A7283 = {
isa = PBXGroup;
children = (
635697C91B14FC11007A7283 /* Tests */,
63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */,
+ 5E8A5DA51D3840B4000F8BC4 /* CoreCronetEnd2EndTests */,
+ 5EE84BF21D4717E40050C6CC /* InteropTestsRemoteWithCronet */,
635697C81B14FC11007A7283 /* Products */,
51E4650F34F854F41FF053B3 /* Pods */,
136D535E19727099B941D7B1 /* Frameworks */,
@@ -239,6 +330,8 @@
63DC84231BE15267000708E8 /* InteropTestsRemote.xctest */,
63DC84341BE15294000708E8 /* InteropTestsLocalSSL.xctest */,
63DC84431BE152B5000708E8 /* InteropTestsLocalCleartext.xctest */,
+ 5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */,
+ 5EE84BF11D4717E40050C6CC /* InteropTestsRemoteWithCronet.xctest */,
);
name = Products;
sourceTree = "<group>";
@@ -270,6 +363,48 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
+ 5E8A5DA31D3840B4000F8BC4 /* CoreCronetEnd2EndTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 5E8A5DAE1D3840B4000F8BC4 /* Build configuration list for PBXNativeTarget "CoreCronetEnd2EndTests" */;
+ buildPhases = (
+ F58F17E425446B15028B9F74 /* [CP] Check Pods Manifest.lock */,
+ 5E8A5DA01D3840B4000F8BC4 /* Sources */,
+ 5E8A5DA11D3840B4000F8BC4 /* Frameworks */,
+ 5E8A5DA21D3840B4000F8BC4 /* Resources */,
+ E63468C760D0724F18861822 /* [CP] Embed Pods Frameworks */,
+ 6DFE9E77CAB5760196D79E0F /* [CP] Copy Pods Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 5E8A5DAB1D3840B4000F8BC4 /* PBXTargetDependency */,
+ );
+ name = CoreCronetEnd2EndTests;
+ productName = CoreCronetEnd2EndTests;
+ productReference = 5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ 5EE84BF01D4717E40050C6CC /* InteropTestsRemoteWithCronet */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 5EE84BFB1D4717E40050C6CC /* Build configuration list for PBXNativeTarget "InteropTestsRemoteWithCronet" */;
+ buildPhases = (
+ C0F7B1FF6F88CC5FBF362F4C /* [CP] Check Pods Manifest.lock */,
+ 5EE84BED1D4717E40050C6CC /* Sources */,
+ 5EE84BEE1D4717E40050C6CC /* Frameworks */,
+ 5EE84BEF1D4717E40050C6CC /* Resources */,
+ 31F8D1C407195CBF0C02929B /* [CP] Embed Pods Frameworks */,
+ DB4D0E73C229F2FF3B364AB3 /* [CP] Copy Pods Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 5EE84BF81D4717E40050C6CC /* PBXTargetDependency */,
+ );
+ name = InteropTestsRemoteWithCronet;
+ productName = InteropTestsRemoteWithCronet;
+ productReference = 5EE84BF11D4717E40050C6CC /* InteropTestsRemoteWithCronet.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
63423F431B150A5F006CF63C /* AllTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 63423F4D1B150A5F006CF63C /* Build configuration list for PBXNativeTarget "AllTests" */;
@@ -403,6 +538,12 @@
LastUpgradeCheck = 0630;
ORGANIZATIONNAME = gRPC;
TargetAttributes = {
+ 5E8A5DA31D3840B4000F8BC4 = {
+ CreatedOnToolsVersion = 7.3.1;
+ };
+ 5EE84BF01D4717E40050C6CC = {
+ CreatedOnToolsVersion = 7.3.1;
+ };
63423F431B150A5F006CF63C = {
CreatedOnToolsVersion = 6.3.1;
};
@@ -441,11 +582,27 @@
63DC84221BE15267000708E8 /* InteropTestsRemote */,
63DC84331BE15294000708E8 /* InteropTestsLocalSSL */,
63DC84421BE152B5000708E8 /* InteropTestsLocalCleartext */,
+ 5E8A5DA31D3840B4000F8BC4 /* CoreCronetEnd2EndTests */,
+ 5EE84BF01D4717E40050C6CC /* InteropTestsRemoteWithCronet */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
+ 5E8A5DA21D3840B4000F8BC4 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 5EE84BEF1D4717E40050C6CC /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
63423F421B150A5F006CF63C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -486,6 +643,21 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
+ 31F8D1C407195CBF0C02929B /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
4C406327D3907A5E5FBA8AC9 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -561,6 +733,21 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL-resources.sh\"\n";
showEnvVarsInLog = 0;
};
+ 6DFE9E77CAB5760196D79E0F /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Copy Pods Resources";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
7418AC7B3844B29E48D24FC7 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -696,6 +883,21 @@
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
+ C0F7B1FF6F88CC5FBF362F4C /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
+ showEnvVarsInLog = 0;
+ };
C2E09DC4BD239F71160F0CC1 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -741,9 +943,71 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
+ DB4D0E73C229F2FF3B364AB3 /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Copy Pods Resources";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ E63468C760D0724F18861822 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ F58F17E425446B15028B9F74 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
+ showEnvVarsInLog = 0;
+ };
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ 5E8A5DA01D3840B4000F8BC4 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 5E8A5DA71D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 5EE84BED1D4717E40050C6CC /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 5EE84BFE1D471D400050C6CC /* InteropTests.m in Sources */,
+ 5EE84BF41D4717E40050C6CC /* InteropTestsRemoteWithCronet.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
63423F401B150A5F006CF63C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -804,6 +1068,16 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
+ 5E8A5DAB1D3840B4000F8BC4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 635697C61B14FC11007A7283 /* Tests */;
+ targetProxy = 5E8A5DAA1D3840B4000F8BC4 /* PBXContainerItemProxy */;
+ };
+ 5EE84BF81D4717E40050C6CC /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 635697C61B14FC11007A7283 /* Tests */;
+ targetProxy = 5EE84BF71D4717E40050C6CC /* PBXContainerItemProxy */;
+ };
63423F4C1B150A5F006CF63C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 635697C61B14FC11007A7283 /* Tests */;
@@ -832,6 +1106,248 @@
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
+ 5E8A5DAC1D3840B4000F8BC4 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ INFOPLIST_FILE = CoreCronetEnd2EndTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CoreCronetEnd2EndTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ USER_HEADER_SEARCH_PATHS = "$(inherited) \"${PODS_ROOT}/../../../..\"";
+ };
+ name = Debug;
+ };
+ 5E8A5DAD1D3840B4000F8BC4 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 4AD97096D13D7416DC91A72A /* Pods-CoreCronetEnd2EndTests.release.xcconfig */;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ INFOPLIST_FILE = CoreCronetEnd2EndTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CoreCronetEnd2EndTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ USER_HEADER_SEARCH_PATHS = "$(inherited) \"${PODS_ROOT}/../../../..\"";
+ };
+ name = Release;
+ };
+ 5EC3C7A01D4FC18C000330E2 /* Cronet */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.3;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ };
+ name = Cronet;
+ };
+ 5EC3C7A11D4FC18C000330E2 /* Cronet */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F671D4CAD2864FB203B920B4 /* Pods-Tests.cronet.xcconfig */;
+ buildSettings = {
+ GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ };
+ name = Cronet;
+ };
+ 5EC3C7A21D4FC18C000330E2 /* Cronet */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(SDKROOT)/Developer/Library/Frameworks",
+ "$(inherited)",
+ );
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ INFOPLIST_FILE = Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Cronet;
+ };
+ 5EC3C7A31D4FC18C000330E2 /* Cronet */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 79C68EFFCB5533475D810B79 /* Pods-RxLibraryUnitTests.cronet.xcconfig */;
+ buildSettings = {
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ INFOPLIST_FILE = Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.RxLibraryUnitTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Cronet;
+ };
+ 5EC3C7A41D4FC18C000330E2 /* Cronet */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 4ADEA1C8BBE10D90940AC68E /* Pods-InteropTestsRemote.cronet.xcconfig */;
+ buildSettings = {
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ INFOPLIST_FILE = Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Cronet;
+ };
+ 5EC3C7A51D4FC18C000330E2 /* Cronet */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */;
+ buildSettings = {
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ INFOPLIST_FILE = Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalSSL;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Cronet;
+ };
+ 5EC3C7A61D4FC18C000330E2 /* Cronet */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */;
+ buildSettings = {
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ INFOPLIST_FILE = Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalCleartext;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Cronet;
+ };
+ 5EC3C7A71D4FC18C000330E2 /* Cronet */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ INFOPLIST_FILE = CoreCronetEnd2EndTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CoreCronetEnd2EndTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ USER_HEADER_SEARCH_PATHS = "$(inherited) \"${PODS_ROOT}/../../../..\"";
+ };
+ name = Cronet;
+ };
+ 5EC3C7A81D4FC18C000330E2 /* Cronet */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 3F27B2E744482771EB93C394 /* Pods-InteropTestsRemoteWithCronet.cronet.xcconfig */;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "COCOAPODS=1",
+ "$(inherited)",
+ "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1",
+ "GRPC_COMPILE_WITH_CRONET=1",
+ );
+ INFOPLIST_FILE = InteropTestsRemoteWithCronet/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsRemoteWithCronet;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Cronet;
+ };
+ 5EE84BF91D4717E40050C6CC /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "COCOAPODS=1",
+ "$(inherited)",
+ "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1",
+ );
+ INFOPLIST_FILE = InteropTestsRemoteWithCronet/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsRemoteWithCronet;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 5EE84BFA1D4717E40050C6CC /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "COCOAPODS=1",
+ "$(inherited)",
+ "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1",
+ "GRPC_COMPILE_WITH_CRONET=1",
+ );
+ INFOPLIST_FILE = InteropTestsRemoteWithCronet/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsRemoteWithCronet;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
63423F4E1B150A5F006CF63C /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = B94C27C06733CF98CE1B2757 /* Pods-AllTests.debug.xcconfig */;
@@ -1071,10 +1587,31 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
+ 5E8A5DAE1D3840B4000F8BC4 /* Build configuration list for PBXNativeTarget "CoreCronetEnd2EndTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 5E8A5DAC1D3840B4000F8BC4 /* Debug */,
+ 5EC3C7A71D4FC18C000330E2 /* Cronet */,
+ 5E8A5DAD1D3840B4000F8BC4 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 5EE84BFB1D4717E40050C6CC /* Build configuration list for PBXNativeTarget "InteropTestsRemoteWithCronet" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 5EE84BF91D4717E40050C6CC /* Debug */,
+ 5EC3C7A81D4FC18C000330E2 /* Cronet */,
+ 5EE84BFA1D4717E40050C6CC /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
63423F4D1B150A5F006CF63C /* Build configuration list for PBXNativeTarget "AllTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
63423F4E1B150A5F006CF63C /* Debug */,
+ 5EC3C7A21D4FC18C000330E2 /* Cronet */,
63423F4F1B150A5F006CF63C /* Release */,
);
defaultConfigurationIsVisible = 0;
@@ -1084,6 +1621,7 @@
isa = XCConfigurationList;
buildConfigurations = (
635697D91B14FC11007A7283 /* Debug */,
+ 5EC3C7A01D4FC18C000330E2 /* Cronet */,
635697DA1B14FC11007A7283 /* Release */,
);
defaultConfigurationIsVisible = 0;
@@ -1093,6 +1631,7 @@
isa = XCConfigurationList;
buildConfigurations = (
635697DC1B14FC11007A7283 /* Debug */,
+ 5EC3C7A11D4FC18C000330E2 /* Cronet */,
635697DD1B14FC11007A7283 /* Release */,
);
defaultConfigurationIsVisible = 0;
@@ -1102,6 +1641,7 @@
isa = XCConfigurationList;
buildConfigurations = (
63DC841C1BE15179000708E8 /* Debug */,
+ 5EC3C7A31D4FC18C000330E2 /* Cronet */,
63DC841D1BE15179000708E8 /* Release */,
);
defaultConfigurationIsVisible = 0;
@@ -1111,6 +1651,7 @@
isa = XCConfigurationList;
buildConfigurations = (
63DC842C1BE15267000708E8 /* Debug */,
+ 5EC3C7A41D4FC18C000330E2 /* Cronet */,
63DC842D1BE15267000708E8 /* Release */,
);
defaultConfigurationIsVisible = 0;
@@ -1120,6 +1661,7 @@
isa = XCConfigurationList;
buildConfigurations = (
63DC843D1BE15294000708E8 /* Debug */,
+ 5EC3C7A51D4FC18C000330E2 /* Cronet */,
63DC843E1BE15294000708E8 /* Release */,
);
defaultConfigurationIsVisible = 0;
@@ -1129,6 +1671,7 @@
isa = XCConfigurationList;
buildConfigurations = (
63DC844C1BE152B5000708E8 /* Debug */,
+ 5EC3C7A61D4FC18C000330E2 /* Cronet */,
63DC844D1BE152B5000708E8 /* Release */,
);
defaultConfigurationIsVisible = 0;
diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
index e6a052a8ce..d1d616c4cf 100644
--- a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
+++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
@@ -39,12 +39,6 @@
</BuildableReference>
<SkippedTests>
<Test
- Identifier = "GRPCClientTests/testConnectionToRemoteServer">
- </Test>
- <Test
- Identifier = "GRPCClientTests/testMetadata">
- </Test>
- <Test
Identifier = "InteropTests">
</Test>
<Test
diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/CoreCronetEnd2EndTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/CoreCronetEnd2EndTests.xcscheme
new file mode 100644
index 0000000000..a1da2e0c97
--- /dev/null
+++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/CoreCronetEnd2EndTests.xcscheme
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0730"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "NO"
+ buildForArchiving = "NO"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4"
+ BuildableName = "CoreCronetEnd2EndTests.xctest"
+ BlueprintName = "CoreCronetEnd2EndTests"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4"
+ BuildableName = "CoreCronetEnd2EndTests.xctest"
+ BlueprintName = "CoreCronetEnd2EndTests"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </TestableReference>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4"
+ BuildableName = "CoreCronetEnd2EndTests.xctest"
+ BlueprintName = "CoreCronetEnd2EndTests"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4"
+ BuildableName = "CoreCronetEnd2EndTests.xctest"
+ BlueprintName = "CoreCronetEnd2EndTests"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4"
+ BuildableName = "CoreCronetEnd2EndTests.xctest"
+ BlueprintName = "CoreCronetEnd2EndTests"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemoteWithCronet.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemoteWithCronet.xcscheme
new file mode 100644
index 0000000000..1d211115f7
--- /dev/null
+++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemoteWithCronet.xcscheme
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0730"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "NO"
+ buildForArchiving = "NO"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5EE84BF01D4717E40050C6CC"
+ BuildableName = "InteropTestsRemoteWithCronet.xctest"
+ BlueprintName = "InteropTestsRemoteWithCronet"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Cronet"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5EE84BF01D4717E40050C6CC"
+ BuildableName = "InteropTestsRemoteWithCronet.xctest"
+ BlueprintName = "InteropTestsRemoteWithCronet"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ <SkippedTests>
+ <Test
+ Identifier = "InteropTests">
+ </Test>
+ </SkippedTests>
+ </TestableReference>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5EE84BF01D4717E40050C6CC"
+ BuildableName = "InteropTestsRemoteWithCronet.xctest"
+ BlueprintName = "InteropTestsRemoteWithCronet"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Cronet"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5EE84BF01D4717E40050C6CC"
+ BuildableName = "InteropTestsRemoteWithCronet.xctest"
+ BlueprintName = "InteropTestsRemoteWithCronet"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Cronet"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5EE84BF01D4717E40050C6CC"
+ BuildableName = "InteropTestsRemoteWithCronet.xctest"
+ BlueprintName = "InteropTestsRemoteWithCronet"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Cronet">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Cronet"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/src/objective-c/tests/build_example_test.sh b/src/objective-c/tests/build_example_test.sh
index 5c3766b4c0..ae75941ec6 100755
--- a/src/objective-c/tests/build_example_test.sh
+++ b/src/objective-c/tests/build_example_test.sh
@@ -31,44 +31,33 @@
# Don't run this script standalone. Instead, run from the repository root:
# ./tools/run_tests/run_tests.py -l objc
-set -eo pipefail
+set -evo pipefail
cd `dirname $0`
-BINDIR=`pwd`/../../../bins/$CONFIG
-TMP_PATH=$PATH
-
-# If `protoc` is not found, add bins/$CONFIG/protobuf/protoc to the search path
-hash protoc 2>/dev/null || TMP_PATH=$BINDIR/protobuf:$TMP_PATH
-
-# If `protoc-gen-objcgrpc` is not found, make a symlink from
-# bins/$CONGIF/grpc_objective_c_plugin and add it to the search path
-PATH=$TMP_PATH hash protoc-gen-objcgrpc 2>/dev/null || {
- ln -sf $BINDIR/grpc_objective_c_plugin $BINDIR/protoc-gen-objcgrpc
- TMP_PATH=$BINDIR:$TMP_PATH
-}
-
SCHEME=HelloWorld \
EXAMPLE_PATH=examples/objective-c/helloworld \
- PATH=$TMP_PATH \
./build_one_example.sh
SCHEME=RouteGuideClient \
EXAMPLE_PATH=examples/objective-c/route_guide \
- PATH=$TMP_PATH \
./build_one_example.sh
SCHEME=AuthSample \
EXAMPLE_PATH=examples/objective-c/auth_sample \
- PATH=$TMP_PATH \
+ ./build_one_example.sh
+
+rm -f ../examples/RemoteTestClient/*.{h,m}
+
+SCHEME=Sample \
+ EXAMPLE_PATH=src/objective-c/examples/Sample \
./build_one_example.sh
SCHEME=Sample \
EXAMPLE_PATH=src/objective-c/examples/Sample \
- PATH=$TMP_PATH \
+ FRAMEWORKS=YES \
./build_one_example.sh
SCHEME=SwiftSample \
EXAMPLE_PATH=src/objective-c/examples/SwiftSample \
- PATH=$TMP_PATH \
./build_one_example.sh
diff --git a/src/objective-c/tests/build_one_example.sh b/src/objective-c/tests/build_one_example.sh
index 24fb8b7bab..9fef6582a3 100755
--- a/src/objective-c/tests/build_one_example.sh
+++ b/src/objective-c/tests/build_one_example.sh
@@ -31,7 +31,7 @@
# Don't run this script standalone. Instead, run from the repository root:
# ./tools/run_tests/run_tests.py -l objc
-set -e
+set -ev
# Params:
# EXAMPLE_PATH - directory of the example
@@ -54,7 +54,7 @@ pod install
set -o pipefail
XCODEBUILD_FILTER='(^===|^\*\*|\bfatal\b|\berror\b|\bwarning\b|\bfail)'
xcodebuild \
- clean build \
+ build \
-workspace *.xcworkspace \
-scheme $SCHEME \
-destination name="iPhone 6" \
diff --git a/src/objective-c/tests/build_tests.sh b/src/objective-c/tests/build_tests.sh
index 8547bfd3a8..bc5bc04494 100755
--- a/src/objective-c/tests/build_tests.sh
+++ b/src/objective-c/tests/build_tests.sh
@@ -44,26 +44,10 @@ hash xcodebuild 2>/dev/null || {
exit 1
}
-BINDIR=../../../bins/$CONFIG
-
-if [ ! -f $BINDIR/protobuf/protoc ]; then
- hash protoc 2>/dev/null || {
- echo >&2 "Can't find protoc. Make sure run_tests.py is making" \
- "grpc_objective_c_plugin before calling this script."
- exit 1
- }
- # When protoc is already installed, make doesn't compile one. Put a link
- # there so the podspecs can do codegen using that path.
- mkdir -p $BINDIR/protobuf
- ln -s `which protoc` $BINDIR/protobuf/protoc
-fi
-
-[ -f $BINDIR/interop_server ] || {
- echo >&2 "Can't find the test server. Make sure run_tests.py is making" \
- "interop_server before calling this script. It needs to be done" \
- "before because pod install of gRPC renames some C gRPC files" \
- "and not the server's code references to them."
- exit 1
-}
+# clean the directory
+rm -rf Pods
+rm -rf Tests.xcworkspace
+rm -f Podfile.lock
+rm -f RemoteTestClient/*.{h,m}
pod install
diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh
index c4fc5644f2..a265149f48 100755
--- a/src/objective-c/tests/run_tests.sh
+++ b/src/objective-c/tests/run_tests.sh
@@ -31,13 +31,21 @@
# Don't run this script standalone. Instead, run from the repository root:
# ./tools/run_tests/run_tests.py -l objc
-set -e
+set -ev
cd $(dirname $0)
# Run the tests server.
-../../../bins/$CONFIG/interop_server --port=5050 &
-../../../bins/$CONFIG/interop_server --port=5051 --use_tls &
+
+BINDIR=../../../bins/$CONFIG
+
+[ -f $BINDIR/interop_server ] || {
+ echo >&2 "Can't find the test server. Make sure run_tests.py is making" \
+ "interop_server before calling this script."
+ exit 1
+}
+$BINDIR/interop_server --port=5050 &
+$BINDIR/interop_server --port=5051 --use_tls &
# Kill them when this script exits.
trap 'kill -9 `jobs -p`' EXIT
diff --git a/src/php/README.md b/src/php/README.md
index 8abedc40a3..7e9819b256 100644
--- a/src/php/README.md
+++ b/src/php/README.md
@@ -9,23 +9,12 @@ GA
## Environment
-Prerequisite: `php` >=5.5, `phpize`, `pecl`, `phpunit`
-
-**Linux (Debian):**
-
-```sh
-$ sudo apt-get install php5 php5-dev php-pear
-```
-
-**Linux (CentOS):**
-
-```sh
-$ yum install php55w
-$ yum --enablerepo=remi,remi-php55 install php-devel php-pear
-```
-
-**Mac OS X:**
+Prerequisite:
+* `php` 5.5 or above, 7.0 or above
+* `pear` and `pecl`
+* `phpunit`
+**PEAR:**
```sh
$ curl -O http://pear.php.net/go-pear.phar
$ sudo php -d detect_unicode=0 go-pear.phar
@@ -72,13 +61,7 @@ $ sudo make install
### gRPC PHP extension
-Install the gRPC PHP extension from PECL
-
-```sh
-$ sudo pecl install grpc
-```
-
-Or, compile from source
+Compile the gRPC PHP extension
```sh
$ cd grpc/src/php/ext/grpc
@@ -148,12 +131,8 @@ Alternatively, you can download `protoc` binaries from [the protocol buffers Git
You need to install `protoc-gen-php` to generate stub class `.php` files from service definition `.proto` files.
```sh
-$ cd grpc/src/php/vendor/stanley-cheung/protobuf-php # if you had run `composer install` in the previous step
-
-OR
-
-$ git clone https://github.com/stanley-cheung/Protobuf-PHP # clone from github repo
-
+$ git clone https://github.com/stanley-cheung/Protobuf-PHP
+$ cd Protobuf-PHP
$ gem install rake ronn
$ rake pear:package version=1.0
$ sudo pear install Protobuf-1.0.tgz
@@ -175,7 +154,7 @@ Run a local server serving the math services. Please see [Node][] for how to run
```sh
$ cd grpc
$ npm install
-$ nodejs src/node/test/math/math_server.js
+$ node src/node/test/math/math_server.js
```
### Run test client
@@ -212,7 +191,7 @@ Make sure the Node math server is still running, as above.
```sh
$ cd grpc
$ npm install
-$ nodejs src/node/test/math/math_server.js
+$ node src/node/test/math/math_server.js
```
Make sure you have run `composer install` to generate the `vendor/autoload.php` file
@@ -282,7 +261,7 @@ Make sure the Node math server is still running, as above.
```sh
$ cd grpc
$ npm install
-$ nodejs src/node/test/math/math_server.js
+$ node src/node/test/math/math_server.js
```
Make sure you have run `composer install` to generate the `vendor/autoload.php` file
diff --git a/src/php/bin/determine_extension_dir.sh b/src/php/bin/determine_extension_dir.sh
index b4342ac89f..a59882506f 100755
--- a/src/php/bin/determine_extension_dir.sh
+++ b/src/php/bin/determine_extension_dir.sh
@@ -29,11 +29,7 @@
# 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 && \
- 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
+if [ ! -e $default_extension_dir/grpc.so ]; then
# the grpc extension is not found in the default PHP extension dir
# try the source modules directory
module_dir=../ext/grpc/modules
diff --git a/src/php/composer.json b/src/php/composer.json
index 23bfcedbe6..571f30013f 100644
--- a/src/php/composer.json
+++ b/src/php/composer.json
@@ -5,10 +5,12 @@
"keywords": ["rpc"],
"homepage": "http://grpc.io",
"license": "BSD-3-Clause",
- "version": "1.0.0",
+ "version": "1.1.0",
"require": {
"php": ">=5.5.0",
- "stanley-cheung/protobuf-php": "dev-master",
+ "stanley-cheung/protobuf-php": "v0.6"
+ },
+ "require-dev": {
"google/auth": "v0.9"
},
"autoload": {
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index 2cd45f10dc..66ca1513ed 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -58,63 +58,44 @@
#include "byte_buffer.h"
zend_class_entry *grpc_ce_call;
+#if PHP_MAJOR_VERSION >= 7
+static zend_object_handlers call_ce_handlers;
+#endif
/* Frees and destroys an instance of wrapped_grpc_call */
-void free_wrapped_grpc_call(void *object TSRMLS_DC) {
- wrapped_grpc_call *call = (wrapped_grpc_call *)object;
- if (call->owned && call->wrapped != NULL) {
- grpc_call_destroy(call->wrapped);
+PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_call)
+ if (p->owned && p->wrapped != NULL) {
+ grpc_call_destroy(p->wrapped);
}
- efree(call);
-}
+PHP_GRPC_FREE_WRAPPED_FUNC_END()
/* Initializes an instance of wrapped_grpc_call to be associated with an object
* of a class specified by class_type */
-zend_object_value create_wrapped_grpc_call(zend_class_entry *class_type
- TSRMLS_DC) {
- zend_object_value retval;
- wrapped_grpc_call *intern;
-
- intern = (wrapped_grpc_call *)emalloc(sizeof(wrapped_grpc_call));
- memset(intern, 0, sizeof(wrapped_grpc_call));
-
+php_grpc_zend_object create_wrapped_grpc_call(zend_class_entry *class_type
+ TSRMLS_DC) {
+ PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_call);
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
object_properties_init(&intern->std, class_type);
- retval.handle = zend_objects_store_put(
- intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
- free_wrapped_grpc_call, NULL TSRMLS_CC);
- retval.handlers = zend_get_std_object_handlers();
- return retval;
-}
-
-/* Wraps a grpc_call struct in a PHP object. Owned indicates whether the struct
- should be destroyed at the end of the object's lifecycle */
-zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC) {
- zval *call_object;
- MAKE_STD_ZVAL(call_object);
- object_init_ex(call_object, grpc_ce_call);
- wrapped_grpc_call *call =
- (wrapped_grpc_call *)zend_object_store_get_object(call_object TSRMLS_CC);
- call->wrapped = wrapped;
- call->owned = owned;
- return call_object;
+ PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_call, call_ce_handlers);
}
/* Creates and returns a PHP array object with the data in a
* grpc_metadata_array. Returns NULL on failure */
-zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC) {
+zval *grpc_parse_metadata_array(grpc_metadata_array
+ *metadata_array TSRMLS_DC) {
int count = metadata_array->count;
grpc_metadata *elements = metadata_array->metadata;
- int i;
zval *array;
- zval **data = NULL;
+ PHP_GRPC_MAKE_STD_ZVAL(array);
+ array_init(array);
+ int i;
HashTable *array_hash;
zval *inner_array;
char *str_key;
char *str_val;
size_t key_len;
- MAKE_STD_ZVAL(array);
- array_init(array);
+ zval *data = NULL;
+
array_hash = Z_ARRVAL_P(array);
grpc_metadata *elem;
for (i = 0; i < count; i++) {
@@ -124,9 +105,9 @@ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC) {
memcpy(str_key, elem->key, key_len);
str_val = ecalloc(elem->value_length + 1, sizeof(char));
memcpy(str_val, elem->value, elem->value_length);
- if (zend_hash_find(array_hash, str_key, key_len, (void **)data) ==
- SUCCESS) {
- if (Z_TYPE_P(*data) != IS_ARRAY) {
+ if (php_grpc_zend_hash_find(array_hash, str_key, key_len, (void **)&data)
+ == SUCCESS) {
+ if (Z_TYPE_P(data) != IS_ARRAY) {
zend_throw_exception(zend_exception_get_default(TSRMLS_C),
"Metadata hash somehow contains wrong types.",
1 TSRMLS_CC);
@@ -134,11 +115,13 @@ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC) {
efree(str_val);
return NULL;
}
- add_next_index_stringl(*data, str_val, elem->value_length, false);
+ php_grpc_add_next_index_stringl(data, str_val, elem->value_length,
+ false);
} else {
- MAKE_STD_ZVAL(inner_array);
+ PHP_GRPC_MAKE_STD_ZVAL(inner_array);
array_init(inner_array);
- add_next_index_stringl(inner_array, str_val, elem->value_length, false);
+ php_grpc_add_next_index_stringl(inner_array, str_val,
+ elem->value_length, false);
add_assoc_zval(array, str_key, inner_array);
}
}
@@ -148,61 +131,65 @@ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC) {
/* Populates a grpc_metadata_array with the data in a PHP array object.
Returns true on success and false on failure */
bool create_metadata_array(zval *array, grpc_metadata_array *metadata) {
- zval **inner_array;
- zval **value;
HashTable *array_hash;
- HashPosition array_pointer;
HashTable *inner_array_hash;
- HashPosition inner_array_pointer;
- char *key;
- uint key_len;
- ulong index;
+ zval *value;
+ zval *inner_array;
if (Z_TYPE_P(array) != IS_ARRAY) {
return false;
}
grpc_metadata_array_init(metadata);
array_hash = Z_ARRVAL_P(array);
- for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer);
- zend_hash_get_current_data_ex(array_hash, (void**)&inner_array,
- &array_pointer) == SUCCESS;
- zend_hash_move_forward_ex(array_hash, &array_pointer)) {
- if (zend_hash_get_current_key_ex(array_hash, &key, &key_len, &index, 0,
- &array_pointer) != HASH_KEY_IS_STRING) {
+
+ char *key;
+ int key_type;
+ PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(array_hash, key, key_type,
+ inner_array)
+ if (key_type != HASH_KEY_IS_STRING || key == NULL) {
return false;
}
- if (Z_TYPE_P(*inner_array) != IS_ARRAY) {
+ if (Z_TYPE_P(inner_array) != IS_ARRAY) {
return false;
}
- inner_array_hash = Z_ARRVAL_P(*inner_array);
+ inner_array_hash = Z_ARRVAL_P(inner_array);
metadata->capacity += zend_hash_num_elements(inner_array_hash);
- }
+ PHP_GRPC_HASH_FOREACH_END()
+
metadata->metadata = gpr_malloc(metadata->capacity * sizeof(grpc_metadata));
- for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer);
- zend_hash_get_current_data_ex(array_hash, (void**)&inner_array,
- &array_pointer) == SUCCESS;
- zend_hash_move_forward_ex(array_hash, &array_pointer)) {
- if (zend_hash_get_current_key_ex(array_hash, &key, &key_len, &index, 0,
- &array_pointer) != HASH_KEY_IS_STRING) {
+
+ char *key1 = NULL;
+ int key_type1;
+ PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(array_hash, key1, key_type1,
+ inner_array)
+ if (key_type1 != HASH_KEY_IS_STRING) {
return false;
}
- inner_array_hash = Z_ARRVAL_P(*inner_array);
- for (zend_hash_internal_pointer_reset_ex(inner_array_hash,
- &inner_array_pointer);
- zend_hash_get_current_data_ex(inner_array_hash, (void**)&value,
- &inner_array_pointer) == SUCCESS;
- zend_hash_move_forward_ex(inner_array_hash, &inner_array_pointer)) {
- if (Z_TYPE_P(*value) != IS_STRING) {
+ inner_array_hash = Z_ARRVAL_P(inner_array);
+ PHP_GRPC_HASH_FOREACH_VAL_START(inner_array_hash, value)
+ if (Z_TYPE_P(value) != IS_STRING) {
return false;
}
- metadata->metadata[metadata->count].key = key;
- metadata->metadata[metadata->count].value = Z_STRVAL_P(*value);
- metadata->metadata[metadata->count].value_length = Z_STRLEN_P(*value);
+ metadata->metadata[metadata->count].key = key1;
+ metadata->metadata[metadata->count].value = Z_STRVAL_P(value);
+ metadata->metadata[metadata->count].value_length = Z_STRLEN_P(value);
metadata->count += 1;
- }
- }
+ PHP_GRPC_HASH_FOREACH_END()
+ PHP_GRPC_HASH_FOREACH_END()
return true;
}
+/* Wraps a grpc_call struct in a PHP object. Owned indicates whether the
+ struct should be destroyed at the end of the object's lifecycle */
+zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC) {
+ zval *call_object;
+ PHP_GRPC_MAKE_STD_ZVAL(call_object);
+ object_init_ex(call_object, grpc_ce_call);
+ wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(call_object);
+ call->wrapped = wrapped;
+ call->owned = owned;
+ return call_object;
+}
+
/**
* Constructs a new instance of the Call class.
* @param Channel $channel The channel to associate the call with. Must not be
@@ -211,30 +198,25 @@ bool create_metadata_array(zval *array, grpc_metadata_array *metadata) {
* @param Timeval $absolute_deadline The deadline for completing the call
*/
PHP_METHOD(Call, __construct) {
- wrapped_grpc_call *call =
- (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC);
zval *channel_obj;
char *method;
- int method_len;
+ php_grpc_int method_len;
zval *deadline_obj;
char *host_override = NULL;
- int host_override_len = 0;
+ php_grpc_int host_override_len = 0;
+ wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis());
+
/* "OsO|s" == 1 Object, 1 string, 1 Object, 1 optional string */
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OsO|s",
- &channel_obj, grpc_ce_channel,
- &method, &method_len,
- &deadline_obj, grpc_ce_timeval,
- &host_override, &host_override_len)
- == FAILURE) {
- zend_throw_exception(
- spl_ce_InvalidArgumentException,
- "Call expects a Channel, a String, a Timeval and an optional String",
- 1 TSRMLS_CC);
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OsO|s", &channel_obj,
+ grpc_ce_channel, &method, &method_len,
+ &deadline_obj, grpc_ce_timeval, &host_override,
+ &host_override_len) == FAILURE) {
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "Call expects a Channel, a String, a Timeval and "
+ "an optional String", 1 TSRMLS_CC);
return;
}
- wrapped_grpc_channel *channel =
- (wrapped_grpc_channel *)zend_object_store_get_object(
- channel_obj TSRMLS_CC);
+ wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(channel_obj);
if (channel->wrapped == NULL) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"Call cannot be constructed from a closed Channel",
@@ -242,12 +224,11 @@ PHP_METHOD(Call, __construct) {
return;
}
add_property_zval(getThis(), "channel", channel_obj);
- wrapped_grpc_timeval *deadline =
- (wrapped_grpc_timeval *)zend_object_store_get_object(
- deadline_obj TSRMLS_CC);
- call->wrapped = grpc_channel_create_call(
- channel->wrapped, NULL, GRPC_PROPAGATE_DEFAULTS, completion_queue, method,
- host_override, deadline->wrapped, NULL);
+ wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj);
+ call->wrapped =
+ grpc_channel_create_call(channel->wrapped, NULL, GRPC_PROPAGATE_DEFAULTS,
+ completion_queue, method, host_override,
+ deadline->wrapped, NULL);
call->owned = true;
}
@@ -257,22 +238,26 @@ PHP_METHOD(Call, __construct) {
* @return object Object with results of all actions
*/
PHP_METHOD(Call, startBatch) {
- wrapped_grpc_call *call =
- (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC);
+ zval *result;
+ PHP_GRPC_MAKE_STD_ZVAL(result);
+ object_init(result);
+ php_grpc_ulong index;
+ zval *recv_status;
+ PHP_GRPC_MAKE_STD_ZVAL(recv_status);
+ object_init(recv_status);
+ zval *value;
+ zval *inner_value;
+ zval *message_value;
+ zval *message_flags;
+ wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis());
+
grpc_op ops[8];
size_t op_num = 0;
zval *array;
- zval **value;
- zval **inner_value;
HashTable *array_hash;
- HashPosition array_pointer;
HashTable *status_hash;
HashTable *message_hash;
- zval **message_value;
- zval **message_flags;
- char *key;
- uint key_len;
- ulong index;
+
grpc_metadata_array metadata;
grpc_metadata_array trailing_metadata;
grpc_metadata_array recv_metadata;
@@ -283,17 +268,15 @@ PHP_METHOD(Call, startBatch) {
grpc_byte_buffer *message;
int cancelled;
grpc_call_error error;
- zval *result;
char *message_str;
size_t message_len;
- zval *recv_status;
+
grpc_metadata_array_init(&metadata);
grpc_metadata_array_init(&trailing_metadata);
grpc_metadata_array_init(&recv_metadata);
grpc_metadata_array_init(&recv_trailing_metadata);
- MAKE_STD_ZVAL(result);
- object_init(result);
memset(ops, 0, sizeof(ops));
+
/* "a" == 1 array */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) ==
FAILURE) {
@@ -301,136 +284,136 @@ PHP_METHOD(Call, startBatch) {
"start_batch expects an array", 1 TSRMLS_CC);
goto cleanup;
}
+
array_hash = Z_ARRVAL_P(array);
- for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer);
- zend_hash_get_current_data_ex(array_hash, (void**)&value,
- &array_pointer) == SUCCESS;
- zend_hash_move_forward_ex(array_hash, &array_pointer)) {
- if (zend_hash_get_current_key_ex(array_hash, &key, &key_len, &index, 0,
- &array_pointer) != HASH_KEY_IS_LONG) {
+
+ char *key = NULL;
+ int key_type;
+ PHP_GRPC_HASH_FOREACH_LONG_KEY_VAL_START(array_hash, key, key_type, index,
+ value)
+ if (key_type != HASH_KEY_IS_LONG || key != NULL) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"batch keys must be integers", 1 TSRMLS_CC);
goto cleanup;
}
switch(index) {
- case GRPC_OP_SEND_INITIAL_METADATA:
- if (!create_metadata_array(*value, &metadata)) {
- zend_throw_exception(spl_ce_InvalidArgumentException,
- "Bad metadata value given", 1 TSRMLS_CC);
- goto cleanup;
- }
- ops[op_num].data.send_initial_metadata.count =
- metadata.count;
- ops[op_num].data.send_initial_metadata.metadata =
- metadata.metadata;
- break;
- case GRPC_OP_SEND_MESSAGE:
- if (Z_TYPE_PP(value) != IS_ARRAY) {
+ case GRPC_OP_SEND_INITIAL_METADATA:
+ if (!create_metadata_array(value, &metadata)) {
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "Bad metadata value given", 1 TSRMLS_CC);
+ goto cleanup;
+ }
+ ops[op_num].data.send_initial_metadata.count = metadata.count;
+ ops[op_num].data.send_initial_metadata.metadata = metadata.metadata;
+ break;
+ case GRPC_OP_SEND_MESSAGE:
+ if (Z_TYPE_P(value) != IS_ARRAY) {
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "Expected an array for send message",
+ 1 TSRMLS_CC);
+ goto cleanup;
+ }
+ message_hash = Z_ARRVAL_P(value);
+ if (php_grpc_zend_hash_find(message_hash, "flags", sizeof("flags"),
+ (void **)&message_flags) == SUCCESS) {
+ if (Z_TYPE_P(message_flags) != IS_LONG) {
zend_throw_exception(spl_ce_InvalidArgumentException,
- "Expected an array for send message",
+ "Expected an int for message flags",
1 TSRMLS_CC);
- goto cleanup;
}
- message_hash = Z_ARRVAL_PP(value);
- if (zend_hash_find(message_hash, "flags", sizeof("flags"),
- (void **)&message_flags) == SUCCESS) {
- if (Z_TYPE_PP(message_flags) != IS_LONG) {
- zend_throw_exception(spl_ce_InvalidArgumentException,
- "Expected an int for message flags",
- 1 TSRMLS_CC);
- }
- ops[op_num].flags = Z_LVAL_PP(message_flags) & GRPC_WRITE_USED_MASK;
- }
- if (zend_hash_find(message_hash, "message", sizeof("message"),
- (void **)&message_value) != SUCCESS ||
- Z_TYPE_PP(message_value) != IS_STRING) {
+ ops[op_num].flags = Z_LVAL_P(message_flags) & GRPC_WRITE_USED_MASK;
+ }
+ if (php_grpc_zend_hash_find(message_hash, "message", sizeof("message"),
+ (void **)&message_value) != SUCCESS ||
+ Z_TYPE_P(message_value) != IS_STRING) {
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "Expected a string for send message",
+ 1 TSRMLS_CC);
+ goto cleanup;
+ }
+ ops[op_num].data.send_message =
+ string_to_byte_buffer(Z_STRVAL_P(message_value),
+ Z_STRLEN_P(message_value));
+ break;
+ case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
+ break;
+ case GRPC_OP_SEND_STATUS_FROM_SERVER:
+ status_hash = Z_ARRVAL_P(value);
+ if (php_grpc_zend_hash_find(status_hash, "metadata", sizeof("metadata"),
+ (void **)&inner_value) == SUCCESS) {
+ if (!create_metadata_array(inner_value, &trailing_metadata)) {
zend_throw_exception(spl_ce_InvalidArgumentException,
- "Expected a string for send message",
+ "Bad trailing metadata value given",
1 TSRMLS_CC);
goto cleanup;
}
- ops[op_num].data.send_message =
- string_to_byte_buffer(Z_STRVAL_PP(message_value),
- Z_STRLEN_PP(message_value));
- break;
- case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
- break;
- case GRPC_OP_SEND_STATUS_FROM_SERVER:
- status_hash = Z_ARRVAL_PP(value);
- if (zend_hash_find(status_hash, "metadata", sizeof("metadata"),
- (void **)&inner_value) == SUCCESS) {
- if (!create_metadata_array(*inner_value, &trailing_metadata)) {
- zend_throw_exception(spl_ce_InvalidArgumentException,
- "Bad trailing metadata value given",
- 1 TSRMLS_CC);
- goto cleanup;
- }
- ops[op_num].data.send_status_from_server.trailing_metadata =
- trailing_metadata.metadata;
- ops[op_num].data.send_status_from_server.trailing_metadata_count =
- trailing_metadata.count;
- }
- if (zend_hash_find(status_hash, "code", sizeof("code"),
- (void**)&inner_value) == SUCCESS) {
- if (Z_TYPE_PP(inner_value) != IS_LONG) {
- zend_throw_exception(spl_ce_InvalidArgumentException,
- "Status code must be an integer",
- 1 TSRMLS_CC);
- goto cleanup;
- }
- ops[op_num].data.send_status_from_server.status =
- Z_LVAL_PP(inner_value);
- } else {
+ ops[op_num].data.send_status_from_server.trailing_metadata =
+ trailing_metadata.metadata;
+ ops[op_num].data.send_status_from_server.trailing_metadata_count =
+ trailing_metadata.count;
+ }
+ if (php_grpc_zend_hash_find(status_hash, "code", sizeof("code"),
+ (void**)&inner_value) == SUCCESS) {
+ if (Z_TYPE_P(inner_value) != IS_LONG) {
zend_throw_exception(spl_ce_InvalidArgumentException,
- "Integer status code is required",
+ "Status code must be an integer",
1 TSRMLS_CC);
goto cleanup;
}
- if (zend_hash_find(status_hash, "details", sizeof("details"),
- (void**)&inner_value) == SUCCESS) {
- if (Z_TYPE_PP(inner_value) != IS_STRING) {
- zend_throw_exception(spl_ce_InvalidArgumentException,
- "Status details must be a string",
- 1 TSRMLS_CC);
- goto cleanup;
- }
- ops[op_num].data.send_status_from_server.status_details =
- Z_STRVAL_PP(inner_value);
- } else {
+ ops[op_num].data.send_status_from_server.status =
+ Z_LVAL_P(inner_value);
+ } else {
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "Integer status code is required",
+ 1 TSRMLS_CC);
+ goto cleanup;
+ }
+ if (php_grpc_zend_hash_find(status_hash, "details", sizeof("details"),
+ (void**)&inner_value) == SUCCESS) {
+ if (Z_TYPE_P(inner_value) != IS_STRING) {
zend_throw_exception(spl_ce_InvalidArgumentException,
- "String status details is required",
+ "Status details must be a string",
1 TSRMLS_CC);
goto cleanup;
}
- break;
- case GRPC_OP_RECV_INITIAL_METADATA:
- ops[op_num].data.recv_initial_metadata = &recv_metadata;
- break;
- case GRPC_OP_RECV_MESSAGE:
- ops[op_num].data.recv_message = &message;
- break;
- case GRPC_OP_RECV_STATUS_ON_CLIENT:
- ops[op_num].data.recv_status_on_client.trailing_metadata =
- &recv_trailing_metadata;
- ops[op_num].data.recv_status_on_client.status = &status;
- ops[op_num].data.recv_status_on_client.status_details =
- &status_details;
- ops[op_num].data.recv_status_on_client.status_details_capacity =
- &status_details_capacity;
- break;
- case GRPC_OP_RECV_CLOSE_ON_SERVER:
- ops[op_num].data.recv_close_on_server.cancelled = &cancelled;
- break;
- default:
+ ops[op_num].data.send_status_from_server.status_details =
+ Z_STRVAL_P(inner_value);
+ } else {
zend_throw_exception(spl_ce_InvalidArgumentException,
- "Unrecognized key in batch", 1 TSRMLS_CC);
+ "String status details is required",
+ 1 TSRMLS_CC);
goto cleanup;
+ }
+ break;
+ case GRPC_OP_RECV_INITIAL_METADATA:
+ ops[op_num].data.recv_initial_metadata = &recv_metadata;
+ break;
+ case GRPC_OP_RECV_MESSAGE:
+ ops[op_num].data.recv_message = &message;
+ break;
+ case GRPC_OP_RECV_STATUS_ON_CLIENT:
+ ops[op_num].data.recv_status_on_client.trailing_metadata =
+ &recv_trailing_metadata;
+ ops[op_num].data.recv_status_on_client.status = &status;
+ ops[op_num].data.recv_status_on_client.status_details =
+ &status_details;
+ ops[op_num].data.recv_status_on_client.status_details_capacity =
+ &status_details_capacity;
+ break;
+ case GRPC_OP_RECV_CLOSE_ON_SERVER:
+ ops[op_num].data.recv_close_on_server.cancelled = &cancelled;
+ break;
+ default:
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "Unrecognized key in batch", 1 TSRMLS_CC);
+ goto cleanup;
}
ops[op_num].op = (grpc_op_type)index;
ops[op_num].flags = 0;
ops[op_num].reserved = NULL;
op_num++;
- }
+ PHP_GRPC_HASH_FOREACH_END()
+
error = grpc_call_start_batch(call->wrapped, ops, op_num, call->wrapped,
NULL);
if (error != GRPC_CALL_OK) {
@@ -441,52 +424,65 @@ PHP_METHOD(Call, startBatch) {
}
grpc_completion_queue_pluck(completion_queue, call->wrapped,
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+#if PHP_MAJOR_VERSION >= 7
+ zval recv_md;
+#endif
for (int i = 0; i < op_num; i++) {
switch(ops[i].op) {
- case GRPC_OP_SEND_INITIAL_METADATA:
- add_property_bool(result, "send_metadata", true);
- break;
- case GRPC_OP_SEND_MESSAGE:
- add_property_bool(result, "send_message", true);
- break;
- case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
- add_property_bool(result, "send_close", true);
- break;
- case GRPC_OP_SEND_STATUS_FROM_SERVER:
- add_property_bool(result, "send_status", true);
- break;
- case GRPC_OP_RECV_INITIAL_METADATA:
- array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC);
- add_property_zval(result, "metadata", array);
- Z_DELREF_P(array);
- break;
- case GRPC_OP_RECV_MESSAGE:
- byte_buffer_to_string(message, &message_str, &message_len);
- if (message_str == NULL) {
- add_property_null(result, "message");
- } else {
- add_property_stringl(result, "message", message_str, message_len,
- false);
- }
- break;
- case GRPC_OP_RECV_STATUS_ON_CLIENT:
- MAKE_STD_ZVAL(recv_status);
- object_init(recv_status);
- array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC);
- add_property_zval(recv_status, "metadata", array);
- Z_DELREF_P(array);
- add_property_long(recv_status, "code", status);
- add_property_string(recv_status, "details", status_details, true);
- add_property_zval(result, "status", recv_status);
- Z_DELREF_P(recv_status);
- break;
- case GRPC_OP_RECV_CLOSE_ON_SERVER:
- add_property_bool(result, "cancelled", cancelled);
- break;
- default:
- break;
+ case GRPC_OP_SEND_INITIAL_METADATA:
+ add_property_bool(result, "send_metadata", true);
+ break;
+ case GRPC_OP_SEND_MESSAGE:
+ add_property_bool(result, "send_message", true);
+ break;
+ case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
+ add_property_bool(result, "send_close", true);
+ break;
+ case GRPC_OP_SEND_STATUS_FROM_SERVER:
+ add_property_bool(result, "send_status", true);
+ break;
+ case GRPC_OP_RECV_INITIAL_METADATA:
+#if PHP_MAJOR_VERSION < 7
+ array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC);
+ add_property_zval(result, "metadata", array);
+#else
+ recv_md = *grpc_parse_metadata_array(&recv_metadata);
+ add_property_zval(result, "metadata", &recv_md);
+#endif
+ PHP_GRPC_DELREF(array);
+ break;
+ case GRPC_OP_RECV_MESSAGE:
+ byte_buffer_to_string(message, &message_str, &message_len);
+ if (message_str == NULL) {
+ add_property_null(result, "message");
+ } else {
+ php_grpc_add_property_stringl(result, "message", message_str,
+ message_len, false);
+ }
+ break;
+ case GRPC_OP_RECV_STATUS_ON_CLIENT:
+#if PHP_MAJOR_VERSION < 7
+ array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC);
+ add_property_zval(recv_status, "metadata", array);
+#else
+ recv_md = *grpc_parse_metadata_array(&recv_trailing_metadata);
+ add_property_zval(recv_status, "metadata", &recv_md);
+#endif
+ PHP_GRPC_DELREF(array);
+ add_property_long(recv_status, "code", status);
+ php_grpc_add_property_string(recv_status, "details", status_details,
+ true);
+ add_property_zval(result, "status", recv_status);
+ PHP_GRPC_DELREF(recv_status);
+ break;
+ case GRPC_OP_RECV_CLOSE_ON_SERVER:
+ add_property_bool(result, "cancelled", cancelled);
+ break;
+ default:
+ break;
}
}
+
cleanup:
grpc_metadata_array_destroy(&metadata);
grpc_metadata_array_destroy(&trailing_metadata);
@@ -511,9 +507,8 @@ cleanup:
* @return string The URI of the endpoint
*/
PHP_METHOD(Call, getPeer) {
- wrapped_grpc_call *call =
- (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC);
- RETURN_STRING(grpc_call_get_peer(call->wrapped), 1);
+ wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis());
+ PHP_GRPC_RETURN_STRING(grpc_call_get_peer(call->wrapped), 1);
}
/**
@@ -521,8 +516,7 @@ PHP_METHOD(Call, getPeer) {
* has not already ended with another status.
*/
PHP_METHOD(Call, cancel) {
- wrapped_grpc_call *call =
- (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC);
+ wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis());
grpc_call_cancel(call->wrapped, NULL);
}
@@ -544,11 +538,8 @@ PHP_METHOD(Call, setCredentials) {
}
wrapped_grpc_call_credentials *creds =
- (wrapped_grpc_call_credentials *)zend_object_store_get_object(
- creds_obj TSRMLS_CC);
-
- wrapped_grpc_call *call =
- (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC);
+ Z_WRAPPED_GRPC_CALL_CREDS_P(creds_obj);
+ wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis());
grpc_call_error error = GRPC_CALL_ERROR;
error = grpc_call_set_credentials(call->wrapped, creds->wrapped);
@@ -556,16 +547,18 @@ PHP_METHOD(Call, setCredentials) {
}
static zend_function_entry call_methods[] = {
- PHP_ME(Call, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
- PHP_ME(Call, startBatch, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Call, getPeer, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Call, cancel, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Call, setCredentials, NULL, ZEND_ACC_PUBLIC)
- PHP_FE_END};
+ PHP_ME(Call, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+ PHP_ME(Call, startBatch, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Call, getPeer, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Call, cancel, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Call, setCredentials, NULL, ZEND_ACC_PUBLIC)
+ PHP_FE_END
+};
void grpc_init_call(TSRMLS_D) {
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "Grpc\\Call", call_methods);
ce.create_object = create_wrapped_grpc_call;
grpc_ce_call = zend_register_internal_class(&ce TSRMLS_CC);
+ PHP_GRPC_INIT_HANDLER(wrapped_grpc_call, call_ce_handlers);
}
diff --git a/src/php/ext/grpc/call.h b/src/php/ext/grpc/call.h
index 36c5f2d272..e49f9b382a 100644
--- a/src/php/ext/grpc/call.h
+++ b/src/php/ext/grpc/call.h
@@ -49,23 +49,38 @@
extern zend_class_entry *grpc_ce_call;
/* Wrapper struct for grpc_call that can be associated with a PHP object */
-typedef struct wrapped_grpc_call {
- zend_object std;
-
+PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_call)
bool owned;
grpc_call *wrapped;
-} wrapped_grpc_call;
+PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_call)
-/* Initializes the Call PHP class */
-void grpc_init_call(TSRMLS_D);
+#if PHP_MAJOR_VERSION < 7
-/* Creates a Call object that wraps the given grpc_call struct */
-zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC);
+#define Z_WRAPPED_GRPC_CALL_P(zv) \
+ (wrapped_grpc_call *)zend_object_store_get_object(zv TSRMLS_CC)
+
+#else
+
+static inline wrapped_grpc_call
+*wrapped_grpc_call_from_obj(zend_object *obj) {
+ return (wrapped_grpc_call*)((char*)(obj) -
+ XtOffsetOf(wrapped_grpc_call, std));
+}
+
+#define Z_WRAPPED_GRPC_CALL_P(zv) wrapped_grpc_call_from_obj(Z_OBJ_P((zv)))
+
+#endif /* PHP_MAJOR_VERSION */
/* Creates and returns a PHP associative array of metadata from a C array of
* call metadata */
zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC);
+/* Creates a Call object that wraps the given grpc_call struct */
+zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC);
+
+/* Initializes the Call PHP class */
+void grpc_init_call(TSRMLS_D);
+
/* Populates a grpc_metadata_array with the data in a PHP array object.
Returns true on success and false on failure */
bool create_metadata_array(zval *array, grpc_metadata_array *metadata);
diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c
index ec0e6b9181..6921a5df17 100644
--- a/src/php/ext/grpc/call_credentials.c
+++ b/src/php/ext/grpc/call_credentials.c
@@ -52,44 +52,35 @@
#include <grpc/grpc_security.h>
zend_class_entry *grpc_ce_call_credentials;
+#if PHP_MAJOR_VERSION >= 7
+static zend_object_handlers call_credentials_ce_handlers;
+#endif
/* Frees and destroys an instance of wrapped_grpc_call_credentials */
-void free_wrapped_grpc_call_credentials(void *object TSRMLS_DC) {
- wrapped_grpc_call_credentials *creds =
- (wrapped_grpc_call_credentials *)object;
- if (creds->wrapped != NULL) {
- grpc_call_credentials_release(creds->wrapped);
+PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_call_credentials)
+ if (p->wrapped != NULL) {
+ grpc_call_credentials_release(p->wrapped);
}
- efree(creds);
-}
+PHP_GRPC_FREE_WRAPPED_FUNC_END()
/* Initializes an instance of wrapped_grpc_call_credentials to be
* associated with an object of a class specified by class_type */
-zend_object_value create_wrapped_grpc_call_credentials(
+php_grpc_zend_object create_wrapped_grpc_call_credentials(
zend_class_entry *class_type TSRMLS_DC) {
- zend_object_value retval;
- wrapped_grpc_call_credentials *intern;
-
- intern = (wrapped_grpc_call_credentials *)emalloc(
- sizeof(wrapped_grpc_call_credentials));
- memset(intern, 0, sizeof(wrapped_grpc_call_credentials));
-
+ PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_call_credentials);
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
object_properties_init(&intern->std, class_type);
- retval.handle = zend_objects_store_put(
- intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
- free_wrapped_grpc_call_credentials, NULL TSRMLS_CC);
- retval.handlers = zend_get_std_object_handlers();
- return retval;
+ PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_call_credentials,
+ call_credentials_ce_handlers);
}
-zval *grpc_php_wrap_call_credentials(grpc_call_credentials *wrapped TSRMLS_DC) {
+zval *grpc_php_wrap_call_credentials(grpc_call_credentials
+ *wrapped TSRMLS_DC) {
zval *credentials_object;
- MAKE_STD_ZVAL(credentials_object);
+ PHP_GRPC_MAKE_STD_ZVAL(credentials_object);
object_init_ex(credentials_object, grpc_ce_call_credentials);
wrapped_grpc_call_credentials *credentials =
- (wrapped_grpc_call_credentials *)zend_object_store_get_object(
- credentials_object TSRMLS_CC);
+ Z_WRAPPED_GRPC_CALL_CREDS_P(credentials_object);
credentials->wrapped = wrapped;
return credentials_object;
}
@@ -114,15 +105,15 @@ PHP_METHOD(CallCredentials, createComposite) {
return;
}
wrapped_grpc_call_credentials *cred1 =
- (wrapped_grpc_call_credentials *)zend_object_store_get_object(
- cred1_obj TSRMLS_CC);
+ Z_WRAPPED_GRPC_CALL_CREDS_P(cred1_obj);
wrapped_grpc_call_credentials *cred2 =
- (wrapped_grpc_call_credentials *)zend_object_store_get_object(
- cred2_obj TSRMLS_CC);
+ Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj);
grpc_call_credentials *creds =
grpc_composite_call_credentials_create(cred1->wrapped, cred2->wrapped,
NULL);
- zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC);
+ zval *creds_object;
+ PHP_GRPC_MAKE_STD_ZVAL(creds_object);
+ creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
@@ -141,13 +132,10 @@ PHP_METHOD(CallCredentials, createFromPlugin) {
memset(fci_cache, 0, sizeof(zend_fcall_info_cache));
/* "f" == 1 function */
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f", fci,
- fci_cache,
- fci->params,
- fci->param_count) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f*", fci, fci_cache,
+ fci->params, fci->param_count) == FAILURE) {
zend_throw_exception(spl_ce_InvalidArgumentException,
- "createFromPlugin expects 1 callback",
- 1 TSRMLS_CC);
+ "createFromPlugin expects 1 callback", 1 TSRMLS_CC);
return;
}
@@ -165,9 +153,11 @@ PHP_METHOD(CallCredentials, createFromPlugin) {
plugin.state = (void *)state;
plugin.type = "";
- grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin(
- plugin, NULL);
- zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC);
+ grpc_call_credentials *creds =
+ grpc_metadata_credentials_create_from_plugin(plugin, NULL);
+ zval *creds_object;
+ PHP_GRPC_MAKE_STD_ZVAL(creds_object);
+ creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
@@ -181,17 +171,23 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
/* prepare to call the user callback function with info from the
* grpc_auth_metadata_context */
- zval **params[1];
zval *arg;
- zval *retval;
- MAKE_STD_ZVAL(arg);
+ PHP_GRPC_MAKE_STD_ZVAL(arg);
object_init(arg);
- add_property_string(arg, "service_url", context.service_url, true);
- add_property_string(arg, "method_name", context.method_name, true);
+ php_grpc_add_property_string(arg, "service_url", context.service_url, true);
+ php_grpc_add_property_string(arg, "method_name", context.method_name, true);
+ zval *retval;
+ PHP_GRPC_MAKE_STD_ZVAL(retval);
+#if PHP_MAJOR_VERSION < 7
+ zval **params[1];
params[0] = &arg;
- state->fci->param_count = 1;
state->fci->params = params;
state->fci->retval_ptr_ptr = &retval;
+#else
+ state->fci->params = arg;
+ state->fci->retval = retval;
+#endif
+ state->fci->param_count = 1;
/* call the user callback function */
zend_call_function(state->fci, state->fci_cache TSRMLS_CC);
@@ -200,6 +196,7 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
zend_throw_exception(spl_ce_InvalidArgumentException,
"plugin callback must return metadata array",
1 TSRMLS_CC);
+ return;
}
grpc_metadata_array metadata;
@@ -207,6 +204,7 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
zend_throw_exception(spl_ce_InvalidArgumentException,
"invalid metadata", 1 TSRMLS_CC);
grpc_metadata_array_destroy(&metadata);
+ return;
}
/* TODO: handle error */
@@ -229,11 +227,14 @@ static zend_function_entry call_credentials_methods[] = {
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(CallCredentials, createFromPlugin, NULL,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_FE_END};
+ PHP_FE_END
+};
void grpc_init_call_credentials(TSRMLS_D) {
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "Grpc\\CallCredentials", call_credentials_methods);
ce.create_object = create_wrapped_grpc_call_credentials;
grpc_ce_call_credentials = zend_register_internal_class(&ce TSRMLS_CC);
+ PHP_GRPC_INIT_HANDLER(wrapped_grpc_call_credentials,
+ call_credentials_ce_handlers);
}
diff --git a/src/php/ext/grpc/call_credentials.h b/src/php/ext/grpc/call_credentials.h
index d2f6a92449..c1d85c0fb2 100755
--- a/src/php/ext/grpc/call_credentials.h
+++ b/src/php/ext/grpc/call_credentials.h
@@ -51,11 +51,27 @@ extern zend_class_entry *grpc_ce_call_credentials;
/* Wrapper struct for grpc_call_credentials that can be associated
* with a PHP object */
-typedef struct wrapped_grpc_call_credentials {
- zend_object std;
-
+PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_call_credentials)
grpc_call_credentials *wrapped;
-} wrapped_grpc_call_credentials;
+PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_call_credentials)
+
+#if PHP_MAJOR_VERSION < 7
+
+#define Z_WRAPPED_GRPC_CALL_CREDS_P(zv) \
+ (wrapped_grpc_call_credentials *)zend_object_store_get_object(zv TSRMLS_CC)
+
+#else
+
+static inline wrapped_grpc_call_credentials
+*wrapped_grpc_call_credentials_from_obj(zend_object *obj) {
+ return (wrapped_grpc_call_credentials*)(
+ (char*)(obj) - XtOffsetOf(wrapped_grpc_call_credentials, std));
+}
+
+#define Z_WRAPPED_GRPC_CALL_CREDS_P(zv) \
+ wrapped_grpc_call_credentials_from_obj(Z_OBJ_P((zv)))
+
+#endif /* PHP_MAJOR_VERSION */
/* Struct to hold callback function for plugin creds API */
typedef struct plugin_state {
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index 8d94c59683..b5a2c9f6ba 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -56,72 +56,68 @@
#include "timeval.h"
zend_class_entry *grpc_ce_channel;
+#if PHP_MAJOR_VERSION >= 7
+static zend_object_handlers channel_ce_handlers;
+#endif
/* Frees and destroys an instance of wrapped_grpc_channel */
-void free_wrapped_grpc_channel(void *object TSRMLS_DC) {
- wrapped_grpc_channel *channel = (wrapped_grpc_channel *)object;
- if (channel->wrapped != NULL) {
- grpc_channel_destroy(channel->wrapped);
+PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel)
+ if (p->wrapped != NULL) {
+ grpc_channel_destroy(p->wrapped);
}
- efree(channel);
-}
+PHP_GRPC_FREE_WRAPPED_FUNC_END()
/* Initializes an instance of wrapped_grpc_channel to be associated with an
* object of a class specified by class_type */
-zend_object_value create_wrapped_grpc_channel(zend_class_entry *class_type
- TSRMLS_DC) {
- zend_object_value retval;
- wrapped_grpc_channel *intern;
- intern = (wrapped_grpc_channel *)emalloc(sizeof(wrapped_grpc_channel));
- memset(intern, 0, sizeof(wrapped_grpc_channel));
+php_grpc_zend_object create_wrapped_grpc_channel(zend_class_entry *class_type
+ TSRMLS_DC) {
+ PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_channel);
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
object_properties_init(&intern->std, class_type);
- retval.handle = zend_objects_store_put(
- intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
- free_wrapped_grpc_channel, NULL TSRMLS_CC);
- retval.handlers = zend_get_std_object_handlers();
- return retval;
+ PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_channel, channel_ce_handlers);
}
-void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_DC) {
+void php_grpc_read_args_array(zval *args_array,
+ grpc_channel_args *args TSRMLS_DC) {
HashTable *array_hash;
- HashPosition array_pointer;
int args_index;
- zval **data;
- char *key;
- uint key_len;
- ulong index;
array_hash = Z_ARRVAL_P(args_array);
+ if (!array_hash) {
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "array_hash is NULL", 1 TSRMLS_CC);
+ return;
+ }
args->num_args = zend_hash_num_elements(array_hash);
args->args = ecalloc(args->num_args, sizeof(grpc_arg));
args_index = 0;
- for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer);
- zend_hash_get_current_data_ex(array_hash, (void **)&data,
- &array_pointer) == SUCCESS;
- zend_hash_move_forward_ex(array_hash, &array_pointer)) {
- if (zend_hash_get_current_key_ex(array_hash, &key, &key_len, &index, 0,
- &array_pointer) != HASH_KEY_IS_STRING) {
+
+ char *key = NULL;
+ zval *data;
+ int key_type;
+
+ PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(array_hash, key, key_type, data)
+ if (key_type != HASH_KEY_IS_STRING) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"args keys must be strings", 1 TSRMLS_CC);
return;
}
args->args[args_index].key = key;
- switch (Z_TYPE_P(*data)) {
- case IS_LONG:
- args->args[args_index].value.integer = (int)Z_LVAL_P(*data);
- args->args[args_index].type = GRPC_ARG_INTEGER;
- break;
- case IS_STRING:
- args->args[args_index].value.string = Z_STRVAL_P(*data);
- args->args[args_index].type = GRPC_ARG_STRING;
- break;
- default:
- zend_throw_exception(spl_ce_InvalidArgumentException,
- "args values must be int or string", 1 TSRMLS_CC);
- return;
+ switch (Z_TYPE_P(data)) {
+ case IS_LONG:
+ args->args[args_index].value.integer = (int)Z_LVAL_P(data);
+ args->args[args_index].type = GRPC_ARG_INTEGER;
+ break;
+ case IS_STRING:
+ args->args[args_index].value.string = Z_STRVAL_P(data);
+ args->args[args_index].type = GRPC_ARG_STRING;
+ break;
+ default:
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "args values must be int or string", 1 TSRMLS_CC);
+ return;
}
args_index++;
- }
+ PHP_GRPC_HASH_FOREACH_END()
}
/**
@@ -132,16 +128,15 @@ void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_D
* @param array $args The arguments to pass to the Channel (optional)
*/
PHP_METHOD(Channel, __construct) {
- wrapped_grpc_channel *channel =
- (wrapped_grpc_channel *)zend_object_store_get_object(
- getThis() TSRMLS_CC);
+ wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
+ zval *creds_obj = NULL;
char *target;
- int target_length;
+ php_grpc_int target_length;
zval *args_array = NULL;
grpc_channel_args args;
HashTable *array_hash;
- zval **creds_obj = NULL;
wrapped_grpc_channel_credentials *creds = NULL;
+
/* "sa" == 1 string, 1 array */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &target,
&target_length, &args_array) == FAILURE) {
@@ -150,21 +145,20 @@ PHP_METHOD(Channel, __construct) {
return;
}
array_hash = Z_ARRVAL_P(args_array);
- if (zend_hash_find(array_hash, "credentials", sizeof("credentials"),
+ if (php_grpc_zend_hash_find(array_hash, "credentials", sizeof("credentials"),
(void **)&creds_obj) == SUCCESS) {
- if (Z_TYPE_P(*creds_obj) == IS_NULL) {
+ if (Z_TYPE_P(creds_obj) == IS_NULL) {
creds = NULL;
- zend_hash_del(array_hash, "credentials", 12);
- } else if (zend_get_class_entry(*creds_obj TSRMLS_CC) !=
- grpc_ce_channel_credentials) {
+ php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials"));
+ } else if (PHP_GRPC_GET_CLASS_ENTRY(creds_obj) !=
+ grpc_ce_channel_credentials) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"credentials must be a ChannelCredentials object",
1 TSRMLS_CC);
return;
} else {
- creds = (wrapped_grpc_channel_credentials *)zend_object_store_get_object(
- *creds_obj TSRMLS_CC);
- zend_hash_del(array_hash, "credentials", 12);
+ creds = Z_WRAPPED_GRPC_CHANNEL_CREDS_P(creds_obj);
+ php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials"));
}
}
php_grpc_read_args_array(args_array, &args TSRMLS_CC);
@@ -182,9 +176,8 @@ PHP_METHOD(Channel, __construct) {
* @return string The URI of the endpoint
*/
PHP_METHOD(Channel, getTarget) {
- wrapped_grpc_channel *channel =
- (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC);
- RETURN_STRING(grpc_channel_get_target(channel->wrapped), 1);
+ wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
+ PHP_GRPC_RETURN_STRING(grpc_channel_get_target(channel->wrapped), 1);
}
/**
@@ -193,12 +186,12 @@ PHP_METHOD(Channel, getTarget) {
* @return long The grpc connectivity state
*/
PHP_METHOD(Channel, getConnectivityState) {
- wrapped_grpc_channel *channel =
- (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC);
- bool try_to_connect;
+ wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
+ bool try_to_connect = false;
+
/* "|b" == 1 optional bool */
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &try_to_connect) ==
- FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &try_to_connect)
+ == FAILURE) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"getConnectivityState expects a bool", 1 TSRMLS_CC);
return;
@@ -215,28 +208,26 @@ PHP_METHOD(Channel, getConnectivityState) {
* before deadline
*/
PHP_METHOD(Channel, watchConnectivityState) {
- wrapped_grpc_channel *channel =
- (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC);
- long last_state;
+ wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
+ php_grpc_long last_state;
zval *deadline_obj;
+
/* "lO" == 1 long 1 object */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lO",
&last_state, &deadline_obj, grpc_ce_timeval) == FAILURE) {
zend_throw_exception(spl_ce_InvalidArgumentException,
- "watchConnectivityState expects 1 long 1 timeval",
- 1 TSRMLS_CC);
+ "watchConnectivityState expects 1 long 1 timeval", 1 TSRMLS_CC);
return;
}
- wrapped_grpc_timeval *deadline =
- (wrapped_grpc_timeval *)zend_object_store_get_object(
- deadline_obj TSRMLS_CC);
- grpc_channel_watch_connectivity_state(
- channel->wrapped, (grpc_connectivity_state)last_state,
- deadline->wrapped, completion_queue, NULL);
- grpc_event event = grpc_completion_queue_pluck(
- completion_queue, NULL,
- gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+ wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj);
+ grpc_channel_watch_connectivity_state(channel->wrapped,
+ (grpc_connectivity_state)last_state,
+ deadline->wrapped, completion_queue,
+ NULL);
+ grpc_event event =
+ grpc_completion_queue_pluck(completion_queue, NULL,
+ gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
RETURN_BOOL(event.success);
}
@@ -244,8 +235,7 @@ PHP_METHOD(Channel, watchConnectivityState) {
* Close the channel
*/
PHP_METHOD(Channel, close) {
- wrapped_grpc_channel *channel =
- (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC);
+ wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
if (channel->wrapped != NULL) {
grpc_channel_destroy(channel->wrapped);
channel->wrapped = NULL;
@@ -253,16 +243,18 @@ PHP_METHOD(Channel, close) {
}
static zend_function_entry channel_methods[] = {
- PHP_ME(Channel, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
- PHP_ME(Channel, getTarget, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Channel, getConnectivityState, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Channel, watchConnectivityState, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC)
- PHP_FE_END};
+ PHP_ME(Channel, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+ PHP_ME(Channel, getTarget, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Channel, getConnectivityState, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Channel, watchConnectivityState, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC)
+ PHP_FE_END
+};
void grpc_init_channel(TSRMLS_D) {
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "Grpc\\Channel", channel_methods);
ce.create_object = create_wrapped_grpc_channel;
grpc_ce_channel = zend_register_internal_class(&ce TSRMLS_CC);
+ PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel, channel_ce_handlers);
}
diff --git a/src/php/ext/grpc/channel.h b/src/php/ext/grpc/channel.h
index cc5823ee7f..0b815657d3 100755
--- a/src/php/ext/grpc/channel.h
+++ b/src/php/ext/grpc/channel.h
@@ -49,16 +49,33 @@
extern zend_class_entry *grpc_ce_channel;
/* Wrapper struct for grpc_channel that can be associated with a PHP object */
-typedef struct wrapped_grpc_channel {
- zend_object std;
-
+PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_channel)
grpc_channel *wrapped;
-} wrapped_grpc_channel;
+PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_channel)
+
+#if PHP_MAJOR_VERSION < 7
+
+#define Z_WRAPPED_GRPC_CHANNEL_P(zv) \
+ (wrapped_grpc_channel *)zend_object_store_get_object(zv TSRMLS_CC)
+
+#else
+
+static inline wrapped_grpc_channel
+*wrapped_grpc_channel_from_obj(zend_object *obj) {
+ return (wrapped_grpc_channel*)((char*)(obj) -
+ XtOffsetOf(wrapped_grpc_channel, std));
+}
+
+#define Z_WRAPPED_GRPC_CHANNEL_P(zv) \
+ wrapped_grpc_channel_from_obj(Z_OBJ_P((zv)))
+
+#endif /* PHP_MAJOR_VERSION */
/* Initializes the Channel class */
void grpc_init_channel(TSRMLS_D);
/* Iterates through a PHP array and populates args with the contents */
-void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_DC);
+void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args
+ TSRMLS_DC);
#endif /* NET_GRPC_PHP_GRPC_CHANNEL_H_ */
diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c
index b76fb105f3..0b356aa25f 100644
--- a/src/php/ext/grpc/channel_credentials.c
+++ b/src/php/ext/grpc/channel_credentials.c
@@ -52,7 +52,9 @@
#include <grpc/grpc_security.h>
zend_class_entry *grpc_ce_channel_credentials;
-
+#if PHP_MAJOR_VERSION >= 7
+static zend_object_handlers channel_credentials_ce_handlers;
+#endif
static char *default_pem_root_certs = NULL;
static grpc_ssl_roots_override_result get_ssl_roots_override(
@@ -65,42 +67,30 @@ static grpc_ssl_roots_override_result get_ssl_roots_override(
}
/* Frees and destroys an instance of wrapped_grpc_channel_credentials */
-void free_wrapped_grpc_channel_credentials(void *object TSRMLS_DC) {
- wrapped_grpc_channel_credentials *creds =
- (wrapped_grpc_channel_credentials *)object;
- if (creds->wrapped != NULL) {
- grpc_channel_credentials_release(creds->wrapped);
+PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel_credentials)
+ if (p->wrapped != NULL) {
+ grpc_channel_credentials_release(p->wrapped);
}
- efree(creds);
-}
+PHP_GRPC_FREE_WRAPPED_FUNC_END()
/* Initializes an instance of wrapped_grpc_channel_credentials to be
* associated with an object of a class specified by class_type */
-zend_object_value create_wrapped_grpc_channel_credentials(
+php_grpc_zend_object create_wrapped_grpc_channel_credentials(
zend_class_entry *class_type TSRMLS_DC) {
- zend_object_value retval;
- wrapped_grpc_channel_credentials *intern;
-
- intern = (wrapped_grpc_channel_credentials *)emalloc(
- sizeof(wrapped_grpc_channel_credentials));
- memset(intern, 0, sizeof(wrapped_grpc_channel_credentials));
-
+ PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_channel_credentials);
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
object_properties_init(&intern->std, class_type);
- retval.handle = zend_objects_store_put(
- intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
- free_wrapped_grpc_channel_credentials, NULL TSRMLS_CC);
- retval.handlers = zend_get_std_object_handlers();
- return retval;
+ PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_channel_credentials,
+ channel_credentials_ce_handlers);
}
-zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped TSRMLS_DC) {
+zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials
+ *wrapped TSRMLS_DC) {
zval *credentials_object;
- MAKE_STD_ZVAL(credentials_object);
+ PHP_GRPC_MAKE_STD_ZVAL(credentials_object);
object_init_ex(credentials_object, grpc_ce_channel_credentials);
wrapped_grpc_channel_credentials *credentials =
- (wrapped_grpc_channel_credentials *)zend_object_store_get_object(
- credentials_object TSRMLS_CC);
+ Z_WRAPPED_GRPC_CHANNEL_CREDS_P(credentials_object);
credentials->wrapped = wrapped;
return credentials_object;
}
@@ -112,7 +102,9 @@ zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped TSRMLS
*/
PHP_METHOD(ChannelCredentials, setDefaultRootsPem) {
char *pem_roots;
- int pem_roots_length;
+ php_grpc_int pem_roots_length;
+
+ /* "s" == 1 string */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &pem_roots,
&pem_roots_length) == FAILURE) {
zend_throw_exception(spl_ce_InvalidArgumentException,
@@ -129,7 +121,9 @@ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) {
*/
PHP_METHOD(ChannelCredentials, createDefault) {
grpc_channel_credentials *creds = grpc_google_default_credentials_create();
- zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
+ zval *creds_object;
+ PHP_GRPC_MAKE_STD_ZVAL(creds_object);
+ creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
@@ -146,11 +140,13 @@ PHP_METHOD(ChannelCredentials, createSsl) {
char *pem_root_certs = NULL;
grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
- int root_certs_length = 0, private_key_length = 0, cert_chain_length = 0;
+ php_grpc_int root_certs_length = 0;
+ php_grpc_int private_key_length = 0;
+ php_grpc_int cert_chain_length = 0;
pem_key_cert_pair.private_key = pem_key_cert_pair.cert_chain = NULL;
- /* "|s!s!s! == 3 optional nullable strings */
+ /* "|s!s!s!" == 3 optional nullable strings */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!s!",
&pem_root_certs, &root_certs_length,
&pem_key_cert_pair.private_key,
@@ -164,7 +160,9 @@ PHP_METHOD(ChannelCredentials, createSsl) {
grpc_channel_credentials *creds = grpc_ssl_credentials_create(
pem_root_certs,
pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL);
- zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
+ zval *creds_object;
+ PHP_GRPC_MAKE_STD_ZVAL(creds_object);
+ creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
@@ -178,7 +176,7 @@ PHP_METHOD(ChannelCredentials, createComposite) {
zval *cred1_obj;
zval *cred2_obj;
- /* "OO" == 3 Objects */
+ /* "OO" == 2 Objects */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &cred1_obj,
grpc_ce_channel_credentials, &cred2_obj,
grpc_ce_call_credentials) == FAILURE) {
@@ -187,15 +185,15 @@ PHP_METHOD(ChannelCredentials, createComposite) {
return;
}
wrapped_grpc_channel_credentials *cred1 =
- (wrapped_grpc_channel_credentials *)zend_object_store_get_object(
- cred1_obj TSRMLS_CC);
+ Z_WRAPPED_GRPC_CHANNEL_CREDS_P(cred1_obj);
wrapped_grpc_call_credentials *cred2 =
- (wrapped_grpc_call_credentials *)zend_object_store_get_object(
- cred2_obj TSRMLS_CC);
+ Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj);
grpc_channel_credentials *creds =
grpc_composite_channel_credentials_create(cred1->wrapped, cred2->wrapped,
NULL);
- zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
+ zval *creds_object;
+ PHP_GRPC_MAKE_STD_ZVAL(creds_object);
+ creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
@@ -218,7 +216,8 @@ static zend_function_entry channel_credentials_methods[] = {
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(ChannelCredentials, createInsecure, NULL,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_FE_END};
+ PHP_FE_END
+};
void grpc_init_channel_credentials(TSRMLS_D) {
zend_class_entry ce;
@@ -227,4 +226,6 @@ void grpc_init_channel_credentials(TSRMLS_D) {
grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
ce.create_object = create_wrapped_grpc_channel_credentials;
grpc_ce_channel_credentials = zend_register_internal_class(&ce TSRMLS_CC);
+ PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel_credentials,
+ channel_credentials_ce_handlers);
}
diff --git a/src/php/ext/grpc/channel_credentials.h b/src/php/ext/grpc/channel_credentials.h
index d89984ce60..b043d91fa6 100755
--- a/src/php/ext/grpc/channel_credentials.h
+++ b/src/php/ext/grpc/channel_credentials.h
@@ -51,11 +51,27 @@ extern zend_class_entry *grpc_ce_channel_credentials;
/* Wrapper struct for grpc_channel_credentials that can be associated
* with a PHP object */
-typedef struct wrapped_grpc_channel_credentials {
- zend_object std;
-
+PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_channel_credentials)
grpc_channel_credentials *wrapped;
-} wrapped_grpc_channel_credentials;
+PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_channel_credentials)
+
+#if PHP_MAJOR_VERSION < 7
+
+#define Z_WRAPPED_GRPC_CHANNEL_CREDS_P(zv) \
+ (wrapped_grpc_channel_credentials *)zend_object_store_get_object(zv TSRMLS_CC)
+
+#else
+
+static inline wrapped_grpc_channel_credentials
+*wrapped_grpc_channel_credentials_from_obj(zend_object *obj) {
+ return (wrapped_grpc_channel_credentials *)(
+ (char*)(obj) - XtOffsetOf(wrapped_grpc_channel_credentials, std));
+}
+
+#define Z_WRAPPED_GRPC_CHANNEL_CREDS_P(zv) \
+ wrapped_grpc_channel_credentials_from_obj(Z_OBJ_P((zv)))
+
+#endif /* PHP_MAJOR_VERSION */
/* Initializes the ChannelCredentials PHP class */
void grpc_init_channel_credentials(TSRMLS_D);
diff --git a/src/php/ext/grpc/package.xml b/src/php/ext/grpc/package.xml
deleted file mode 100644
index daf2ee5a53..0000000000
--- a/src/php/ext/grpc/package.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<package packagerversion="1.9.5" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
- <name>grpc</name>
- <channel>pecl.php.net</channel>
- <summary>A high performance, open source, general RPC framework that puts mobile and HTTP/2 first.</summary>
- <description>Remote Procedure Calls (RPCs) provide a useful abstraction for building distributed applications and services. The libraries in this repository provide a concrete implementation of the gRPC protocol, layered over HTTP/2. These libraries enable communication between clients and servers using any combination of the supported languages.</description>
- <lead>
- <name>Stanley Cheung</name>
- <user>stanleycheung</user>
- <email>grpc-packages@google.com</email>
- <active>yes</active>
- </lead>
- <date>2016-01-13</date>
- <time>16:06:07</time>
- <version>
- <release>0.7.0</release>
- <api>0.7.0</api>
- </version>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <license>BSD</license>
- <notes>
-- Breaking change to Credentials class (removed) #3765
-- Replaced by ChannelCredentials and CallCredentials class #3765
-- New plugin based metadata auth API #4394
-- Explicit ChannelCredentials::createInsecure() call
- </notes>
- <contents>
- <dir baseinstalldir="/" name="/">
- <file baseinstalldir="/" md5sum="f201d644fdbd8228ffd1d4a69cc44f1f" name="tests/grpc-basic.phpt" role="test" />
- <file baseinstalldir="/" md5sum="6f19828fb869b7b8a590cbb76b4f996d" name="byte_buffer.c" role="src" />
- <file baseinstalldir="/" md5sum="c8de0f819499c48adfc8d7f472c0196b" name="byte_buffer.h" role="src" />
- <file baseinstalldir="/" md5sum="ee7eb7757f9e6f0e36f8f616b6bd0af5" name="call.c" role="src" />
- <file baseinstalldir="/" md5sum="44c56bd9912d2538cbd6059e3e0452b6" name="call.h" role="src" />
- <file baseinstalldir="/" md5sum="ff90f6c03ed44b5f4170bf3259a6704e" name="call_credentials.c" role="src" />
- <file baseinstalldir="/" md5sum="3c3860e1d84f43cb6b2fbaa8d2ae1ab7" name="call_credentials.h" role="src" />
- <file baseinstalldir="/" md5sum="aee9b63f790522aec2c682055240cc61" name="channel.c" role="src" />
- <file baseinstalldir="/" md5sum="ed4b00c0cf3702b115d0cfa87450dc09" name="channel.h" role="src" />
- <file baseinstalldir="/" md5sum="1a51c76d0b7b7d3ab570ed7d60c2ea46" name="channel_credentials.c" role="src" />
- <file baseinstalldir="/" md5sum="a86250e03f610ce6c2c7595a84e08821" name="channel_credentials.h" role="src" />
- <file baseinstalldir="/" md5sum="55ab7a42f9dd9bfc7e28a61cfc5fca63" name="completion_queue.c" role="src" />
- <file baseinstalldir="/" md5sum="f10b5bb232d74a6878e829e2e76cdaa2" name="completion_queue.h" role="src" />
- <file baseinstalldir="/" md5sum="cafed254127007ff2271dad7d56a06c8" name="config.m4" role="src" />
- <file baseinstalldir="/" md5sum="38a1bc979d810c36ebc2a52d4b7b5319" name="CREDITS" role="doc" />
- <file baseinstalldir="/" md5sum="8847cf67b1b54c981d47ecbb0d139a0c" name="LICENSE" role="doc" />
- <file baseinstalldir="/" md5sum="3131a8af38fe5918e5409016b89d6cdb" name="php_grpc.c" role="src" />
- <file baseinstalldir="/" md5sum="673b07859d9f69232f8a754c56780686" name="php_grpc.h" role="src" />
- <file baseinstalldir="/" md5sum="7533a6d3ea02c78cad23a9651de0825d" name="README.md" role="doc" />
- <file baseinstalldir="/" md5sum="3e4e960454ebb2fc7b78a840493f5315" name="server.c" role="src" />
- <file baseinstalldir="/" md5sum="4b730f06d14cbbb0642bdbd194749595" name="server.h" role="src" />
- <file baseinstalldir="/" md5sum="34ea881f1fe960d190d0713422cf8916" name="server_credentials.c" role="src" />
- <file baseinstalldir="/" md5sum="9c4b4cc06356a8a39a16a085a9b85996" name="server_credentials.h" role="src" />
- <file baseinstalldir="/" md5sum="7646ec78cb133f66ba59e03c6f451e39" name="timeval.c" role="src" />
- <file baseinstalldir="/" md5sum="496e27a100b4d93ca3fb35c924c5e163" name="timeval.h" role="src" />
- </dir>
- </contents>
- <dependencies>
- <required>
- <php>
- <min>5.5.0</min>
- </php>
- <pearinstaller>
- <min>1.4.0</min>
- </pearinstaller>
- </required>
- </dependencies>
- <providesextension>grpc</providesextension>
- <extsrcrelease />
- <changelog>
- <release>
- <version>
- <release>0.5.0</release>
- <api>0.5.0</api>
- </version>
- <stability>
- <release>alpha</release>
- <api>alpha</api>
- </stability>
- <date>2015-06-16</date>
- <license>BSD</license>
- <notes>
-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>
- <release>
- <version>
- <release>0.6.0</release>
- <api>0.6.0</api>
- </version>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <date>2015-09-24</date>
- <license>BSD</license>
- <notes>
-- support per message compression disable
-- expose per-call host override option
-- expose connectivity API
-- expose channel target and call peer
-- add user-agent
-- update to wrap gRPC C core library beta version 0.11.0
- </notes>
- </release>
- <release>
- <version>
- <release>0.6.1</release>
- <api>0.6.0</api>
- </version>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <date>2015-10-21</date>
- <license>BSD</license>
- <notes>
-- fixed undefined constant fatal error when run with apache/nginx #2275
- </notes>
- </release>
- <release>
- <version>
- <release>0.7.0</release>
- <api>0.7.0</api>
- </version>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <date>2016-01-13</date>
- <license>BSD</license>
- <notes>
-- Breaking change to Credentials class (removed) #3765
-- Replaced by ChannelCredentials and CallCredentials class #3765
-- New plugin based metadata auth API #4394
-- Explicit ChannelCredentials::createInsecure() call
- </notes>
- </release>
- </changelog>
-</package>
diff --git a/src/php/ext/grpc/php7_wrapper.h b/src/php/ext/grpc/php7_wrapper.h
new file mode 100644
index 0000000000..1d7824113f
--- /dev/null
+++ b/src/php/ext/grpc/php7_wrapper.h
@@ -0,0 +1,217 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#ifndef PHP7_WRAPPER_GRPC_H
+#define PHP7_WRAPPER_GRPC_H
+
+#if PHP_MAJOR_VERSION < 7
+
+#define php_grpc_int int
+#define php_grpc_long long
+#define php_grpc_ulong ulong
+#define php_grpc_zend_object zend_object_value
+#define php_grpc_add_property_string(arg, name, context, b) \
+ add_property_string(arg, name, context, b)
+#define php_grpc_add_property_stringl(res, name, str, len, b) \
+ add_property_stringl(res, name, str, len, b)
+#define php_grpc_add_next_index_stringl(data, str, len, b) \
+ add_next_index_stringl(data, str, len, b)
+
+#define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val, dup)
+#define PHP_GRPC_MAKE_STD_ZVAL(pzv) MAKE_STD_ZVAL(pzv)
+#define PHP_GRPC_DELREF(zv) Z_DELREF_P(zv)
+
+#define PHP_GRPC_WRAP_OBJECT_START(name) \
+ typedef struct name { \
+ zend_object std;
+#define PHP_GRPC_WRAP_OBJECT_END(name) \
+ } name;
+
+#define PHP_GRPC_FREE_WRAPPED_FUNC_START(class_object) \
+ void free_##class_object(void *object TSRMLS_DC) { \
+ class_object *p = (class_object *)object;
+#define PHP_GRPC_FREE_WRAPPED_FUNC_END() \
+ zend_object_std_dtor(&p->std TSRMLS_CC); \
+ efree(p); \
+ }
+
+#define PHP_GRPC_ALLOC_CLASS_OBJECT(class_object) \
+ class_object *intern; \
+ zend_object_value retval; \
+ intern = (class_object *)emalloc(sizeof(class_object)); \
+ memset(intern, 0, sizeof(class_object));
+
+#define PHP_GRPC_FREE_CLASS_OBJECT(class_object, handler) \
+ retval.handle = zend_objects_store_put( \
+ intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \
+ free_##class_object, NULL TSRMLS_CC); \
+ retval.handlers = zend_get_std_object_handlers(); \
+ return retval;
+
+#define PHP_GRPC_HASH_FOREACH_VAL_START(ht, data) \
+ zval **tmp_data = NULL; \
+ for (zend_hash_internal_pointer_reset(ht); \
+ zend_hash_get_current_data(ht, (void**)&tmp_data) == SUCCESS; \
+ zend_hash_move_forward(ht)) { \
+ data = *tmp_data;
+
+#define PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(ht, key, key_type, data) \
+ zval **tmp##key = NULL; \
+ ulong index##key; \
+ uint len##key; \
+ for (zend_hash_internal_pointer_reset(ht); \
+ zend_hash_get_current_data(ht, (void**)&tmp##key) == SUCCESS; \
+ zend_hash_move_forward(ht)) { \
+ key_type = zend_hash_get_current_key_ex(ht, &key, &len##key, &index##key,\
+ 0, NULL); \
+ data = *tmp##key;
+
+#define PHP_GRPC_HASH_FOREACH_LONG_KEY_VAL_START(ht, key, key_type, index,\
+ data) \
+ zval **tmp##key = NULL; \
+ uint len##key; \
+ for (zend_hash_internal_pointer_reset(ht); \
+ zend_hash_get_current_data(ht, (void**)&tmp##key) == SUCCESS; \
+ zend_hash_move_forward(ht)) { \
+ key_type = zend_hash_get_current_key_ex(ht, &key, &len##key, &index,\
+ 0, NULL); \
+ data = *tmp##key;
+
+#define PHP_GRPC_HASH_FOREACH_END() }
+
+static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len,
+ void **value) {
+ zval **data = NULL;
+ if (zend_hash_find(ht, key, len, (void **)&data) == SUCCESS) {
+ *value = *data;
+ return SUCCESS;
+ } else {
+ *value = NULL;
+ return FAILURE;
+ }
+}
+
+#define php_grpc_zend_hash_del zend_hash_del
+
+#define PHP_GRPC_GET_CLASS_ENTRY(object) zend_get_class_entry(object TSRMLS_CC)
+
+#define PHP_GRPC_INIT_HANDLER(class_object, handler_name)
+
+#else
+
+#define php_grpc_int size_t
+#define php_grpc_long zend_long
+#define php_grpc_ulong zend_ulong
+#define php_grpc_zend_object zend_object*
+#define php_grpc_add_property_string(arg, name, context, b) \
+ add_property_string(arg, name, context)
+#define php_grpc_add_property_stringl(res, name, str, len, b) \
+ add_property_stringl(res, name, str, len)
+#define php_grpc_add_next_index_stringl(data, str, len, b) \
+ add_next_index_stringl(data, str, len)
+
+#define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val)
+#define PHP_GRPC_MAKE_STD_ZVAL(pzv) \
+ pzv = (zval *)emalloc(sizeof(zval));
+#define PHP_GRPC_DELREF(zv)
+
+#define PHP_GRPC_WRAP_OBJECT_START(name) \
+ typedef struct name {
+#define PHP_GRPC_WRAP_OBJECT_END(name) \
+ zend_object std; \
+ } name;
+
+#define WRAPPED_OBJECT_FROM_OBJ(class_object, obj) \
+ class_object##_from_obj(obj);
+
+#define PHP_GRPC_FREE_WRAPPED_FUNC_START(class_object) \
+ static void free_##class_object(zend_object *object) { \
+ class_object *p = WRAPPED_OBJECT_FROM_OBJ(class_object, object)
+#define PHP_GRPC_FREE_WRAPPED_FUNC_END() \
+ zend_object_std_dtor(&p->std); \
+ }
+
+#define PHP_GRPC_ALLOC_CLASS_OBJECT(class_object) \
+ class_object *intern; \
+ intern = ecalloc(1, sizeof(class_object) + \
+ zend_object_properties_size(class_type));
+
+#define PHP_GRPC_FREE_CLASS_OBJECT(class_object, handler) \
+ intern->std.handlers = &handler; \
+ return &intern->std;
+
+#define PHP_GRPC_HASH_FOREACH_VAL_START(ht, data) \
+ ZEND_HASH_FOREACH_VAL(ht, data) {
+
+#define PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(ht, key, key_type, data) \
+ zend_string *(zs_##key); \
+ ZEND_HASH_FOREACH_STR_KEY_VAL(ht, (zs_##key), data) { \
+ if ((zs_##key) == NULL) {key = NULL; key_type = HASH_KEY_IS_LONG;} \
+ else {key = (zs_##key)->val; key_type = HASH_KEY_IS_STRING;}
+
+#define PHP_GRPC_HASH_FOREACH_LONG_KEY_VAL_START(ht, key, key_type, index, \
+ data) \
+ zend_string *(zs_##key); \
+ ZEND_HASH_FOREACH_KEY_VAL(ht, index, zs_##key, data) { \
+ if ((zs_##key) == NULL) {key = NULL; key_type = HASH_KEY_IS_LONG;} \
+ else {key = (zs_##key)->val; key_type = HASH_KEY_IS_STRING;}
+
+#define PHP_GRPC_HASH_FOREACH_END() } ZEND_HASH_FOREACH_END();
+
+static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len,
+ void **value) {
+ zval *value_tmp = zend_hash_str_find(ht, key, len -1);
+ if (value_tmp == NULL) {
+ return FAILURE;
+ } else {
+ *value = (void *)value_tmp;
+ return SUCCESS;
+ }
+}
+
+static inline int php_grpc_zend_hash_del(HashTable *ht, char *key, int len) {
+ return zend_hash_str_del(ht, key, len - 1);
+}
+
+#define PHP_GRPC_GET_CLASS_ENTRY(object) Z_OBJ_P(object)->ce
+
+#define PHP_GRPC_INIT_HANDLER(class_object, handler_name) \
+ memcpy(&handler_name, zend_get_std_object_handlers(), \
+ sizeof(zend_object_handlers)); \
+ handler_name.offset = XtOffsetOf(class_object, std); \
+ handler_name.free_obj = free_##class_object
+
+#endif /* PHP_MAJOR_VERSION */
+
+#endif /* PHP7_WRAPPER_GRPC_H */
diff --git a/src/php/ext/grpc/php_grpc.c b/src/php/ext/grpc/php_grpc.c
index 449ba3cd47..5edfa2da7d 100644
--- a/src/php/ext/grpc/php_grpc.c
+++ b/src/php/ext/grpc/php_grpc.c
@@ -64,15 +64,19 @@ const zend_function_entry grpc_functions[] = {
*/
zend_module_entry grpc_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
- STANDARD_MODULE_HEADER,
+ STANDARD_MODULE_HEADER,
#endif
- "grpc", grpc_functions, PHP_MINIT(grpc),
- PHP_MSHUTDOWN(grpc), NULL, NULL,
- PHP_MINFO(grpc),
+ "grpc",
+ grpc_functions,
+ PHP_MINIT(grpc),
+ PHP_MSHUTDOWN(grpc),
+ NULL,
+ NULL,
+ PHP_MINFO(grpc),
#if ZEND_MODULE_API_NO >= 20010901
- PHP_GRPC_VERSION,
+ PHP_GRPC_VERSION,
#endif
- STANDARD_MODULE_PROPERTIES};
+ STANDARD_MODULE_PROPERTIES};
/* }}} */
#ifdef COMPILE_DL_GRPC
@@ -82,23 +86,24 @@ ZEND_GET_MODULE(grpc)
/* {{{ PHP_INI
*/
/* Remove comments and fill if you need to have entries in php.ini
-PHP_INI_BEGIN()
- STD_PHP_INI_ENTRY("grpc.global_value", "42", PHP_INI_ALL, OnUpdateLong,
-global_value, zend_grpc_globals, grpc_globals)
- STD_PHP_INI_ENTRY("grpc.global_string", "foobar", PHP_INI_ALL,
-OnUpdateString, global_string, zend_grpc_globals, grpc_globals)
-PHP_INI_END()
+ PHP_INI_BEGIN()
+ STD_PHP_INI_ENTRY("grpc.global_value", "42", PHP_INI_ALL, OnUpdateLong,
+ global_value, zend_grpc_globals, grpc_globals)
+ STD_PHP_INI_ENTRY("grpc.global_string", "foobar", PHP_INI_ALL,
+ OnUpdateString, global_string, zend_grpc_globals,
+ grpc_globals)
+ PHP_INI_END()
*/
/* }}} */
/* {{{ php_grpc_init_globals
*/
/* Uncomment this function if you have INI entries
-static void php_grpc_init_globals(zend_grpc_globals *grpc_globals)
-{
- grpc_globals->global_value = 0;
- grpc_globals->global_string = NULL;
-}
+ static void php_grpc_init_globals(zend_grpc_globals *grpc_globals)
+ {
+ grpc_globals->global_value = 0;
+ grpc_globals->global_string = NULL;
+ }
*/
/* }}} */
@@ -106,7 +111,7 @@ static void php_grpc_init_globals(zend_grpc_globals *grpc_globals)
*/
PHP_MINIT_FUNCTION(grpc) {
/* If you have INI entries, uncomment these lines
- REGISTER_INI_ENTRIES();
+ REGISTER_INI_ENTRIES();
*/
/* Register call error constants */
grpc_init();
@@ -246,7 +251,7 @@ PHP_MINIT_FUNCTION(grpc) {
*/
PHP_MSHUTDOWN_FUNCTION(grpc) {
/* uncomment this line if you have INI entries
- UNREGISTER_INI_ENTRIES();
+ UNREGISTER_INI_ENTRIES();
*/
// WARNING: This function IS being called by PHP when the extension
// is unloaded but the logs were somehow suppressed.
@@ -265,7 +270,7 @@ PHP_MINFO_FUNCTION(grpc) {
php_info_print_table_end();
/* Remove comments if you have entries in php.ini
- DISPLAY_INI_ENTRIES();
+ DISPLAY_INI_ENTRIES();
*/
}
/* }}} */
@@ -274,12 +279,3 @@ PHP_MINFO_FUNCTION(grpc) {
function definition, where the functions purpose is also documented. Please
follow this convention for the convenience of others editing your code.
*/
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/src/php/ext/grpc/php_grpc.h b/src/php/ext/grpc/php_grpc.h
index 1d4834c50f..e57a06545e 100644
--- a/src/php/ext/grpc/php_grpc.h
+++ b/src/php/ext/grpc/php_grpc.h
@@ -57,6 +57,8 @@ extern zend_module_entry grpc_module_entry;
#include "php.h"
+#include "php7_wrapper.h"
+
#include "grpc/grpc.h"
#define RETURN_DESTROY_ZVAL(val) \
@@ -72,8 +74,8 @@ PHP_MSHUTDOWN_FUNCTION(grpc);
PHP_MINFO_FUNCTION(grpc);
/*
- Declare any global variables you may need between the BEGIN
- and END macros here:
+ Declare any global variables you may need between the BEGIN
+ and END macros here:
ZEND_BEGIN_MODULE_GLOBALS(grpc)
ZEND_END_MODULE_GLOBALS(grpc)
diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c
index c13e7cd1f9..fc20c42b16 100644
--- a/src/php/ext/grpc/server.c
+++ b/src/php/ext/grpc/server.c
@@ -57,37 +57,29 @@
#include "timeval.h"
zend_class_entry *grpc_ce_server;
+#if PHP_MAJOR_VERSION >= 7
+static zend_object_handlers server_ce_handlers;
+#endif
/* Frees and destroys an instance of wrapped_grpc_server */
-void free_wrapped_grpc_server(void *object TSRMLS_DC) {
- wrapped_grpc_server *server = (wrapped_grpc_server *)object;
- if (server->wrapped != NULL) {
- grpc_server_shutdown_and_notify(server->wrapped, completion_queue, NULL);
- grpc_server_cancel_all_calls(server->wrapped);
+PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_server)
+ if (p->wrapped != NULL) {
+ grpc_server_shutdown_and_notify(p->wrapped, completion_queue, NULL);
+ grpc_server_cancel_all_calls(p->wrapped);
grpc_completion_queue_pluck(completion_queue, NULL,
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
- grpc_server_destroy(server->wrapped);
+ grpc_server_destroy(p->wrapped);
}
- efree(server);
-}
+PHP_GRPC_FREE_WRAPPED_FUNC_END()
/* Initializes an instance of wrapped_grpc_call to be associated with an object
* of a class specified by class_type */
-zend_object_value create_wrapped_grpc_server(zend_class_entry *class_type
- TSRMLS_DC) {
- zend_object_value retval;
- wrapped_grpc_server *intern;
-
- intern = (wrapped_grpc_server *)emalloc(sizeof(wrapped_grpc_server));
- memset(intern, 0, sizeof(wrapped_grpc_server));
-
+php_grpc_zend_object create_wrapped_grpc_server(zend_class_entry *class_type
+ TSRMLS_DC) {
+ PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_server);
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
object_properties_init(&intern->std, class_type);
- retval.handle = zend_objects_store_put(
- intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
- free_wrapped_grpc_server, NULL TSRMLS_CC);
- retval.handlers = zend_get_std_object_handlers();
- return retval;
+ PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_server, server_ce_handlers);
}
/**
@@ -95,10 +87,10 @@ zend_object_value create_wrapped_grpc_server(zend_class_entry *class_type
* @param array $args The arguments to pass to the server (optional)
*/
PHP_METHOD(Server, __construct) {
- wrapped_grpc_server *server =
- (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC);
+ wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis());
zval *args_array = NULL;
grpc_channel_args args;
+
/* "|a" == 1 optional array */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", &args_array) ==
FAILURE) {
@@ -110,6 +102,8 @@ PHP_METHOD(Server, __construct) {
if (args_array == NULL) {
server->wrapped = grpc_server_create(NULL, NULL);
} else {
+ //TODO(thinkerou): deal it if key of array is long, crash now on php7
+ // and update unit test case
php_grpc_read_args_array(args_array, &args TSRMLS_CC);
server->wrapped = grpc_server_create(&args, NULL);
efree(args.args);
@@ -126,15 +120,16 @@ PHP_METHOD(Server, __construct) {
*/
PHP_METHOD(Server, requestCall) {
grpc_call_error error_code;
- wrapped_grpc_server *server =
- (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC);
grpc_call *call;
grpc_call_details details;
grpc_metadata_array metadata;
- zval *result;
grpc_event event;
- MAKE_STD_ZVAL(result);
+
+ wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis());
+ zval *result;
+ PHP_GRPC_MAKE_STD_ZVAL(result);
object_init(result);
+
grpc_call_details_init(&details);
grpc_metadata_array_init(&metadata);
error_code =
@@ -146,20 +141,37 @@ PHP_METHOD(Server, requestCall) {
goto cleanup;
}
event = grpc_completion_queue_pluck(completion_queue, NULL,
- gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+ gpr_inf_future(GPR_CLOCK_REALTIME),
+ NULL);
if (!event.success) {
zend_throw_exception(spl_ce_LogicException,
"Failed to request a call for some reason",
1 TSRMLS_CC);
goto cleanup;
}
+ php_grpc_add_property_string(result, "method", details.method, true);
+ php_grpc_add_property_string(result, "host", details.host, true);
+#if PHP_MAJOR_VERSION < 7
add_property_zval(result, "call", grpc_php_wrap_call(call, true TSRMLS_CC));
- add_property_string(result, "method", details.method, true);
- add_property_string(result, "host", details.host, true);
add_property_zval(result, "absolute_deadline",
grpc_php_wrap_timeval(details.deadline TSRMLS_CC));
- add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata TSRMLS_CC));
-cleanup:
+ add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata
+ TSRMLS_CC));
+#else
+ zval zv_call;
+ zval zv_timeval;
+ zval zv_md;
+ //TODO(thinkerou): why use zval* to unit test error?
+ zv_call = *grpc_php_wrap_call(call, true);
+ zv_timeval = *grpc_php_wrap_timeval(details.deadline);
+ zv_md = *grpc_parse_metadata_array(&metadata);
+
+ add_property_zval(result, "call", &zv_call);
+ add_property_zval(result, "absolute_deadline", &zv_timeval);
+ add_property_zval(result, "metadata", &zv_md);
+#endif
+
+ cleanup:
grpc_call_details_destroy(&details);
grpc_metadata_array_destroy(&metadata);
RETURN_DESTROY_ZVAL(result);
@@ -171,13 +183,13 @@ cleanup:
* @return true on success, false on failure
*/
PHP_METHOD(Server, addHttp2Port) {
- wrapped_grpc_server *server =
- (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC);
const char *addr;
- int addr_len;
+ php_grpc_int addr_len;
+ wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis());
+
/* "s" == 1 string */
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len) ==
- FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len)
+ == FAILURE) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"add_http2_port expects a string", 1 TSRMLS_CC);
return;
@@ -186,11 +198,11 @@ PHP_METHOD(Server, addHttp2Port) {
}
PHP_METHOD(Server, addSecureHttp2Port) {
- wrapped_grpc_server *server =
- (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC);
const char *addr;
- int addr_len;
+ php_grpc_int addr_len;
zval *creds_obj;
+ wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis());
+
/* "sO" == 1 string, 1 object */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO", &addr, &addr_len,
&creds_obj, grpc_ce_server_credentials) ==
@@ -201,8 +213,7 @@ PHP_METHOD(Server, addSecureHttp2Port) {
return;
}
wrapped_grpc_server_credentials *creds =
- (wrapped_grpc_server_credentials *)zend_object_store_get_object(
- creds_obj TSRMLS_CC);
+ Z_WRAPPED_GRPC_SERVER_CREDS_P(creds_obj);
RETURN_LONG(grpc_server_add_secure_http2_port(server->wrapped, addr,
creds->wrapped));
}
@@ -212,21 +223,23 @@ PHP_METHOD(Server, addSecureHttp2Port) {
* @return Void
*/
PHP_METHOD(Server, start) {
- wrapped_grpc_server *server =
- (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC);
+ wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis());
grpc_server_start(server->wrapped);
}
static zend_function_entry server_methods[] = {
- PHP_ME(Server, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
- PHP_ME(Server, requestCall, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Server, addHttp2Port, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Server, addSecureHttp2Port, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Server, start, NULL, ZEND_ACC_PUBLIC) PHP_FE_END};
+ PHP_ME(Server, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+ PHP_ME(Server, requestCall, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Server, addHttp2Port, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Server, addSecureHttp2Port, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Server, start, NULL, ZEND_ACC_PUBLIC)
+ PHP_FE_END
+};
void grpc_init_server(TSRMLS_D) {
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "Grpc\\Server", server_methods);
ce.create_object = create_wrapped_grpc_server;
grpc_ce_server = zend_register_internal_class(&ce TSRMLS_CC);
+ PHP_GRPC_INIT_HANDLER(wrapped_grpc_server, server_ce_handlers);
}
diff --git a/src/php/ext/grpc/server.h b/src/php/ext/grpc/server.h
index 022257f37c..a635bc11df 100755
--- a/src/php/ext/grpc/server.h
+++ b/src/php/ext/grpc/server.h
@@ -49,11 +49,26 @@
extern zend_class_entry *grpc_ce_server;
/* Wrapper struct for grpc_server that can be associated with a PHP object */
-typedef struct wrapped_grpc_server {
- zend_object std;
-
+PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_server)
grpc_server *wrapped;
-} wrapped_grpc_server;
+PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_server)
+
+#if PHP_MAJOR_VERSION < 7
+
+#define Z_WRAPPED_GRPC_SERVER_P(zv) \
+ (wrapped_grpc_server *)zend_object_store_get_object(zv TSRMLS_CC)
+
+#else
+
+static inline wrapped_grpc_server
+*wrapped_grpc_server_from_obj(zend_object *obj) {
+ return (wrapped_grpc_server*)((char*)(obj) -
+ XtOffsetOf(wrapped_grpc_server, std));
+}
+
+#define Z_WRAPPED_GRPC_SERVER_P(zv) wrapped_grpc_server_from_obj(Z_OBJ_P((zv)))
+
+#endif /* PHP_MAJOR_VERSION */
/* Initializes the Server class */
void grpc_init_server(TSRMLS_D);
diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c
index 505da10a28..b05896af4a 100644
--- a/src/php/ext/grpc/server_credentials.c
+++ b/src/php/ext/grpc/server_credentials.c
@@ -50,44 +50,35 @@
#include <grpc/grpc_security.h>
zend_class_entry *grpc_ce_server_credentials;
+#if PHP_MAJOR_VERSION >= 7
+static zend_object_handlers server_credentials_ce_handlers;
+#endif
/* Frees and destroys an instace of wrapped_grpc_server_credentials */
-void free_wrapped_grpc_server_credentials(void *object TSRMLS_DC) {
- wrapped_grpc_server_credentials *creds =
- (wrapped_grpc_server_credentials *)object;
- if (creds->wrapped != NULL) {
- grpc_server_credentials_release(creds->wrapped);
+PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_server_credentials)
+ if (p->wrapped != NULL) {
+ grpc_server_credentials_release(p->wrapped);
}
- efree(creds);
-}
+PHP_GRPC_FREE_WRAPPED_FUNC_END()
/* Initializes an instace of wrapped_grpc_server_credentials to be associated
* with an object of a class specified by class_type */
-zend_object_value create_wrapped_grpc_server_credentials(
+php_grpc_zend_object create_wrapped_grpc_server_credentials(
zend_class_entry *class_type TSRMLS_DC) {
- zend_object_value retval;
- wrapped_grpc_server_credentials *intern;
-
- intern = (wrapped_grpc_server_credentials *)emalloc(
- sizeof(wrapped_grpc_server_credentials));
- memset(intern, 0, sizeof(wrapped_grpc_server_credentials));
-
+ PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_server_credentials);
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
object_properties_init(&intern->std, class_type);
- retval.handle = zend_objects_store_put(
- intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
- free_wrapped_grpc_server_credentials, NULL TSRMLS_CC);
- retval.handlers = zend_get_std_object_handlers();
- return retval;
+ PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_server_credentials,
+ server_credentials_ce_handlers);
}
-zval *grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped TSRMLS_DC) {
+zval *grpc_php_wrap_server_credentials(grpc_server_credentials
+ *wrapped TSRMLS_DC) {
zval *server_credentials_object;
- MAKE_STD_ZVAL(server_credentials_object);
+ PHP_GRPC_MAKE_STD_ZVAL(server_credentials_object);
object_init_ex(server_credentials_object, grpc_ce_server_credentials);
wrapped_grpc_server_credentials *server_credentials =
- (wrapped_grpc_server_credentials *)zend_object_store_get_object(
- server_credentials_object TSRMLS_CC);
+ Z_WRAPPED_GRPC_SERVER_CREDS_P(server_credentials_object);
server_credentials->wrapped = wrapped;
return server_credentials_object;
}
@@ -103,7 +94,9 @@ PHP_METHOD(ServerCredentials, createSsl) {
char *pem_root_certs = 0;
grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
- int root_certs_length = 0, private_key_length, cert_chain_length;
+ php_grpc_int root_certs_length = 0;
+ php_grpc_int private_key_length;
+ php_grpc_int cert_chain_length;
/* "s!ss" == 1 nullable string, 2 strings */
/* TODO: support multiple key cert pairs. */
@@ -120,17 +113,23 @@ PHP_METHOD(ServerCredentials, createSsl) {
grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex(
pem_root_certs, &pem_key_cert_pair, 1,
GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL);
- zval *creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC);
+ zval *creds_object;
+ PHP_GRPC_MAKE_STD_ZVAL(creds_object);
+ creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
static zend_function_entry server_credentials_methods[] = {
- PHP_ME(ServerCredentials, createSsl, NULL,
- ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END};
+ PHP_ME(ServerCredentials, createSsl, NULL,
+ ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_FE_END
+ };
void grpc_init_server_credentials(TSRMLS_D) {
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "Grpc\\ServerCredentials", server_credentials_methods);
ce.create_object = create_wrapped_grpc_server_credentials;
grpc_ce_server_credentials = zend_register_internal_class(&ce TSRMLS_CC);
+ PHP_GRPC_INIT_HANDLER(wrapped_grpc_server_credentials,
+ server_credentials_ce_handlers);
}
diff --git a/src/php/ext/grpc/server_credentials.h b/src/php/ext/grpc/server_credentials.h
index 7101d65000..6781a614b1 100755
--- a/src/php/ext/grpc/server_credentials.h
+++ b/src/php/ext/grpc/server_credentials.h
@@ -51,11 +51,27 @@ extern zend_class_entry *grpc_ce_server_credentials;
/* Wrapper struct for grpc_server_credentials that can be associated with a PHP
* object */
-typedef struct wrapped_grpc_server_credentials {
- zend_object std;
-
+PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_server_credentials)
grpc_server_credentials *wrapped;
-} wrapped_grpc_server_credentials;
+PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_server_credentials)
+
+#if PHP_MAJOR_VERSION < 7
+
+#define Z_WRAPPED_GRPC_SERVER_CREDS_P(zv) \
+ (wrapped_grpc_server_credentials *)zend_object_store_get_object(zv TSRMLS_CC)
+
+#else
+
+static inline wrapped_grpc_server_credentials
+*wrapped_grpc_server_credentials_from_obj(zend_object *obj) {
+ return (wrapped_grpc_server_credentials*)(
+ (char*)(obj) - XtOffsetOf(wrapped_grpc_server_credentials, std));
+}
+
+#define Z_WRAPPED_GRPC_SERVER_CREDS_P(zv) \
+ wrapped_grpc_server_credentials_from_obj(Z_OBJ_P((zv)))
+
+#endif /* PHP_MAJOR_VERSION */
/* Initializes the Server_Credentials PHP class */
void grpc_init_server_credentials(TSRMLS_D);
diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c
index 5e242162a8..e145d96772 100644
--- a/src/php/ext/grpc/timeval.c
+++ b/src/php/ext/grpc/timeval.c
@@ -51,34 +51,29 @@
#include <grpc/support/time.h>
zend_class_entry *grpc_ce_timeval;
+#if PHP_MAJOR_VERSION >= 7
+static zend_object_handlers timeval_ce_handlers;
+#endif
/* Frees and destroys an instance of wrapped_grpc_call */
-void free_wrapped_grpc_timeval(void *object TSRMLS_DC) { efree(object); }
+PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_timeval)
+PHP_GRPC_FREE_WRAPPED_FUNC_END()
/* Initializes an instance of wrapped_grpc_timeval to be associated with an
* object of a class specified by class_type */
-zend_object_value create_wrapped_grpc_timeval(zend_class_entry *class_type
- TSRMLS_DC) {
- zend_object_value retval;
- wrapped_grpc_timeval *intern;
- intern = (wrapped_grpc_timeval *)emalloc(sizeof(wrapped_grpc_timeval));
- memset(intern, 0, sizeof(wrapped_grpc_timeval));
+php_grpc_zend_object create_wrapped_grpc_timeval(zend_class_entry *class_type
+ TSRMLS_DC) {
+ PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_timeval);
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
object_properties_init(&intern->std, class_type);
- retval.handle = zend_objects_store_put(
- intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
- free_wrapped_grpc_timeval, NULL TSRMLS_CC);
- retval.handlers = zend_get_std_object_handlers();
- return retval;
+ PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_timeval, timeval_ce_handlers);
}
zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC) {
zval *timeval_object;
- MAKE_STD_ZVAL(timeval_object);
+ PHP_GRPC_MAKE_STD_ZVAL(timeval_object);
object_init_ex(timeval_object, grpc_ce_timeval);
- wrapped_grpc_timeval *timeval =
- (wrapped_grpc_timeval *)zend_object_store_get_object(
- timeval_object TSRMLS_CC);
+ wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(timeval_object);
memcpy(&timeval->wrapped, &wrapped, sizeof(gpr_timespec));
return timeval_object;
}
@@ -88,9 +83,9 @@ zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC) {
* @param long $usec The number of microseconds in the interval
*/
PHP_METHOD(Timeval, __construct) {
- wrapped_grpc_timeval *timeval =
- (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC);
- long microseconds;
+ wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(getThis());
+ php_grpc_long microseconds;
+
/* "l" == 1 long */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &microseconds) ==
FAILURE) {
@@ -110,6 +105,7 @@ PHP_METHOD(Timeval, __construct) {
*/
PHP_METHOD(Timeval, add) {
zval *other_obj;
+
/* "O" == 1 Object */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj,
grpc_ce_timeval) == FAILURE) {
@@ -117,12 +113,13 @@ PHP_METHOD(Timeval, add) {
"add expects a Timeval", 1 TSRMLS_CC);
return;
}
- wrapped_grpc_timeval *self =
- (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC);
- wrapped_grpc_timeval *other =
- (wrapped_grpc_timeval *)zend_object_store_get_object(other_obj TSRMLS_CC);
- zval *sum =
- grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) TSRMLS_CC);
+ wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis());
+ wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj);
+ zval *sum;
+ PHP_GRPC_MAKE_STD_ZVAL(sum);
+ sum =
+ grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped)
+ TSRMLS_CC);
RETURN_DESTROY_ZVAL(sum);
}
@@ -134,6 +131,7 @@ PHP_METHOD(Timeval, add) {
*/
PHP_METHOD(Timeval, subtract) {
zval *other_obj;
+
/* "O" == 1 Object */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj,
grpc_ce_timeval) == FAILURE) {
@@ -141,12 +139,13 @@ PHP_METHOD(Timeval, subtract) {
"subtract expects a Timeval", 1 TSRMLS_CC);
return;
}
- wrapped_grpc_timeval *self =
- (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC);
- wrapped_grpc_timeval *other =
- (wrapped_grpc_timeval *)zend_object_store_get_object(other_obj TSRMLS_CC);
- zval *diff =
- grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) TSRMLS_CC);
+ wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis());
+ wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj);
+ zval *diff;
+ PHP_GRPC_MAKE_STD_ZVAL(diff);
+ diff =
+ grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped)
+ TSRMLS_CC);
RETURN_DESTROY_ZVAL(diff);
}
@@ -158,7 +157,9 @@ PHP_METHOD(Timeval, subtract) {
* @return long
*/
PHP_METHOD(Timeval, compare) {
- zval *a_obj, *b_obj;
+ zval *a_obj;
+ zval *b_obj;
+
/* "OO" == 2 Objects */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &a_obj,
grpc_ce_timeval, &b_obj,
@@ -167,10 +168,8 @@ PHP_METHOD(Timeval, compare) {
"compare expects two Timevals", 1 TSRMLS_CC);
return;
}
- wrapped_grpc_timeval *a =
- (wrapped_grpc_timeval *)zend_object_store_get_object(a_obj TSRMLS_CC);
- wrapped_grpc_timeval *b =
- (wrapped_grpc_timeval *)zend_object_store_get_object(b_obj TSRMLS_CC);
+ wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj);
+ wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj);
long result = gpr_time_cmp(a->wrapped, b->wrapped);
RETURN_LONG(result);
}
@@ -183,7 +182,10 @@ PHP_METHOD(Timeval, compare) {
* @return bool True if $a and $b are within $threshold, False otherwise
*/
PHP_METHOD(Timeval, similar) {
- zval *a_obj, *b_obj, *thresh_obj;
+ zval *a_obj;
+ zval *b_obj;
+ zval *thresh_obj;
+
/* "OOO" == 3 Objects */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOO", &a_obj,
grpc_ce_timeval, &b_obj, grpc_ce_timeval,
@@ -192,13 +194,9 @@ PHP_METHOD(Timeval, similar) {
"compare expects three Timevals", 1 TSRMLS_CC);
return;
}
- wrapped_grpc_timeval *a =
- (wrapped_grpc_timeval *)zend_object_store_get_object(a_obj TSRMLS_CC);
- wrapped_grpc_timeval *b =
- (wrapped_grpc_timeval *)zend_object_store_get_object(b_obj TSRMLS_CC);
- wrapped_grpc_timeval *thresh =
- (wrapped_grpc_timeval *)zend_object_store_get_object(
- thresh_obj TSRMLS_CC);
+ wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj);
+ wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj);
+ wrapped_grpc_timeval *thresh = Z_WRAPPED_GRPC_TIMEVAL_P(thresh_obj);
int result = gpr_time_similar(a->wrapped, b->wrapped, thresh->wrapped);
RETURN_BOOL(result);
}
@@ -208,7 +206,9 @@ PHP_METHOD(Timeval, similar) {
* @return Timeval The current time
*/
PHP_METHOD(Timeval, now) {
- zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC);
+ zval *now;
+ PHP_GRPC_MAKE_STD_ZVAL(now);
+ now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC);
RETURN_DESTROY_ZVAL(now);
}
@@ -217,7 +217,9 @@ PHP_METHOD(Timeval, now) {
* @return Timeval Zero length time interval
*/
PHP_METHOD(Timeval, zero) {
- zval *grpc_php_timeval_zero =
+ zval *grpc_php_timeval_zero;
+ PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_zero);
+ grpc_php_timeval_zero =
grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC);
RETURN_ZVAL(grpc_php_timeval_zero,
false, /* Copy original before returning? */
@@ -229,7 +231,9 @@ PHP_METHOD(Timeval, zero) {
* @return Timeval Infinite future time value
*/
PHP_METHOD(Timeval, infFuture) {
- zval *grpc_php_timeval_inf_future =
+ zval *grpc_php_timeval_inf_future;
+ PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_inf_future);
+ grpc_php_timeval_inf_future =
grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC);
RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future);
}
@@ -239,7 +243,9 @@ PHP_METHOD(Timeval, infFuture) {
* @return Timeval Infinite past time value
*/
PHP_METHOD(Timeval, infPast) {
- zval *grpc_php_timeval_inf_past =
+ zval *grpc_php_timeval_inf_past;
+ PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_inf_past);
+ grpc_php_timeval_inf_past =
grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC);
RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past);
}
@@ -249,28 +255,30 @@ PHP_METHOD(Timeval, infPast) {
* @return void
*/
PHP_METHOD(Timeval, sleepUntil) {
- wrapped_grpc_timeval *this =
- (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC);
+ wrapped_grpc_timeval *this = Z_WRAPPED_GRPC_TIMEVAL_P(getThis());
gpr_sleep_until(this->wrapped);
}
static zend_function_entry timeval_methods[] = {
- PHP_ME(Timeval, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
- PHP_ME(Timeval, add, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timeval, compare, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Timeval, infFuture, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Timeval, infPast, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Timeval, now, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Timeval, similar, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Timeval, sleepUntil, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timeval, subtract, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timeval, zero, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END};
+ PHP_ME(Timeval, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+ PHP_ME(Timeval, add, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Timeval, compare, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timeval, infFuture, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timeval, infPast, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timeval, now, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timeval, similar, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timeval, sleepUntil, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Timeval, subtract, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Timeval, zero, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_FE_END
+};
void grpc_init_timeval(TSRMLS_D) {
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "Grpc\\Timeval", timeval_methods);
ce.create_object = create_wrapped_grpc_timeval;
grpc_ce_timeval = zend_register_internal_class(&ce TSRMLS_CC);
+ PHP_GRPC_INIT_HANDLER(wrapped_grpc_timeval, timeval_ce_handlers);
}
void grpc_shutdown_timeval(TSRMLS_D) {}
diff --git a/src/php/ext/grpc/timeval.h b/src/php/ext/grpc/timeval.h
index 7456eb6d58..63a1d702f3 100755
--- a/src/php/ext/grpc/timeval.h
+++ b/src/php/ext/grpc/timeval.h
@@ -50,11 +50,27 @@
extern zend_class_entry *grpc_ce_timeval;
/* Wrapper struct for timeval that can be associated with a PHP object */
-typedef struct wrapped_grpc_timeval {
- zend_object std;
-
+PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_timeval)
gpr_timespec wrapped;
-} wrapped_grpc_timeval;
+PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_timeval)
+
+#if PHP_MAJOR_VERSION < 7
+
+#define Z_WRAPPED_GRPC_TIMEVAL_P(zv) \
+ (wrapped_grpc_timeval *)zend_object_store_get_object(zv TSRMLS_CC)
+
+#else
+
+static inline wrapped_grpc_timeval
+*wrapped_grpc_timeval_from_obj(zend_object *obj) {
+ return (wrapped_grpc_timeval*)((char*)(obj) -
+ XtOffsetOf(wrapped_grpc_timeval, std));
+}
+
+#define Z_WRAPPED_GRPC_TIMEVAL_P(zv) \
+ wrapped_grpc_timeval_from_obj(Z_OBJ_P((zv)))
+
+#endif /* PHP_MAJOR_VERSION */
/* Initialize the Timeval PHP class */
void grpc_init_timeval(TSRMLS_D);
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index df3fe85d44..2fec1bd9cc 100755..100644
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -84,8 +84,8 @@ class BaseStub
}
if ($channel) {
if (!is_a($channel, 'Channel')) {
- throw new \Exception("The channel argument is not a".
- "Channel object");
+ throw new \Exception('The channel argument is not a'.
+ 'Channel object');
}
$this->channel = $channel;
} else {
diff --git a/src/php/lib/Grpc/BidiStreamingCall.php b/src/php/lib/Grpc/BidiStreamingCall.php
index 95e51c5088..c2fdb94b86 100644
--- a/src/php/lib/Grpc/BidiStreamingCall.php
+++ b/src/php/lib/Grpc/BidiStreamingCall.php
@@ -113,6 +113,7 @@ class BidiStreamingCall extends AbstractCall
]);
$this->trailing_metadata = $status_event->status->metadata;
+
return $status_event->status;
}
}
diff --git a/src/php/lib/Grpc/ClientStreamingCall.php b/src/php/lib/Grpc/ClientStreamingCall.php
index 315a406735..4050f7ed06 100644
--- a/src/php/lib/Grpc/ClientStreamingCall.php
+++ b/src/php/lib/Grpc/ClientStreamingCall.php
@@ -88,6 +88,7 @@ class ClientStreamingCall extends AbstractCall
$status = $event->status;
$this->trailing_metadata = $status->metadata;
+
return [$this->deserializeResponse($event->message), $status];
}
}
diff --git a/src/php/lib/Grpc/ServerStreamingCall.php b/src/php/lib/Grpc/ServerStreamingCall.php
index 53599fe4ae..ba89d9f972 100644
--- a/src/php/lib/Grpc/ServerStreamingCall.php
+++ b/src/php/lib/Grpc/ServerStreamingCall.php
@@ -92,6 +92,7 @@ class ServerStreamingCall extends AbstractCall
]);
$this->trailing_metadata = $status_event->status->metadata;
+
return $status_event->status;
}
}
diff --git a/src/php/lib/Grpc/UnaryCall.php b/src/php/lib/Grpc/UnaryCall.php
index b114b771b8..a71b05dc93 100644
--- a/src/php/lib/Grpc/UnaryCall.php
+++ b/src/php/lib/Grpc/UnaryCall.php
@@ -77,6 +77,7 @@ class UnaryCall extends AbstractCall
$status = $event->status;
$this->trailing_metadata = $status->metadata;
+
return [$this->deserializeResponse($event->message), $status];
}
}
diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php
index 43b3199d92..bf40549a04 100755
--- a/src/php/tests/interop/interop_client.php
+++ b/src/php/tests/interop/interop_client.php
@@ -450,7 +450,7 @@ function statusCodeAndMessage($stub)
{
$echo_status = new grpc\testing\EchoStatus();
$echo_status->setCode(2);
- $echo_status->setMessage("test status message");
+ $echo_status->setMessage('test status message');
$request = new grpc\testing\SimpleRequest();
$request->setResponseStatus($echo_status);
@@ -460,7 +460,7 @@ function statusCodeAndMessage($stub)
hardAssert($status->code === 2,
'Received unexpected status code');
- hardAssert($status->details === "test status message",
+ hardAssert($status->details === 'test status message',
'Received unexpected status details');
$streaming_call = $stub->FullDuplexCall();
@@ -473,7 +473,7 @@ function statusCodeAndMessage($stub)
$status = $streaming_call->getStatus();
hardAssert($status->code === 2,
'Received unexpected status code');
- hardAssert($status->details === "test status message",
+ hardAssert($status->details === 'test status message',
'Received unexpected status details');
}
@@ -570,9 +570,9 @@ function _makeStub($args)
}
if ($test_case == 'unimplemented_method') {
- $stub = new grpc\testing\UnimplementedServiceClient($server_address, $opts);
+ $stub = new grpc\testing\UnimplementedServiceClient($server_address, $opts);
} else {
- $stub = new grpc\testing\TestServiceClient($server_address, $opts);
+ $stub = new grpc\testing\TestServiceClient($server_address, $opts);
}
return $stub;
diff --git a/src/php/tests/unit_tests/CallCredentialsTest.php b/src/php/tests/unit_tests/CallCredentialsTest.php
index 5fec06cd13..1994c8afe5 100644
--- a/src/php/tests/unit_tests/CallCredentialsTest.php
+++ b/src/php/tests/unit_tests/CallCredentialsTest.php
@@ -148,7 +148,8 @@ class CallCredentialsTest extends PHPUnit_Framework_TestCase
$this->call_credentials,
$call_credentials2
);
- $this->assertSame('Grpc\CallCredentials', get_class($call_credentials3));
+ $this->assertSame('Grpc\CallCredentials',
+ get_class($call_credentials3));
}
/**
diff --git a/src/php/tests/unit_tests/CallTest.php b/src/php/tests/unit_tests/CallTest.php
index fa026f0935..d736f51546 100755..100644
--- a/src/php/tests/unit_tests/CallTest.php
+++ b/src/php/tests/unit_tests/CallTest.php
@@ -50,6 +50,18 @@ class CallTest extends PHPUnit_Framework_TestCase
Grpc\Timeval::infFuture());
}
+ public function tearDown()
+ {
+ unset($this->call);
+ unset($this->channel);
+ }
+
+ public function testConstructor()
+ {
+ $this->assertSame('Grpc\Call', get_class($this->call));
+ $this->assertObjectHasAttribute('channel', $this->call);
+ }
+
public function testAddEmptyMetadata()
{
$batch = [
@@ -81,7 +93,8 @@ class CallTest extends PHPUnit_Framework_TestCase
{
$batch = [
Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1'],
- 'key2' => ['value2', 'value3'], ],
+ 'key2' => ['value2',
+ 'value3'], ],
];
$result = $this->call->startBatch($batch);
$this->assertTrue($result->send_metadata);
@@ -118,4 +131,38 @@ class CallTest extends PHPUnit_Framework_TestCase
];
$result = $this->call->startBatch($batch);
}
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidConstuctor()
+ {
+ $this->call = new Grpc\Call();
+ $this->assertNull($this->call);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidConstuctor2()
+ {
+ $this->call = new Grpc\Call('hi', 'hi', 'hi');
+ $this->assertNull($this->call);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidSetCredentials()
+ {
+ $this->call->setCredentials('hi');
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidSetCredentials2()
+ {
+ $this->call->setCredentials([]);
+ }
}
diff --git a/src/php/tests/unit_tests/ChannelCredentialsTest.php b/src/php/tests/unit_tests/ChannelCredentialsTest.php
index 56c1d8f006..e822929ccd 100644
--- a/src/php/tests/unit_tests/ChannelCredentialsTest.php
+++ b/src/php/tests/unit_tests/ChannelCredentialsTest.php
@@ -42,10 +42,23 @@ class ChanellCredentialsTest extends PHPUnit_Framework_TestCase
{
}
- public function testCreateDefault()
+ public function testCreateSslWith3Null()
{
- $channel_credentials = Grpc\ChannelCredentials::createDefault();
- $this->assertSame('Grpc\ChannelCredentials', get_class($channel_credentials));
+ $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
+ null);
+ $this->assertNotNull($channel_credentials);
+ }
+
+ public function testCreateSslWith3NullString()
+ {
+ $channel_credentials = Grpc\ChannelCredentials::createSsl('', '', '');
+ $this->assertNotNull($channel_credentials);
+ }
+
+ public function testCreateInsecure()
+ {
+ $channel_credentials = Grpc\ChannelCredentials::createInsecure();
+ $this->assertNull($channel_credentials);
}
/**
@@ -64,10 +77,4 @@ class ChanellCredentialsTest extends PHPUnit_Framework_TestCase
$channel_credentials = Grpc\ChannelCredentials::createComposite(
'something', 'something');
}
-
- public function testCreateInsecure()
- {
- $channel_credentials = Grpc\ChannelCredentials::createInsecure();
- $this->assertNull($channel_credentials);
- }
}
diff --git a/src/php/tests/unit_tests/ChannelTest.php b/src/php/tests/unit_tests/ChannelTest.php
index a1f9053c39..4b35b1a28c 100644
--- a/src/php/tests/unit_tests/ChannelTest.php
+++ b/src/php/tests/unit_tests/ChannelTest.php
@@ -40,6 +40,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function tearDown()
{
+ unset($this->channel);
}
public function testInsecureCredentials()
@@ -53,6 +54,82 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$this->assertSame('Grpc\Channel', get_class($this->channel));
}
+ public function testGetConnectivityState()
+ {
+ $this->channel = new Grpc\Channel('localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+ $state = $this->channel->getConnectivityState();
+ $this->assertEquals(0, $state);
+ }
+
+ public function testGetConnectivityStateWithInt()
+ {
+ $this->channel = new Grpc\Channel('localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+ $state = $this->channel->getConnectivityState(123);
+ $this->assertEquals(0, $state);
+ }
+
+ public function testGetConnectivityStateWithString()
+ {
+ $this->channel = new Grpc\Channel('localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+ $state = $this->channel->getConnectivityState('hello');
+ $this->assertEquals(0, $state);
+ }
+
+ public function testGetConnectivityStateWithBool()
+ {
+ $this->channel = new Grpc\Channel('localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+ $state = $this->channel->getConnectivityState(true);
+ $this->assertEquals(0, $state);
+ }
+
+ public function testGetTarget()
+ {
+ $this->channel = new Grpc\Channel('localhost:8888',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+ $target = $this->channel->getTarget();
+ $this->assertTrue(is_string($target));
+ }
+
+ public function testWatchConnectivityState()
+ {
+ $this->channel = new Grpc\Channel('localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+ $time = new Grpc\Timeval(1000);
+ $state = $this->channel->watchConnectivityState(123, $time);
+ $this->assertTrue($state);
+ unset($time);
+ }
+
+ public function testClose()
+ {
+ $this->channel = new Grpc\Channel('localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+ $this->assertNotNull($this->channel);
+ $this->channel->close();
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidConstructorWithNull()
+ {
+ $this->channel = new Grpc\Channel();
+ $this->assertNull($this->channel);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidConstructorWith()
+ {
+ $this->channel = new Grpc\Channel('localhost', 'invalid');
+ $this->assertNull($this->channel);
+ }
+
/**
* @expectedException InvalidArgumentException
*/
@@ -78,4 +155,34 @@ class ChannelTest extends PHPUnit_Framework_TestCase
]
);
}
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidGetConnectivityStateWithArray()
+ {
+ $this->channel = new Grpc\Channel('localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+ $this->channel->getConnectivityState([]);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidWatchConnectivityState()
+ {
+ $this->channel = new Grpc\Channel('localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+ $this->channel->watchConnectivityState([]);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidWatchConnectivityState2()
+ {
+ $this->channel = new Grpc\Channel('localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+ $this->channel->watchConnectivityState(1, 'hi');
+ }
}
diff --git a/src/php/tests/unit_tests/EndToEndTest.php b/src/php/tests/unit_tests/EndToEndTest.php
index 2b09f9d112..09364580c0 100755..100644
--- a/src/php/tests/unit_tests/EndToEndTest.php
+++ b/src/php/tests/unit_tests/EndToEndTest.php
@@ -521,7 +521,8 @@ class EndToEndTest extends PHPUnit_Framework_TestCase
public function testGetConnectivityState()
{
- $this->assertTrue($this->channel->getConnectivityState() == Grpc\CHANNEL_IDLE);
+ $this->assertTrue($this->channel->getConnectivityState() ==
+ Grpc\CHANNEL_IDLE);
}
public function testWatchConnectivityStateFailed()
diff --git a/src/php/tests/unit_tests/SecureEndToEndTest.php b/src/php/tests/unit_tests/SecureEndToEndTest.php
index c388ee5031..c388ee5031 100755..100644
--- a/src/php/tests/unit_tests/SecureEndToEndTest.php
+++ b/src/php/tests/unit_tests/SecureEndToEndTest.php
diff --git a/src/php/tests/unit_tests/ServerTest.php b/src/php/tests/unit_tests/ServerTest.php
index 76aaa06970..f2346ab113 100644
--- a/src/php/tests/unit_tests/ServerTest.php
+++ b/src/php/tests/unit_tests/ServerTest.php
@@ -36,10 +36,70 @@ class ServerTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
+ $this->server = null;
}
public function tearDown()
{
+ unset($this->server);
+ }
+
+ public function testConstructorWithNull()
+ {
+ $this->server = new Grpc\Server();
+ $this->assertNotNull($this->server);
+ }
+
+ public function testConstructorWithNullArray()
+ {
+ $this->server = new Grpc\Server([]);
+ $this->assertNotNull($this->server);
+ }
+
+ public function testConstructorWithArray()
+ {
+ // key of array must be string
+ $this->server = new Grpc\Server(['ip' => '127.0.0.1',
+ 'port' => '8080', ]);
+ $this->assertNotNull($this->server);
+ }
+
+ public function testRequestCall()
+ {
+ $this->server = new Grpc\Server();
+ $port = $this->server->addHttp2Port('0.0.0.0:8888');
+ $this->server->start();
+ $channel = new Grpc\Channel('localhost:8888',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+
+ $deadline = Grpc\Timeval::infFuture();
+ $call = new Grpc\Call($channel, 'dummy_method', $deadline);
+
+ $event = $call->startBatch([Grpc\OP_SEND_INITIAL_METADATA => [],
+ Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
+ ]);
+
+ $c = $this->server->requestCall();
+ $this->assertObjectHasAttribute('call', $c);
+ $this->assertObjectHasAttribute('method', $c);
+ $this->assertSame('dummy_method', $c->method);
+ $this->assertObjectHasAttribute('host', $c);
+ $this->assertTrue(is_string($c->host));
+ $this->assertObjectHasAttribute('absolute_deadline', $c);
+ $this->assertObjectHasAttribute('metadata', $c);
+
+ unset($call);
+ unset($channel);
+ }
+
+ private function createSslObj()
+ {
+ $server_credentials = Grpc\ServerCredentials::createSsl(
+ null,
+ file_get_contents(dirname(__FILE__).'/../data/server1.key'),
+ file_get_contents(dirname(__FILE__).'/../data/server1.pem'));
+
+ return $server_credentials;
}
/**
@@ -47,7 +107,8 @@ class ServerTest extends PHPUnit_Framework_TestCase
*/
public function testInvalidConstructor()
{
- $server = new Grpc\Server('invalid_host');
+ $this->server = new Grpc\Server('invalid_host');
+ $this->assertNull($this->server);
}
/**
@@ -56,7 +117,7 @@ class ServerTest extends PHPUnit_Framework_TestCase
public function testInvalidAddHttp2Port()
{
$this->server = new Grpc\Server([]);
- $this->port = $this->server->addHttp2Port(['0.0.0.0:0']);
+ $port = $this->server->addHttp2Port(['0.0.0.0:0']);
}
/**
@@ -65,6 +126,24 @@ class ServerTest extends PHPUnit_Framework_TestCase
public function testInvalidAddSecureHttp2Port()
{
$this->server = new Grpc\Server([]);
- $this->port = $this->server->addSecureHttp2Port(['0.0.0.0:0']);
+ $port = $this->server->addSecureHttp2Port(['0.0.0.0:0']);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidAddSecureHttp2Port2()
+ {
+ $this->server = new Grpc\Server();
+ $port = $this->server->addSecureHttp2Port('0.0.0.0:0');
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidAddSecureHttp2Port3()
+ {
+ $this->server = new Grpc\Server();
+ $port = $this->server->addSecureHttp2Port('0.0.0.0:0', 'invalid');
}
}
diff --git a/src/php/tests/unit_tests/TimevalTest.php b/src/php/tests/unit_tests/TimevalTest.php
index a3dbce079f..2d19f64c79 100755..100644
--- a/src/php/tests/unit_tests/TimevalTest.php
+++ b/src/php/tests/unit_tests/TimevalTest.php
@@ -33,6 +33,57 @@
*/
class TimevalTest extends PHPUnit_Framework_TestCase
{
+ public function setUp()
+ {
+ }
+
+ public function tearDown()
+ {
+ unset($this->time);
+ }
+
+ public function testConstructorWithInt()
+ {
+ $this->time = new Grpc\Timeval(1234);
+ $this->assertNotNull($this->time);
+ $this->assertSame('Grpc\Timeval', get_class($this->time));
+ }
+
+ public function testConstructorWithNegative()
+ {
+ $this->time = new Grpc\Timeval(-123);
+ $this->assertNotNull($this->time);
+ $this->assertSame('Grpc\Timeval', get_class($this->time));
+ }
+
+ public function testConstructorWithZero()
+ {
+ $this->time = new Grpc\Timeval(0);
+ $this->assertNotNull($this->time);
+ $this->assertSame('Grpc\Timeval', get_class($this->time));
+ }
+
+ public function testConstructorWithOct()
+ {
+ $this->time = new Grpc\Timeval(0123);
+ $this->assertNotNull($this->time);
+ $this->assertSame('Grpc\Timeval', get_class($this->time));
+ }
+
+ public function testConstructorWithHex()
+ {
+ $this->time = new Grpc\Timeval(0x1A);
+ $this->assertNotNull($this->time);
+ $this->assertSame('Grpc\Timeval', get_class($this->time));
+ }
+
+ public function testConstructorWithFloat()
+ {
+ $this->time = new Grpc\Timeval(123.456);
+ $this->assertNotNull($this->time);
+ $this->assertSame('Grpc\Timeval', get_class($this->time));
+ }
+
public function testCompareSame()
{
$zero = Grpc\Timeval::zero();
@@ -70,6 +121,7 @@ class TimevalTest extends PHPUnit_Framework_TestCase
public function testNowAndAdd()
{
$now = Grpc\Timeval::now();
+ $this->assertNotNull($now);
$delta = new Grpc\Timeval(1000);
$deadline = $now->add($delta);
$this->assertGreaterThan(0, Grpc\Timeval::compare($deadline, $now));
@@ -154,5 +206,6 @@ class TimevalTest extends PHPUnit_Framework_TestCase
public function testSimilarInvalidParam()
{
$a = Grpc\Timeval::similar(1000, 1100, 1200);
+ $this->assertNull($delta);
}
}
diff --git a/src/proto/census/census.proto b/src/proto/census/census.proto
index c869d851ff..c2a594b641 100644
--- a/src/proto/census/census.proto
+++ b/src/proto/census/census.proto
@@ -33,12 +33,12 @@ package google.census;
// All the census protos.
//
-// Nomenclature note: capitalized names below (like Metric) are protos.
+// Nomenclature note: capitalized names below (like Resource) are protos.
//
-// Census lets you define a Metric - something which can be measured, like the
+// Census lets you define a Resource - something which can be measured, like the
// latency of an RPC, the number of CPU cycles spent on an operation, or
// anything else you care to measure. You can record individual instances of
-// measurements (a double value) for every metric of interest. These
+// measurements (a double value) for every Resource of interest. These
// individual measurements are aggregated together into an Aggregation. There
// are two Aggregation types available: Distribution (describes the
// distribution of all measurements, possibly with a histogram) and
@@ -47,8 +47,8 @@ package google.census;
//
// You can define how your stats are broken down by Tag values and which
// Aggregations to use through a View. The corresponding combination of
-// Metric/View/Aggregation which is available to census clients is called a
-// ViewAggregation.
+// Resource/View/Aggregation which is available to census clients is called a
+// Metric.
// The following two types are copied from
@@ -85,26 +85,23 @@ message Timestamp {
int32 nanos = 2;
}
-// Describes a metric
-message Metric {
- // name of metric, e.g. rpc_latency, cpu.
+// Describes a Resource.
+message Resource {
+ // name of resource, e.g. rpc_latency, cpu. Must be unique.
string name = 1;
- // More detailed description of the metric, used in documentation.
+ // More detailed description of the resource, used in documentation.
string description = 2;
// Fundamental units of measurement supported by Census
// TODO(aveitch): expand this to include other S.I. units?
- message BasicUnit {
- enum Measure {
- UNKNOWN = 0;
- BITS = 1;
- BYTES = 2;
- SECS = 3;
- CORES = 4;
- MAX_UNITS = 5;
- }
- Measure type = 1;
+ enum BasicUnit {
+ UNKNOWN = 0;
+ BITS = 1;
+ BYTES = 2;
+ SECS = 3;
+ CORES = 4;
+ MAX_UNITS = 5;
}
// MeasurementUnit lets you build compound units of the form
@@ -124,7 +121,7 @@ message Metric {
// denominator: SECS
// denominator: SECS
//
- // To specify multiples (in power of 10) units, specify a non-zero prefix
+ // To specify multiples (in power of 10) of units, specify a non-zero prefix
// value, for example:
//
// - MB/s (i.e. megabytes / s):
@@ -141,32 +138,40 @@ message Metric {
repeated BasicUnit denominator = 3;
}
- // The units in which the Metric value is reported.
+ // The units in which Resource values are measured.
MeasurementUnit unit = 3;
-
- // Metrics will be assigned an ID when registered. Invalid if <= 0.
- int32 id = 4;
}
-// An Aggregation summarizes a series of individual Metric measurements, an
+// An Aggregation summarizes a series of individual Resource measurements, an
// AggregationDescriptor describes an Aggregation.
message AggregationDescriptor {
- // At most one set of options. If neither option is set, a default type
- // of Distribution (without a histogram component) will be used.
+ enum AggregationType {
+ // Unspecified. Should not be used.
+ UNKNOWN = 0;
+ // A count of measurements made.
+ COUNT = 1;
+ // A Distribution.
+ DISTRIBUTION = 2;
+ // Counts over fixed time intervals.
+ INTERVAL = 3;
+ }
+ // The type of Aggregation.
+ AggregationType type = 1;
+
+ // At most one set of options. It is illegal to specifiy an option for
+ // COUNT Aggregations. interval_boundaries must be set for INTERVAL types.
+ // bucket_boundaries are optional for DISTRIBUTION types.
oneof options {
- // Defines the histogram bucket boundaries for Distributions.
- BucketBoundaries bucket_boundaries = 1;
+ // Defines histogram bucket boundaries for Distributions.
+ BucketBoundaries bucket_boundaries = 2;
// Defines the time windows to record for IntervalStats.
- IntervalBoundaries interval_boundaries = 2;
+ IntervalBoundaries interval_boundaries = 3;
}
// A Distribution may optionally contain a histogram of the values in the
- // population. The bucket boundaries for that histogram is described by
- // `bucket_boundaries`.
- //
- // Describes histogram bucket boundaries. Defines `size(bounds) + 1` (= N)
- // buckets (for size(bounds) >= 1; if size(bounds) == 0, then no histogram
- // will be defined. The boundaries for bucket index i are:
+ // population. The bucket boundaries for that histogram are described by
+ // `bucket_boundaries`. This defines `size(bounds) + 1` (= N) buckets. The
+ // boundaries for bucket index i are:
//
// [-infinity, bounds[i]) for i == 0
// [bounds[i-1], bounds[i]) for 0 < i < N-2
@@ -196,8 +201,8 @@ message AggregationDescriptor {
// a specified set of histogram buckets, as defined in
// Aggregation.bucket_options.
//
-// The summary statistics are the count, mean, sum of the squared deviation from
-// the mean, the minimum, and the maximum of the set of population of values.
+// The summary statistics are the count, mean, minimum, and the maximum of the
+// set of population of values.
//
// Although it is not forbidden, it is generally a bad idea to include
// non-finite values (infinities or NaNs) in the population of values, as this
@@ -243,7 +248,7 @@ message Distribution {
message IntervalStats {
// Summary statistic over a single time window.
message Window {
- // The window duration.
+ // The window duration. Must be positive.
Duration window_size = 1;
// The number of measurements in this window.
int64 count = 2;
@@ -251,7 +256,7 @@ message IntervalStats {
double mean = 3;
}
- // Full set of windows for this metric.
+ // Full set of windows for this aggregation.
repeated Window window = 1;
}
@@ -264,24 +269,24 @@ message Tag {
// A View specifies an Aggregation and a set of tag keys. The Aggregation will
// be broken down by the unique set of matching tag values for each measurement.
message View {
- // Name of view.
+ // Name of view. Must be unique.
string name = 1;
// More detailed description, for documentation purposes.
string description = 2;
- // ID of Metric to associate with this View.
- int32 metric_id = 3;
+ // Name of Resource to be broken down for this view.
+ string resource_name = 3;
// Aggregation type to associate with this View.
AggregationDescriptor aggregation = 4;
- // Tag keys to match with a given Metric. If no keys are specified, then all
- // stats for the Metric are recorded. Keys must be unique.
+ // Tag keys to match with a given Resource measurement. If no keys are
+ // specified, then all stats are recorded. Keys must be unique.
repeated string tag_key = 5;
}
-// An Aggregation summarizes a series of individual Metric measures.
+// An Aggregation summarizes a series of individual Resource measurements.
message Aggregation {
// Name of this aggregation.
string name = 1;
@@ -291,23 +296,27 @@ message Aggregation {
// The data for this Aggregation.
oneof data {
- Distribution distribution = 3;
- IntervalStats interval_stats = 4;
+ uint64 count = 3;
+ Distribution distribution = 4;
+ IntervalStats interval_stats = 5;
}
// Tags associated with this Aggregation.
- repeated Tag tag = 5;
+ repeated Tag tag = 6;
}
-// A ViewAggregations represents all the Aggregations for a particular view.
-message ViewAggregations {
+// A Metric represents all the Aggregations for a particular view.
+message Metric {
+ // View associated with this Metric.
+ string view_name = 1;
+
// Aggregations - each will have a unique set of tag values for the tag_keys
// associated with the corresponding View.
- repeated Aggregation aggregation = 1;
+ repeated Aggregation aggregation = 2;
- // Start and end timestamps over which the value was accumulated. These
+ // Start and end timestamps over which the metric was accumulated. These
// values are not relevant/defined for IntervalStats aggregations, which are
// always accumulated over a fixed time period.
- Timestamp start = 2;
- Timestamp end = 3;
+ Timestamp start = 3;
+ Timestamp end = 4;
}
diff --git a/src/python/grpcio/.gitignore b/src/python/grpcio/.gitignore
index 7cd8fab273..3309795948 100644
--- a/src/python/grpcio/.gitignore
+++ b/src/python/grpcio/.gitignore
@@ -14,3 +14,4 @@ doc/
_grpcio_metadata.py
htmlcov/
grpc/_cython/_credentials
+poison.c
diff --git a/src/python/grpcio/_unixccompiler_patch.py b/src/python/grpcio/_unixccompiler_patch.py
index 0ce5d63e98..894c3ef395 100644
--- a/src/python/grpcio/_unixccompiler_patch.py
+++ b/src/python/grpcio/_unixccompiler_patch.py
@@ -34,6 +34,7 @@ from distutils import errors
from distutils import unixccompiler
import os
import os.path
+import shlex
import shutil
import sys
import tempfile
@@ -47,6 +48,9 @@ def _unix_commandfile_spawn(self, command):
Some commands like `gcc` (and friends like `clang`) support command files to
work around shell command length limits.
"""
+ # Sometimes distutils embeds the executables as full strings including some
+ # hard-coded flags rather than as lists.
+ command = list(shlex.split(command[0])) + list(command[1:])
command_base = os.path.basename(command[0].strip())
if command_base == 'ccache':
command_base = command[:2]
diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py
index 86a73fa836..d36ac23305 100644
--- a/src/python/grpcio/commands.py
+++ b/src/python/grpcio/commands.py
@@ -184,6 +184,71 @@ class BuildPy(build_py.build_py):
build_py.build_py.run(self)
+def _poison_extensions(extensions, message):
+ """Includes a file that will always fail to compile in all extensions."""
+ poison_filename = os.path.join(PYTHON_STEM, 'poison.c')
+ with open(poison_filename, 'w') as poison:
+ poison.write('#error {}'.format(message))
+ for extension in extensions:
+ extension.sources = [poison_filename]
+
+def check_and_update_cythonization(extensions):
+ """Replace .pyx files with their generated counterparts and return whether or
+ not cythonization still needs to occur."""
+ for extension in extensions:
+ generated_pyx_sources = []
+ other_sources = []
+ for source in extension.sources:
+ base, file_ext = os.path.splitext(source)
+ if file_ext == '.pyx':
+ generated_pyx_source = next(
+ (base + gen_ext for gen_ext in ('.c', '.cpp',)
+ if os.path.isfile(base + gen_ext)), None)
+ if generated_pyx_source:
+ generated_pyx_sources.append(generated_pyx_source)
+ else:
+ sys.stderr.write('Cython-generated files are missing...\n')
+ return False
+ else:
+ other_sources.append(source)
+ extension.sources = generated_pyx_sources + other_sources
+ sys.stderr.write('Found cython-generated files...\n')
+ return True
+
+def try_cythonize(extensions, linetracing=False, mandatory=True):
+ """Attempt to cythonize the extensions.
+
+ Args:
+ extensions: A list of `distutils.extension.Extension`.
+ linetracing: A bool indicating whether or not to enable linetracing.
+ mandatory: Whether or not having Cython-generated files is mandatory. If it
+ is, extensions will be poisoned when they can't be fully generated.
+ """
+ try:
+ # Break import style to ensure we have access to Cython post-setup_requires
+ import Cython.Build
+ except ImportError:
+ if mandatory:
+ sys.stderr.write(
+ "This package needs to generate C files with Cython but it cannot. "
+ "Poisoning extension sources to disallow extension commands...")
+ _poison_extensions(
+ extensions,
+ "Extensions have been poisoned due to missing Cython-generated code.")
+ return extensions
+ cython_compiler_directives = {}
+ if linetracing:
+ additional_define_macros = [('CYTHON_TRACE_NOGIL', '1')]
+ cython_compiler_directives['linetrace'] = True
+ return Cython.Build.cythonize(
+ extensions,
+ include_path=[
+ include_dir for extension in extensions for include_dir in extension.include_dirs
+ ],
+ compiler_directives=cython_compiler_directives
+ )
+
+
class BuildExt(build_ext.build_ext):
"""Custom build_ext command to enable compiler-specific flags."""
@@ -201,6 +266,8 @@ class BuildExt(build_ext.build_ext):
if compiler in BuildExt.LINK_OPTIONS:
for extension in self.extensions:
extension.extra_link_args += list(BuildExt.LINK_OPTIONS[compiler])
+ if not check_and_update_cythonization(self.extensions):
+ self.extensions = try_cythonize(self.extensions)
try:
build_ext.build_ext.build_extensions(self)
except Exception as error:
diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py
index fd015129f0..513839df7d 100644
--- a/src/python/grpcio/grpc/__init__.py
+++ b/src/python/grpcio/grpc/__init__.py
@@ -345,7 +345,7 @@ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)):
This method blocks until the value is available.
Returns:
- The bytes of the details of the RPC.
+ The details string of the RPC.
"""
raise NotImplementedError()
@@ -764,7 +764,7 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)):
details to transmit.
Args:
- details: The details bytes of the RPC to be transmitted to
+ details: The details string of the RPC to be transmitted to
the invocation side of the RPC.
"""
raise NotImplementedError()
diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py
index 29dbc3a668..3117dd1cb3 100644
--- a/src/python/grpcio/grpc/_channel.py
+++ b/src/python/grpcio/grpc/_channel.py
@@ -353,12 +353,12 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call):
else:
return max(self._deadline - time.time(), 0)
- def add_cancellation_callback(self, callback):
+ def add_callback(self, callback):
with self._state.condition:
if self._state.callbacks is None:
return False
else:
- self._state.callbacks.append(lambda unused_future: callback())
+ self._state.callbacks.append(lambda: callback())
return True
def initial_metadata(self):
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
index ba60986143..cc3bd7a067 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
@@ -34,6 +34,7 @@ cdef class Call:
def __cinit__(self):
# Create an *empty* call
+ grpc_init()
self.c_call = NULL
self.references = []
@@ -106,6 +107,7 @@ cdef class Call:
def __dealloc__(self):
if self.c_call != NULL:
grpc_call_destroy(self.c_call)
+ grpc_shutdown()
# The object *should* always be valid from Python. Used for debugging.
@property
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
index 5416401431..3df937eb14 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
@@ -34,6 +34,7 @@ cdef class Channel:
def __cinit__(self, bytes target, ChannelArgs arguments=None,
ChannelCredentials channel_credentials=None):
+ grpc_init()
cdef grpc_channel_args *c_arguments = NULL
cdef char *c_target = NULL
self.c_channel = NULL
@@ -103,3 +104,4 @@ cdef class Channel:
def __dealloc__(self):
if self.c_channel != NULL:
grpc_channel_destroy(self.c_channel)
+ grpc_shutdown()
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
index 5955021ceb..a258ba4063 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
@@ -38,6 +38,7 @@ cdef int _INTERRUPT_CHECK_PERIOD_MS = 200
cdef class CompletionQueue:
def __cinit__(self):
+ grpc_init()
with nogil:
self.c_completion_queue = grpc_completion_queue_create(NULL)
self.is_shutting_down = False
@@ -129,3 +130,4 @@ cdef class CompletionQueue:
self.c_completion_queue, c_deadline, NULL)
self._interpret_event(event)
grpc_completion_queue_destroy(self.c_completion_queue)
+ grpc_shutdown()
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
index 035ac49a8b..04872b9c09 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
@@ -33,6 +33,7 @@ cimport cpython
cdef class ChannelCredentials:
def __cinit__(self):
+ grpc_init()
self.c_credentials = NULL
self.c_ssl_pem_key_cert_pair.private_key = NULL
self.c_ssl_pem_key_cert_pair.certificate_chain = NULL
@@ -47,11 +48,13 @@ cdef class ChannelCredentials:
def __dealloc__(self):
if self.c_credentials != NULL:
grpc_channel_credentials_release(self.c_credentials)
+ grpc_shutdown()
cdef class CallCredentials:
def __cinit__(self):
+ grpc_init()
self.c_credentials = NULL
self.references = []
@@ -64,17 +67,20 @@ cdef class CallCredentials:
def __dealloc__(self):
if self.c_credentials != NULL:
grpc_call_credentials_release(self.c_credentials)
+ grpc_shutdown()
cdef class ServerCredentials:
def __cinit__(self):
+ grpc_init()
self.c_credentials = NULL
self.references = []
def __dealloc__(self):
if self.c_credentials != NULL:
grpc_server_credentials_release(self.c_credentials)
+ grpc_shutdown()
cdef class CredentialsMetadataPlugin:
@@ -90,6 +96,7 @@ cdef class CredentialsMetadataPlugin:
successful).
name (bytes): Plugin name.
"""
+ grpc_init()
if not callable(plugin_callback):
raise ValueError('expected callable plugin_callback')
self.plugin_callback = plugin_callback
@@ -105,10 +112,14 @@ cdef class CredentialsMetadataPlugin:
cpython.Py_INCREF(self)
return result
+ def __dealloc__(self):
+ grpc_shutdown()
+
cdef class AuthMetadataContext:
def __cinit__(self):
+ grpc_init()
self.context.service_url = NULL
self.context.method_name = NULL
@@ -120,6 +131,9 @@ cdef class AuthMetadataContext:
def method_name(self):
return self.context.method_name
+ def __dealloc__(self):
+ grpc_shutdown()
+
cdef void plugin_get_metadata(
void *state, grpc_auth_metadata_context context,
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index 7714504d1b..42fced6545 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -30,19 +30,29 @@
cimport libc.time
-cdef extern from "grpc/_cython/loader.h":
+# Typedef types with approximately the same semantics to provide their names to
+# Cython
+ctypedef int int32_t
+ctypedef unsigned uint32_t
+ctypedef long int64_t
- ctypedef int int32_t
- ctypedef unsigned uint32_t
- ctypedef long int64_t
- int pygrpc_load_core(char*)
- int pygrpc_initialize_core()
+cdef extern from "grpc/support/alloc.h":
void *gpr_malloc(size_t size) nogil
void gpr_free(void *ptr) nogil
void *gpr_realloc(void *p, size_t size) nogil
+
+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/grpc.h":
+
ctypedef struct gpr_slice:
# don't worry about writing out the members of gpr_slice; we never access
# them directly.
@@ -86,7 +96,22 @@ cdef extern from "grpc/_cython/loader.h":
gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) nogil
int gpr_time_cmp(gpr_timespec a, gpr_timespec b) nogil
-
+
+ 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) nogil
+ size_t grpc_byte_buffer_length(grpc_byte_buffer *bb) nogil
+ void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer) nogil
+
+ int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
+ grpc_byte_buffer *buffer) nogil
+ int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader,
+ gpr_slice *slice) nogil
+ void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) nogil
+
ctypedef enum grpc_status_code:
GRPC_STATUS_OK
GRPC_STATUS_CANCELLED
@@ -107,37 +132,6 @@ cdef extern from "grpc/_cython/loader.h":
GRPC_STATUS_DATA_LOSS
GRPC_STATUS__DO_NOT_USE
- ctypedef enum grpc_ssl_roots_override_result:
- GRPC_SSL_ROOTS_OVERRIDE_OK
- GRPC_SSL_ROOTS_OVERRIDE_FAILED_PERMANENTLY
- GRPC_SSL_ROOTS_OVERRIDE_FAILED
-
- ctypedef enum grpc_ssl_client_certificate_request_type:
- GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
- GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY
- GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY
- GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY
- GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
-
- struct grpc_byte_buffer_reader:
- # We don't care about the internals
- pass
-
- 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) nogil
- size_t grpc_byte_buffer_length(grpc_byte_buffer *bb) nogil
- void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer) nogil
-
- int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
- grpc_byte_buffer *buffer) nogil
- int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader,
- gpr_slice *slice) nogil
- void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) nogil
-
const char *GRPC_ARG_PRIMARY_USER_AGENT_STRING
const char *GRPC_ARG_ENABLE_CENSUS
const char *GRPC_ARG_MAX_CONCURRENT_STREAMS
@@ -353,6 +347,21 @@ cdef extern from "grpc/_cython/loader.h":
void grpc_server_cancel_all_calls(grpc_server *server) nogil
void grpc_server_destroy(grpc_server *server) nogil
+
+cdef extern from "grpc/grpc_security.h":
+
+ ctypedef enum grpc_ssl_roots_override_result:
+ GRPC_SSL_ROOTS_OVERRIDE_OK
+ GRPC_SSL_ROOTS_OVERRIDE_FAILED_PERMANENTLY
+ GRPC_SSL_ROOTS_OVERRIDE_FAILED
+
+ ctypedef enum grpc_ssl_client_certificate_request_type:
+ GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
+ GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY
+ GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY
+ GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY
+ GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+
ctypedef struct grpc_ssl_pem_key_cert_pair:
const char *private_key
const char *certificate_chain "cert_chain"
@@ -438,6 +447,9 @@ cdef extern from "grpc/_cython/loader.h":
grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
grpc_metadata_credentials_plugin plugin, void *reserved) nogil
+
+cdef extern from "grpc/compression.h":
+
ctypedef enum grpc_compression_algorithm:
GRPC_COMPRESS_NONE
GRPC_COMPRESS_DEFLATE
@@ -472,3 +484,4 @@ cdef extern from "grpc/_cython/loader.h":
int grpc_compression_options_is_algorithm_enabled(
const grpc_compression_options *opts,
grpc_compression_algorithm algorithm) nogil
+
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
index 54b3d00dfc..834a44123d 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
@@ -176,12 +176,14 @@ cdef class Timespec:
cdef class CallDetails:
def __cinit__(self):
+ grpc_init()
with nogil:
grpc_call_details_init(&self.c_details)
def __dealloc__(self):
with nogil:
grpc_call_details_destroy(&self.c_details)
+ grpc_shutdown()
@property
def method(self):
@@ -232,6 +234,7 @@ cdef class Event:
cdef class ByteBuffer:
def __cinit__(self, bytes data):
+ grpc_init()
if data is None:
self.c_byte_buffer = NULL
return
@@ -288,6 +291,7 @@ cdef class ByteBuffer:
def __dealloc__(self):
if self.c_byte_buffer != NULL:
grpc_byte_buffer_destroy(self.c_byte_buffer)
+ grpc_shutdown()
cdef class SslPemKeyCertPair:
@@ -319,6 +323,7 @@ cdef class ChannelArg:
cdef class ChannelArgs:
def __cinit__(self, args):
+ grpc_init()
self.args = list(args)
for arg in self.args:
if not isinstance(arg, ChannelArg):
@@ -333,6 +338,7 @@ cdef class ChannelArgs:
def __dealloc__(self):
with nogil:
gpr_free(self.c_args.arguments)
+ grpc_shutdown()
def __len__(self):
# self.args is never stale; it's only updated from this file
@@ -399,6 +405,7 @@ cdef class _MetadataIterator:
cdef class Metadata:
def __cinit__(self, metadata):
+ grpc_init()
self.metadata = list(metadata)
for metadatum in metadata:
if not isinstance(metadatum, Metadatum):
@@ -420,6 +427,7 @@ cdef class Metadata:
# it'd be nice if that were documented somewhere...)
# TODO(atash): document this in the C core
grpc_metadata_array_destroy(&self.c_metadata_array)
+ grpc_shutdown()
def __len__(self):
return self.c_metadata_array.count
@@ -437,6 +445,7 @@ cdef class Metadata:
cdef class Operation:
def __cinit__(self):
+ grpc_init()
self.references = []
self._received_status_details = NULL
self._received_status_details_capacity = 0
@@ -529,6 +538,7 @@ cdef class Operation:
# This means that we need to clean up after receive_status_on_client.
if self.c_op.type == GRPC_OP_RECV_STATUS_ON_CLIENT:
gpr_free(self._received_status_details)
+ grpc_shutdown()
def operation_send_initial_metadata(Metadata metadata, int flags):
cdef Operation op = Operation()
@@ -645,6 +655,7 @@ cdef class _OperationsIterator:
cdef class Operations:
def __cinit__(self, operations):
+ grpc_init()
self.operations = list(operations) # normalize iterable
self.c_ops = NULL
self.c_nops = 0
@@ -667,6 +678,7 @@ cdef class Operations:
def __dealloc__(self):
with nogil:
gpr_free(self.c_ops)
+ grpc_shutdown()
def __iter__(self):
return _OperationsIterator(self)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
index 4f2d51b03f..ca2b831114 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
@@ -35,6 +35,7 @@ import time
cdef class Server:
def __cinit__(self, ChannelArgs arguments=None):
+ grpc_init()
cdef grpc_channel_args *c_arguments = NULL
self.references = []
self.registered_completion_queues = []
@@ -172,3 +173,4 @@ cdef class Server:
while not self.is_shutdown:
time.sleep(0)
grpc_server_destroy(self.c_server)
+ grpc_shutdown()
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx
index e055d321bc..08089994a9 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pyx
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx
@@ -49,11 +49,14 @@ include "grpc/_cython/_cygrpc/server.pyx.pxi"
#
-def _initialize():
- if not pygrpc_initialize_core():
- raise ImportError('failed to initialize core gRPC library')
+cdef extern from "Python.h":
+
+ int Py_AtExit(void(*func)())
+
+def _initialize():
grpc_set_ssl_roots_override_callback(
<grpc_ssl_roots_override_callback>ssl_roots_override_callback)
+
_initialize()
diff --git a/src/python/grpcio/grpc/_cython/loader.h b/src/python/grpcio/grpc/_cython/loader.h
deleted file mode 100644
index 62fd225204..0000000000
--- a/src/python/grpcio/grpc/_cython/loader.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *
- * Copyright 2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef PYGRPC_LOADER_H_
-#define PYGRPC_LOADER_H_
-
-#include "imports.generated.h"
-
-/* Additional inclusions not covered by "imports.generated.h" */
-#include <grpc/byte_buffer_reader.h>
-
-/* TODO(atash) remove cruft */
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cpluslus */
-
-/* Attempts to load the core if necessary, and return non-zero upon succes. */
-int pygrpc_load_core(char *path);
-
-/* Initializes grpc and registers grpc_shutdown() to be called right before
- * interpreter exit. Returns non-zero upon success.
- */
-int pygrpc_initialize_core(void);
-
-#ifdef __cplusplus
-}
-#endif /* __cpluslus */
-
-#endif /* GRPC_RB_BYTE_BUFFER_H_ */
-
diff --git a/src/python/grpcio/grpc/beta/_client_adaptations.py b/src/python/grpcio/grpc/beta/_client_adaptations.py
index 73415e0be7..e4ee44d7a3 100644
--- a/src/python/grpcio/grpc/beta/_client_adaptations.py
+++ b/src/python/grpcio/grpc/beta/_client_adaptations.py
@@ -67,7 +67,7 @@ def _abortion(rpc_error_call):
error_kind = face.Abortion.Kind.LOCAL_FAILURE if pair is None else pair[0]
return face.Abortion(
error_kind, rpc_error_call.initial_metadata(),
- rpc_error_call.trailing_metadata(), code, rpc_error_code.details())
+ rpc_error_call.trailing_metadata(), code, rpc_error_call.details())
def _abortion_error(rpc_error_call):
@@ -159,9 +159,11 @@ class _Rendezvous(future.Future, face.Call):
return self._call.time_remaining()
def add_abortion_callback(self, abortion_callback):
- registered = self._call.add_callback(
- lambda: abortion_callback(_abortion(self._call)))
- return None if registered else _abortion(self._call)
+ def done_callback():
+ if self.code() is not grpc.StatusCode.OK:
+ abortion_callback(_abortion(self._call))
+ registered = self._call.add_callback(done_callback)
+ return None if registered else done_callback()
def protocol_context(self):
return _InvocationProtocolContext()
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index b37e27c27e..7ae76f52c1 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -81,6 +81,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/channel/channel_stack_builder.c',
'src/core/lib/channel/compress_filter.c',
'src/core/lib/channel/connected_channel.c',
+ 'src/core/lib/channel/handshaker.c',
'src/core/lib/channel/http_client_filter.c',
'src/core/lib/channel/http_server_filter.c',
'src/core/lib/compression/compression.c',
@@ -161,6 +162,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/static_metadata.c',
+ 'src/core/lib/transport/timeout_encoding.c',
'src/core/lib/transport/transport.c',
'src/core/lib/transport/transport_op_string.c',
'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c',
@@ -183,7 +185,6 @@ CORE_SOURCE_FILES = [
'src/core/ext/transport/chttp2/transport/status_conversion.c',
'src/core/ext/transport/chttp2/transport/stream_lists.c',
'src/core/ext/transport/chttp2/transport/stream_map.c',
- 'src/core/ext/transport/chttp2/transport/timeout_encoding.c',
'src/core/ext/transport/chttp2/transport/varint.c',
'src/core/ext/transport/chttp2/transport/writing.c',
'src/core/ext/transport/chttp2/alpn/alpn.c',
@@ -239,6 +240,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c',
'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c',
+ 'src/core/ext/lb_policy/grpclb/grpclb.c',
'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c',
@@ -250,6 +252,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/resolver/sockaddr/sockaddr_resolver.c',
'src/core/ext/load_reporting/load_reporting.c',
'src/core/ext/load_reporting/load_reporting_filter.c',
+ 'src/core/ext/census/base_resources.c',
'src/core/ext/census/context.c',
'src/core/ext/census/gen/census.pb.c',
'src/core/ext/census/grpc_context.c',
@@ -259,6 +262,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/census/mlog.c',
'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c',
+ 'src/core/ext/census/resource.c',
'src/core/ext/census/tracing.c',
'src/core/plugin_registry/grpc_plugin_registry.c',
'src/boringssl/err_data.c',
diff --git a/src/python/grpcio_health_checking/MANIFEST.in b/src/python/grpcio_health_checking/MANIFEST.in
index 7d26647697..7407f646d1 100644
--- a/src/python/grpcio_health_checking/MANIFEST.in
+++ b/src/python/grpcio_health_checking/MANIFEST.in
@@ -1,3 +1,4 @@
+include grpc_version.py
include health_commands.py
-graft grpc_health
+graft grpc
global-exclude *.pyc
diff --git a/src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py b/src/python/grpcio_health_checking/grpc/__init__.py
index 7086519106..fcc7048815 100644
--- a/src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py
+++ b/src/python/grpcio_health_checking/grpc/__init__.py
@@ -27,4 +27,4 @@
# (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__('pkg_resources').declare_namespace(__name__)
diff --git a/src/python/grpcio_health_checking/grpc_health/__init__.py b/src/python/grpcio_health_checking/grpc/health/__init__.py
index 7086519106..7086519106 100644
--- a/src/python/grpcio_health_checking/grpc_health/__init__.py
+++ b/src/python/grpcio_health_checking/grpc/health/__init__.py
diff --git a/src/python/grpcio_health_checking/grpc_health/health/__init__.py b/src/python/grpcio_health_checking/grpc/health/v1/__init__.py
index 7086519106..7086519106 100644
--- a/src/python/grpcio_health_checking/grpc_health/health/__init__.py
+++ b/src/python/grpcio_health_checking/grpc/health/v1/__init__.py
diff --git a/src/python/grpcio_health_checking/grpc_health/health/v1/health.py b/src/python/grpcio_health_checking/grpc/health/v1/health.py
index 8da60c70cb..8108ac1096 100644
--- a/src/python/grpcio_health_checking/grpc_health/health/v1/health.py
+++ b/src/python/grpcio_health_checking/grpc/health/v1/health.py
@@ -31,10 +31,12 @@
import threading
-from grpc_health.health.v1 import health_pb2
+import grpc
+from grpc.health.v1 import health_pb2
-class HealthServicer(health_pb2.BetaHealthServicer):
+
+class HealthServicer(health_pb2.HealthServicer):
"""Servicer handling RPCs for service statuses."""
def __init__(self):
@@ -43,14 +45,12 @@ class HealthServicer(health_pb2.BetaHealthServicer):
def Check(self, request, context):
with self._server_status_lock:
- if request.service not in self._server_status:
- # TODO(atash): once the Python API has a way of setting the server
- # status, bring us into conformance with the health check spec by
- # returning the NOT_FOUND status here.
- raise NotImplementedError()
+ status = self._server_status.get(request.service)
+ if status is None:
+ context.set_code(grpc.StatusCode.NOT_FOUND)
+ return health_pb2.HealthCheckResponse()
else:
- return health_pb2.HealthCheckResponse(
- status=self._server_status[request.service])
+ return health_pb2.HealthCheckResponse(status=status)
def set(self, service, status):
"""Sets the status of a service.
@@ -63,4 +63,3 @@ class HealthServicer(health_pb2.BetaHealthServicer):
"""
with self._server_status_lock:
self._server_status[service] = status
-
diff --git a/src/ruby/tools/bin/grpc_tools_ruby_protoc.rb b/src/python/grpcio_health_checking/grpc_version.py
index 3a2a5b8dc9..be0d0ced3c 100755..100644
--- a/src/ruby/tools/bin/grpc_tools_ruby_protoc.rb
+++ b/src/python/grpcio_health_checking/grpc_version.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env ruby
# Copyright 2016, Google Inc.
# All rights reserved.
#
@@ -28,14 +27,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-require 'rbconfig'
+# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
-require_relative '../os_check'
-
-protoc_name = 'protoc' + RbConfig::CONFIG['EXEEXT']
-
-protoc_path = File.join(File.dirname(__FILE__),
- RbConfig::CONFIG['host_cpu'] + '-' + OS.os_name,
- protoc_name)
-
-exec([ protoc_path, protoc_path ], *ARGV)
+VERSION='1.1.0.dev0'
diff --git a/src/python/grpcio_health_checking/health_commands.py b/src/python/grpcio_health_checking/health_commands.py
index a7a59f6974..66df25da63 100644
--- a/src/python/grpcio_health_checking/health_commands.py
+++ b/src/python/grpcio_health_checking/health_commands.py
@@ -29,16 +29,10 @@
"""Provides distutils command classes for the GRPC Python setup process."""
-import distutils
-import glob
import os
-import os.path
import shutil
-import subprocess
-import sys
import setuptools
-from setuptools.command import build_py
ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
HEALTH_PROTO = os.path.join(ROOT_DIR, '../../proto/grpc/health/v1/health.proto')
@@ -60,12 +54,25 @@ class CopyProtoModules(setuptools.Command):
if os.path.isfile(HEALTH_PROTO):
shutil.copyfile(
HEALTH_PROTO,
- os.path.join(ROOT_DIR, 'grpc_health/health/v1/health.proto'))
+ os.path.join(ROOT_DIR, 'grpc/health/v1/health.proto'))
-class BuildPy(build_py.build_py):
- """Custom project build command."""
+class BuildPackageProtos(setuptools.Command):
+ """Command to generate project *_pb2.py modules from proto files."""
+
+ description = 'build grpc protobuf modules'
+ user_options = []
+
+ def initialize_options(self):
+ pass
+
+ def finalize_options(self):
+ pass
def run(self):
- self.run_command('build_proto_modules')
- build_py.build_py.run(self)
+ # due to limitations of the proto generator, we require that only *one*
+ # directory is provided as an 'include' directory. We assume it's the '' key
+ # to `self.distribution.package_dir` (and get a key error if it's not
+ # there).
+ from grpc.tools import command
+ command.build_package_protos(self.distribution.package_dir[''])
diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py
index 70b4575bf5..6074175a44 100644
--- a/src/python/grpcio_health_checking/setup.py
+++ b/src/python/grpcio_health_checking/setup.py
@@ -30,49 +30,43 @@
"""Setup module for the GRPC Python package's optional health checking."""
import os
-import os.path
import sys
-from distutils import core as _core
import setuptools
-import grpc.tools.command
-
# Ensure we're in the proper directory whether or not we're being used by pip.
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# Break import-style to ensure we can actually find our commands module.
import health_commands
-
-PACKAGES = (
- setuptools.find_packages('.')
-)
+import grpc_version
PACKAGE_DIRECTORIES = {
'': '.',
}
SETUP_REQUIRES = (
- 'grpcio-tools>=0.14.0',
+ 'grpcio-tools>=0.15.0',
)
INSTALL_REQUIRES = (
- 'grpcio>=0.13.1',
+ 'protobuf>=3.0.0',
+ 'grpcio>=0.15.0',
)
COMMAND_CLASS = {
# Run preprocess from the repository *before* doing any packaging!
'preprocess': health_commands.CopyProtoModules,
-
- 'build_proto_modules': grpc.tools.command.BuildProtoModules,
- 'build_py': health_commands.BuildPy,
+ 'build_package_protos': health_commands.BuildPackageProtos,
}
setuptools.setup(
name='grpcio-health-checking',
- version='0.14.0',
- packages=list(PACKAGES),
+ version=grpc_version.VERSION,
+ license='3-clause BSD',
package_dir=PACKAGE_DIRECTORIES,
+ packages=setuptools.find_packages('.'),
+ namespace_packages=['grpc'],
install_requires=INSTALL_REQUIRES,
setup_requires=SETUP_REQUIRES,
cmdclass=COMMAND_CLASS
diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py
index 171829b62f..5ee551cfe1 100644
--- a/src/python/grpcio_tests/commands.py
+++ b/src/python/grpcio_tests/commands.py
@@ -138,7 +138,7 @@ class BuildPy(build_py.build_py):
def run(self):
try:
- self.run_command('build_proto_modules')
+ self.run_command('build_package_protos')
except CommandError as error:
sys.stderr.write('warning: %s\n' % error.message)
build_py.build_py.run(self)
diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py
index 7eef420bdb..5c60eaca3a 100644
--- a/src/python/grpcio_tests/setup.py
+++ b/src/python/grpcio_tests/setup.py
@@ -63,7 +63,7 @@ INSTALL_REQUIRES = (
'grpcio>=0.14.0',
'grpcio-health-checking>=0.14.0',
'oauth2client>=1.4.7',
- 'protobuf>=3.0.0a3',
+ 'protobuf>=3.0.0',
'six>=1.10',
)
@@ -75,7 +75,7 @@ COMMAND_CLASS = {
# Run `preprocess` *before* doing any packaging!
'preprocess': commands.GatherProto,
- 'build_proto_modules': grpc.tools.command.BuildProtoModules,
+ 'build_package_protos': grpc.tools.command.BuildPackageProtos,
'build_py': commands.BuildPy,
'run_interop': commands.RunInterop,
'test_lite': commands.TestLite
diff --git a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py
index 1b63388663..80300d13df 100644
--- a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py
+++ b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py
@@ -27,48 +27,68 @@
# (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 grpc_health.health.v1.health."""
+"""Tests of grpc.health.v1.health."""
import unittest
-from grpc_health.health.v1 import health
-from grpc_health.health.v1 import health_pb2
+import grpc
+from grpc.framework.foundation import logging_pool
+from grpc.health.v1 import health
+from grpc.health.v1 import health_pb2
+
+from tests.unit.framework.common import test_constants
class HealthServicerTest(unittest.TestCase):
def setUp(self):
- self.servicer = health.HealthServicer()
- self.servicer.set('', health_pb2.HealthCheckResponse.SERVING)
- self.servicer.set('grpc.test.TestServiceServing',
- health_pb2.HealthCheckResponse.SERVING)
- self.servicer.set('grpc.test.TestServiceUnknown',
- health_pb2.HealthCheckResponse.UNKNOWN)
- self.servicer.set('grpc.test.TestServiceNotServing',
- health_pb2.HealthCheckResponse.NOT_SERVING)
+ servicer = health.HealthServicer()
+ servicer.set('', health_pb2.HealthCheckResponse.SERVING)
+ servicer.set('grpc.test.TestServiceServing',
+ health_pb2.HealthCheckResponse.SERVING)
+ servicer.set('grpc.test.TestServiceUnknown',
+ health_pb2.HealthCheckResponse.UNKNOWN)
+ servicer.set('grpc.test.TestServiceNotServing',
+ health_pb2.HealthCheckResponse.NOT_SERVING)
+ server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY)
+ self._server = grpc.server(server_pool)
+ port = self._server.add_insecure_port('[::]:0')
+ health_pb2.add_HealthServicer_to_server(servicer, self._server)
+ self._server.start()
+
+ channel = grpc.insecure_channel('localhost:%d' % port)
+ self._stub = health_pb2.HealthStub(channel)
def test_empty_service(self):
request = health_pb2.HealthCheckRequest()
- resp = self.servicer.Check(request, None)
- self.assertEqual(resp.status, health_pb2.HealthCheckResponse.SERVING)
+ resp = self._stub.Check(request)
+ self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status)
def test_serving_service(self):
request = health_pb2.HealthCheckRequest(
service='grpc.test.TestServiceServing')
- resp = self.servicer.Check(request, None)
- self.assertEqual(resp.status, health_pb2.HealthCheckResponse.SERVING)
+ resp = self._stub.Check(request)
+ self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status)
def test_unknown_serivce(self):
request = health_pb2.HealthCheckRequest(
service='grpc.test.TestServiceUnknown')
- resp = self.servicer.Check(request, None)
- self.assertEqual(resp.status, health_pb2.HealthCheckResponse.UNKNOWN)
+ resp = self._stub.Check(request)
+ self.assertEqual(health_pb2.HealthCheckResponse.UNKNOWN, resp.status)
def test_not_serving_service(self):
request = health_pb2.HealthCheckRequest(
service='grpc.test.TestServiceNotServing')
- resp = self.servicer.Check(request, None)
- self.assertEqual(resp.status, health_pb2.HealthCheckResponse.NOT_SERVING)
+ resp = self._stub.Check(request)
+ self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING, resp.status)
+
+ def test_not_found_service(self):
+ request = health_pb2.HealthCheckRequest(
+ service='not-found')
+ with self.assertRaises(grpc.RpcError) as context:
+ resp = self._stub.Check(request)
+
+ self.assertEqual(grpc.StatusCode.NOT_FOUND, context.exception.code())
if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py b/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py
index c753d6faf0..936c895bd2 100644
--- a/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py
+++ b/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py
@@ -29,9 +29,10 @@
"""Insecure client-server interoperability as a unit test."""
+from concurrent import futures
import unittest
-from grpc.beta import implementations
+import grpc
from src.proto.grpc.testing import test_pb2
from tests.interop import _interop_test_case
@@ -44,14 +45,13 @@ class InsecureInteropTest(
unittest.TestCase):
def setUp(self):
- self.server = test_pb2.beta_create_TestService_server(methods.TestService())
+ self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ test_pb2.add_TestServiceServicer_to_server(
+ methods.TestService(), self.server)
port = self.server.add_insecure_port('[::]:0')
self.server.start()
- self.stub = test_pb2.beta_create_TestService_stub(
- implementations.insecure_channel('localhost', port))
-
- def tearDown(self):
- self.server.stop(0)
+ self.stub = test_pb2.TestServiceStub(
+ grpc.insecure_channel('localhost:{}'.format(port)))
if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/interop/_secure_interop_test.py b/src/python/grpcio_tests/tests/interop/_secure_interop_test.py
index cb09f54a34..eaca553e1b 100644
--- a/src/python/grpcio_tests/tests/interop/_secure_interop_test.py
+++ b/src/python/grpcio_tests/tests/interop/_secure_interop_test.py
@@ -29,17 +29,16 @@
"""Secure client-server interoperability as a unit test."""
+from concurrent import futures
import unittest
-from grpc.beta import implementations
+import grpc
from src.proto.grpc.testing import test_pb2
from tests.interop import _interop_test_case
from tests.interop import methods
from tests.interop import resources
-from tests.unit.beta import test_utilities
-
_SERVER_HOST_OVERRIDE = 'foo.test.google.fr'
@@ -48,19 +47,18 @@ class SecureInteropTest(
unittest.TestCase):
def setUp(self):
- self.server = test_pb2.beta_create_TestService_server(methods.TestService())
+ self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ test_pb2.add_TestServiceServicer_to_server(
+ methods.TestService(), self.server)
port = self.server.add_secure_port(
- '[::]:0', implementations.ssl_server_credentials(
+ '[::]:0', grpc.ssl_server_credentials(
[(resources.private_key(), resources.certificate_chain())]))
self.server.start()
- self.stub = test_pb2.beta_create_TestService_stub(
- test_utilities.not_really_secure_channel(
- 'localhost', port, implementations.ssl_channel_credentials(
- resources.test_root_certificates()),
- _SERVER_HOST_OVERRIDE))
-
- def tearDown(self):
- self.server.stop(0)
+ self.stub = test_pb2.TestServiceStub(
+ grpc.secure_channel(
+ 'localhost:{}'.format(port),
+ grpc.ssl_channel_credentials(resources.test_root_certificates()),
+ (('grpc.ssl_target_name_override', _SERVER_HOST_OVERRIDE,),)))
if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/interop/client.py b/src/python/grpcio_tests/tests/interop/client.py
index 8aa1ce30c1..9d61d18975 100644
--- a/src/python/grpcio_tests/tests/interop/client.py
+++ b/src/python/grpcio_tests/tests/interop/client.py
@@ -32,14 +32,12 @@
import argparse
from oauth2client import client as oauth2client_client
+import grpc
from grpc.beta import implementations
from src.proto.grpc.testing import test_pb2
from tests.interop import methods
from tests.interop import resources
-from tests.unit.beta import test_utilities
-
-_ONE_DAY_IN_SECONDS = 60 * 60 * 24
def _args():
@@ -66,41 +64,49 @@ def _args():
return parser.parse_args()
+def _application_default_credentials():
+ return oauth2client_client.GoogleCredentials.get_application_default()
+
+
def _stub(args):
+ target = '{}:{}'.format(args.server_host, args.server_port)
if args.test_case == 'oauth2_auth_token':
- creds = oauth2client_client.GoogleCredentials.get_application_default()
- scoped_creds = creds.create_scoped([args.oauth_scope])
- access_token = scoped_creds.get_access_token().access_token
- call_creds = implementations.access_token_call_credentials(access_token)
+ google_credentials = _application_default_credentials()
+ scoped_credentials = google_credentials.create_scoped([args.oauth_scope])
+ access_token = scoped_credentials.get_access_token().access_token
+ call_credentials = grpc.access_token_call_credentials(access_token)
elif args.test_case == 'compute_engine_creds':
- creds = oauth2client_client.GoogleCredentials.get_application_default()
- scoped_creds = creds.create_scoped([args.oauth_scope])
- call_creds = implementations.google_call_credentials(scoped_creds)
+ google_credentials = _application_default_credentials()
+ scoped_credentials = google_credentials.create_scoped([args.oauth_scope])
+ # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last
+ # remaining use of the Beta API.
+ call_credentials = implementations.google_call_credentials(
+ scoped_credentials)
elif args.test_case == 'jwt_token_creds':
- creds = oauth2client_client.GoogleCredentials.get_application_default()
- call_creds = implementations.google_call_credentials(creds)
+ google_credentials = _application_default_credentials()
+ # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last
+ # remaining use of the Beta API.
+ call_credentials = implementations.google_call_credentials(
+ google_credentials)
else:
- call_creds = None
+ call_credentials = None
if args.use_tls:
if args.use_test_ca:
root_certificates = resources.test_root_certificates()
else:
root_certificates = None # will load default roots.
- channel_creds = implementations.ssl_channel_credentials(root_certificates)
- if call_creds is not None:
- channel_creds = implementations.composite_channel_credentials(
- channel_creds, call_creds)
+ channel_credentials = grpc.ssl_channel_credentials(root_certificates)
+ if call_credentials is not None:
+ channel_credentials = grpc.composite_channel_credentials(
+ channel_credentials, call_credentials)
- channel = test_utilities.not_really_secure_channel(
- args.server_host, args.server_port, channel_creds,
- args.server_host_override)
- stub = test_pb2.beta_create_TestService_stub(channel)
+ channel = grpc.secure_channel(
+ target, channel_credentials,
+ (('grpc.ssl_target_name_override', args.server_host_override,),))
else:
- channel = implementations.insecure_channel(
- args.server_host, args.server_port)
- stub = test_pb2.beta_create_TestService_stub(channel)
- return stub
+ channel = grpc.insecure_channel(target)
+ return test_pb2.TestServiceStub(channel)
def _test_case_from_arg(test_case_arg):
diff --git a/src/python/grpcio_tests/tests/interop/methods.py b/src/python/grpcio_tests/tests/interop/methods.py
index 97e6c9e27e..7edd75c56c 100644
--- a/src/python/grpcio_tests/tests/interop/methods.py
+++ b/src/python/grpcio_tests/tests/interop/methods.py
@@ -29,8 +29,6 @@
"""Implementations of interoperability test methods."""
-from __future__ import print_function
-
import enum
import json
import os
@@ -41,26 +39,21 @@ from oauth2client import client as oauth2client_client
import grpc
from grpc.beta import implementations
-from grpc.beta import interfaces
-from grpc.framework.common import cardinality
-from grpc.framework.interfaces.face import face
from src.proto.grpc.testing import empty_pb2
from src.proto.grpc.testing import messages_pb2
from src.proto.grpc.testing import test_pb2
-_TIMEOUT = 7
-
-class TestService(test_pb2.BetaTestServiceServicer):
+class TestService(test_pb2.TestServiceServicer):
def EmptyCall(self, request, context):
return empty_pb2.Empty()
def UnaryCall(self, request, context):
if request.HasField('response_status'):
- context.code(request.response_status.code)
- context.details(request.response_status.message)
+ context.set_code(request.response_status.code)
+ context.set_details(request.response_status.message)
return messages_pb2.SimpleResponse(
payload=messages_pb2.Payload(
type=messages_pb2.COMPRESSABLE,
@@ -68,8 +61,8 @@ class TestService(test_pb2.BetaTestServiceServicer):
def StreamingOutputCall(self, request, context):
if request.HasField('response_status'):
- context.code(request.response_status.code)
- context.details(request.response_status.message)
+ context.set_code(request.response_status.code)
+ context.set_details(request.response_status.message)
for response_parameters in request.response_parameters:
yield messages_pb2.StreamingOutputCallResponse(
payload=messages_pb2.Payload(
@@ -79,7 +72,7 @@ class TestService(test_pb2.BetaTestServiceServicer):
def StreamingInputCall(self, request_iterator, context):
aggregate_size = 0
for request in request_iterator:
- if request.payload and request.payload.body:
+ if request.payload is not None and request.payload.body:
aggregate_size += len(request.payload.body)
return messages_pb2.StreamingInputCallResponse(
aggregated_payload_size=aggregate_size)
@@ -87,8 +80,8 @@ class TestService(test_pb2.BetaTestServiceServicer):
def FullDuplexCall(self, request_iterator, context):
for request in request_iterator:
if request.HasField('response_status'):
- context.code(request.response_status.code)
- context.details(request.response_status.message)
+ context.set_code(request.response_status.code)
+ context.set_details(request.response_status.message)
for response_parameters in request.response_parameters:
yield messages_pb2.StreamingOutputCallResponse(
payload=messages_pb2.Payload(
@@ -101,83 +94,80 @@ class TestService(test_pb2.BetaTestServiceServicer):
return self.FullDuplexCall(request_iterator, context)
-def _large_unary_common_behavior(stub, fill_username, fill_oauth_scope,
- protocol_options=None):
- with stub:
- request = messages_pb2.SimpleRequest(
- response_type=messages_pb2.COMPRESSABLE, response_size=314159,
- payload=messages_pb2.Payload(body=b'\x00' * 271828),
- fill_username=fill_username, fill_oauth_scope=fill_oauth_scope)
- response_future = stub.UnaryCall.future(request, _TIMEOUT,
- protocol_options=protocol_options)
- response = response_future.result()
- if response.payload.type is not messages_pb2.COMPRESSABLE:
- raise ValueError(
- 'response payload type is "%s"!' % type(response.payload.type))
- if len(response.payload.body) != 314159:
- raise ValueError(
- 'response body of incorrect size %d!' % len(response.payload.body))
+def _large_unary_common_behavior(
+ stub, fill_username, fill_oauth_scope, call_credentials):
+ request = messages_pb2.SimpleRequest(
+ response_type=messages_pb2.COMPRESSABLE, response_size=314159,
+ payload=messages_pb2.Payload(body=b'\x00' * 271828),
+ fill_username=fill_username, fill_oauth_scope=fill_oauth_scope)
+ response_future = stub.UnaryCall.future(
+ request, credentials=call_credentials)
+ response = response_future.result()
+ if response.payload.type is not messages_pb2.COMPRESSABLE:
+ raise ValueError(
+ 'response payload type is "%s"!' % type(response.payload.type))
+ elif len(response.payload.body) != 314159:
+ raise ValueError(
+ 'response body of incorrect size %d!' % len(response.payload.body))
+ else:
return response
def _empty_unary(stub):
- with stub:
- response = stub.EmptyCall(empty_pb2.Empty(), _TIMEOUT)
- if not isinstance(response, empty_pb2.Empty):
- raise TypeError(
- 'response is of type "%s", not empty_pb2.Empty!', type(response))
+ response = stub.EmptyCall(empty_pb2.Empty())
+ if not isinstance(response, empty_pb2.Empty):
+ raise TypeError(
+ 'response is of type "%s", not empty_pb2.Empty!', type(response))
def _large_unary(stub):
- _large_unary_common_behavior(stub, False, False)
+ _large_unary_common_behavior(stub, False, False, None)
def _client_streaming(stub):
- with stub:
- payload_body_sizes = (27182, 8, 1828, 45904)
- payloads = (
- messages_pb2.Payload(body=b'\x00' * size)
- for size in payload_body_sizes)
- requests = (
- messages_pb2.StreamingInputCallRequest(payload=payload)
- for payload in payloads)
- response = stub.StreamingInputCall(requests, _TIMEOUT)
- if response.aggregated_payload_size != 74922:
- raise ValueError(
- 'incorrect size %d!' % response.aggregated_payload_size)
+ payload_body_sizes = (27182, 8, 1828, 45904,)
+ payloads = (
+ messages_pb2.Payload(body=b'\x00' * size)
+ for size in payload_body_sizes)
+ requests = (
+ messages_pb2.StreamingInputCallRequest(payload=payload)
+ for payload in payloads)
+ response = stub.StreamingInputCall(requests)
+ if response.aggregated_payload_size != 74922:
+ raise ValueError(
+ 'incorrect size %d!' % response.aggregated_payload_size)
def _server_streaming(stub):
- sizes = (31415, 9, 2653, 58979)
-
- with stub:
- request = messages_pb2.StreamingOutputCallRequest(
- response_type=messages_pb2.COMPRESSABLE,
- response_parameters=(
- messages_pb2.ResponseParameters(size=sizes[0]),
- messages_pb2.ResponseParameters(size=sizes[1]),
- messages_pb2.ResponseParameters(size=sizes[2]),
- messages_pb2.ResponseParameters(size=sizes[3]),
- ))
- response_iterator = stub.StreamingOutputCall(request, _TIMEOUT)
- for index, response in enumerate(response_iterator):
- if response.payload.type != messages_pb2.COMPRESSABLE:
- raise ValueError(
- 'response body of invalid type %s!' % response.payload.type)
- if len(response.payload.body) != sizes[index]:
- raise ValueError(
- 'response body of invalid size %d!' % len(response.payload.body))
+ sizes = (31415, 9, 2653, 58979,)
+
+ request = messages_pb2.StreamingOutputCallRequest(
+ response_type=messages_pb2.COMPRESSABLE,
+ response_parameters=(
+ messages_pb2.ResponseParameters(size=sizes[0]),
+ messages_pb2.ResponseParameters(size=sizes[1]),
+ messages_pb2.ResponseParameters(size=sizes[2]),
+ messages_pb2.ResponseParameters(size=sizes[3]),
+ )
+ )
+ response_iterator = stub.StreamingOutputCall(request)
+ for index, response in enumerate(response_iterator):
+ if response.payload.type != messages_pb2.COMPRESSABLE:
+ raise ValueError(
+ 'response body of invalid type %s!' % response.payload.type)
+ elif len(response.payload.body) != sizes[index]:
+ raise ValueError(
+ 'response body of invalid size %d!' % len(response.payload.body))
def _cancel_after_begin(stub):
- with stub:
- sizes = (27182, 8, 1828, 45904)
- payloads = [messages_pb2.Payload(body=b'\x00' * size) for size in sizes]
- requests = [messages_pb2.StreamingInputCallRequest(payload=payload)
- for payload in payloads]
- responses = stub.StreamingInputCall.future(requests, _TIMEOUT)
- responses.cancel()
- if not responses.cancelled():
- raise ValueError('expected call to be cancelled')
+ sizes = (27182, 8, 1828, 45904,)
+ payloads = (messages_pb2.Payload(body=b'\x00' * size) for size in sizes)
+ requests = (messages_pb2.StreamingInputCallRequest(payload=payload)
+ for payload in payloads)
+ response_future = stub.StreamingInputCall.future(requests)
+ response_future.cancel()
+ if not response_future.cancelled():
+ raise ValueError('expected call to be cancelled')
class _Pipe(object):
@@ -220,18 +210,17 @@ class _Pipe(object):
def _ping_pong(stub):
- request_response_sizes = (31415, 9, 2653, 58979)
- request_payload_sizes = (27182, 8, 1828, 45904)
+ request_response_sizes = (31415, 9, 2653, 58979,)
+ request_payload_sizes = (27182, 8, 1828, 45904,)
- with stub, _Pipe() as pipe:
- response_iterator = stub.FullDuplexCall(pipe, _TIMEOUT)
- print('Starting ping-pong with response iterator %s' % response_iterator)
+ with _Pipe() as pipe:
+ response_iterator = stub.FullDuplexCall(pipe)
for response_size, payload_size in zip(
request_response_sizes, request_payload_sizes):
request = messages_pb2.StreamingOutputCallRequest(
response_type=messages_pb2.COMPRESSABLE,
- response_parameters=(messages_pb2.ResponseParameters(
- size=response_size),),
+ response_parameters=(
+ messages_pb2.ResponseParameters(size=response_size),),
payload=messages_pb2.Payload(body=b'\x00' * payload_size))
pipe.add(request)
response = next(response_iterator)
@@ -244,17 +233,17 @@ def _ping_pong(stub):
def _cancel_after_first_response(stub):
- request_response_sizes = (31415, 9, 2653, 58979)
- request_payload_sizes = (27182, 8, 1828, 45904)
- with stub, _Pipe() as pipe:
- response_iterator = stub.FullDuplexCall(pipe, _TIMEOUT)
+ request_response_sizes = (31415, 9, 2653, 58979,)
+ request_payload_sizes = (27182, 8, 1828, 45904,)
+ with _Pipe() as pipe:
+ response_iterator = stub.FullDuplexCall(pipe)
response_size = request_response_sizes[0]
payload_size = request_payload_sizes[0]
request = messages_pb2.StreamingOutputCallRequest(
response_type=messages_pb2.COMPRESSABLE,
- response_parameters=(messages_pb2.ResponseParameters(
- size=response_size),),
+ response_parameters=(
+ messages_pb2.ResponseParameters(size=response_size),),
payload=messages_pb2.Payload(body=b'\x00' * payload_size))
pipe.add(request)
response = next(response_iterator)
@@ -264,16 +253,17 @@ def _cancel_after_first_response(stub):
try:
next(response_iterator)
- except Exception:
- pass
+ except grpc.RpcError as rpc_error:
+ if rpc_error.code() is not grpc.StatusCode.CANCELLED:
+ raise
else:
raise ValueError('expected call to be cancelled')
def _timeout_on_sleeping_server(stub):
request_payload_size = 27182
- with stub, _Pipe() as pipe:
- response_iterator = stub.FullDuplexCall(pipe, 0.001)
+ with _Pipe() as pipe:
+ response_iterator = stub.FullDuplexCall(pipe, timeout=0.001)
request = messages_pb2.StreamingOutputCallRequest(
response_type=messages_pb2.COMPRESSABLE,
@@ -282,15 +272,16 @@ def _timeout_on_sleeping_server(stub):
time.sleep(0.1)
try:
next(response_iterator)
- except face.ExpirationError:
- pass
+ except grpc.RpcError as rpc_error:
+ if rpc_error.code() is not grpc.StatusCode.DEADLINE_EXCEEDED:
+ raise
else:
raise ValueError('expected call to exceed deadline')
def _empty_stream(stub):
- with stub, _Pipe() as pipe:
- response_iterator = stub.FullDuplexCall(pipe, _TIMEOUT)
+ with _Pipe() as pipe:
+ response_iterator = stub.FullDuplexCall(pipe)
pipe.close()
try:
next(response_iterator)
@@ -300,65 +291,64 @@ def _empty_stream(stub):
def _status_code_and_message(stub):
- with stub:
- message = 'test status message'
- code = 2
- status = grpc.StatusCode.UNKNOWN # code = 2
- request = messages_pb2.SimpleRequest(
- response_type=messages_pb2.COMPRESSABLE,
- response_size=1,
- payload=messages_pb2.Payload(body=b'\x00'),
- response_status=messages_pb2.EchoStatus(code=code, message=message)
- )
- response_future = stub.UnaryCall.future(request, _TIMEOUT)
- if response_future.code() != status:
- raise ValueError(
- 'expected code %s, got %s' % (status, response_future.code()))
- if response_future.details() != message:
- raise ValueError(
- 'expected message %s, got %s' % (message, response_future.details()))
-
- request = messages_pb2.StreamingOutputCallRequest(
- response_type=messages_pb2.COMPRESSABLE,
- response_parameters=(
- messages_pb2.ResponseParameters(size=1),),
- response_status=messages_pb2.EchoStatus(code=code, message=message))
- response_iterator = stub.StreamingOutputCall(request, _TIMEOUT)
- if response_future.code() != status:
- raise ValueError(
- 'expected code %s, got %s' % (status, response_iterator.code()))
- if response_future.details() != message:
- raise ValueError(
- 'expected message %s, got %s' % (message, response_iterator.details()))
+ message = 'test status message'
+ code = 2
+ status = grpc.StatusCode.UNKNOWN # code = 2
+ request = messages_pb2.SimpleRequest(
+ response_type=messages_pb2.COMPRESSABLE,
+ response_size=1,
+ payload=messages_pb2.Payload(body=b'\x00'),
+ response_status=messages_pb2.EchoStatus(code=code, message=message)
+ )
+ response_future = stub.UnaryCall.future(request)
+ if response_future.code() != status:
+ raise ValueError(
+ 'expected code %s, got %s' % (status, response_future.code()))
+ elif response_future.details() != message:
+ raise ValueError(
+ 'expected message %s, got %s' % (message, response_future.details()))
+
+ request = messages_pb2.StreamingOutputCallRequest(
+ response_type=messages_pb2.COMPRESSABLE,
+ response_parameters=(
+ messages_pb2.ResponseParameters(size=1),),
+ response_status=messages_pb2.EchoStatus(code=code, message=message))
+ response_iterator = stub.StreamingOutputCall(request)
+ if response_future.code() != status:
+ raise ValueError(
+ 'expected code %s, got %s' % (status, response_iterator.code()))
+ elif response_future.details() != message:
+ raise ValueError(
+ 'expected message %s, got %s' % (message, response_iterator.details()))
def _compute_engine_creds(stub, args):
- response = _large_unary_common_behavior(stub, True, True)
+ response = _large_unary_common_behavior(stub, True, True, None)
if args.default_service_account != response.username:
raise ValueError(
- 'expected username %s, got %s' % (args.default_service_account,
- response.username))
+ 'expected username %s, got %s' % (
+ args.default_service_account, response.username))
def _oauth2_auth_token(stub, args):
json_key_filename = os.environ[
oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS]
wanted_email = json.load(open(json_key_filename, 'rb'))['client_email']
- response = _large_unary_common_behavior(stub, True, True)
+ response = _large_unary_common_behavior(stub, True, True, None)
if wanted_email != response.username:
raise ValueError(
'expected username %s, got %s' % (wanted_email, response.username))
if args.oauth_scope.find(response.oauth_scope) == -1:
raise ValueError(
- 'expected to find oauth scope "%s" in received "%s"' %
- (response.oauth_scope, args.oauth_scope))
+ 'expected to find oauth scope "{}" in received "{}"'.format(
+ response.oauth_scope, args.oauth_scope))
def _jwt_token_creds(stub, args):
json_key_filename = os.environ[
oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS]
wanted_email = json.load(open(json_key_filename, 'rb'))['client_email']
- response = _large_unary_common_behavior(stub, True, False)
+ response = _large_unary_common_behavior(stub, True, False, None)
if wanted_email != response.username:
raise ValueError(
'expected username %s, got %s' % (wanted_email, response.username))
@@ -370,11 +360,11 @@ def _per_rpc_creds(stub, args):
wanted_email = json.load(open(json_key_filename, 'rb'))['client_email']
credentials = oauth2client_client.GoogleCredentials.get_application_default()
scoped_credentials = credentials.create_scoped([args.oauth_scope])
- call_creds = implementations.google_call_credentials(scoped_credentials)
- options = interfaces.grpc_call_options(disable_compression=False,
- credentials=call_creds)
- response = _large_unary_common_behavior(stub, True, False,
- protocol_options=options)
+ # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last
+ # remaining use of the Beta API.
+ call_credentials = implementations.google_call_credentials(
+ scoped_credentials)
+ response = _large_unary_common_behavior(stub, True, False, call_credentials)
if wanted_email != response.username:
raise ValueError(
'expected username %s, got %s' % (wanted_email, response.username))
diff --git a/src/python/grpcio_tests/tests/interop/server.py b/src/python/grpcio_tests/tests/interop/server.py
index ab2c3c708f..1ae83bc57d 100644
--- a/src/python/grpcio_tests/tests/interop/server.py
+++ b/src/python/grpcio_tests/tests/interop/server.py
@@ -30,10 +30,11 @@
"""The Python implementation of the GRPC interoperability test server."""
import argparse
+from concurrent import futures
import logging
import time
-from grpc.beta import implementations
+import grpc
from src.proto.grpc.testing import test_pb2
from tests.interop import methods
@@ -51,12 +52,13 @@ def serve():
default=False, type=resources.parse_bool)
args = parser.parse_args()
- server = test_pb2.beta_create_TestService_server(methods.TestService())
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ test_pb2.add_TestServiceServicer_to_server(methods.TestService(), server)
if args.use_tls:
private_key = resources.private_key()
certificate_chain = resources.certificate_chain()
- credentials = implementations.ssl_server_credentials(
- [(private_key, certificate_chain)])
+ credentials = grpc.ssl_server_credentials(
+ ((private_key, certificate_chain),))
server.add_secure_port('[::]:{}'.format(args.port), credentials)
else:
server.add_insecure_port('[::]:{}'.format(args.port))
@@ -68,7 +70,7 @@ def serve():
time.sleep(_ONE_DAY_IN_SECONDS)
except BaseException as e:
logging.info('Caught exception "%s"; stopping server...', e)
- server.stop(0)
+ server.stop(None)
logging.info('Server stopped; exiting.')
if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/stress/client.py b/src/python/grpcio_tests/tests/stress/client.py
index 0de2532cd8..975f33b4c1 100644
--- a/src/python/grpcio_tests/tests/stress/client.py
+++ b/src/python/grpcio_tests/tests/stress/client.py
@@ -30,9 +30,10 @@
"""Entry point for running stress tests."""
import argparse
+from concurrent import futures
import threading
-from grpc.beta import implementations
+import grpc
from six.moves import queue
from src.proto.grpc.testing import metrics_pb2
from src.proto.grpc.testing import test_pb2
@@ -92,24 +93,24 @@ def _parse_weighted_test_cases(test_case_args):
def run_test(args):
test_cases = _parse_weighted_test_cases(args.test_cases)
- test_servers = args.server_addresses.split(',')
+ test_server_targets = args.server_addresses.split(',')
# Propagate any client exceptions with a queue
exception_queue = queue.Queue()
stop_event = threading.Event()
hist = histogram.Histogram(1, 1)
runners = []
- server = metrics_pb2.beta_create_MetricsService_server(
- metrics_server.MetricsServer(hist))
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=25))
+ metrics_pb2.add_MetricsServiceServicer_to_server(
+ metrics_server.MetricsServer(hist), server)
server.add_insecure_port('[::]:{}'.format(args.metrics_port))
server.start()
- for test_server in test_servers:
- host, port = test_server.split(':', 1)
+ for test_server_target in test_server_targets:
for _ in xrange(args.num_channels_per_server):
- channel = implementations.insecure_channel(host, int(port))
+ channel = grpc.insecure_channel(test_server_target)
for _ in xrange(args.num_stubs_per_channel):
- stub = test_pb2.beta_create_TestService_stub(channel)
+ stub = test_pb2.TestServiceStub(channel)
runner = test_runner.TestRunner(stub, test_cases, hist,
exception_queue, stop_event)
runners.append(runner)
@@ -128,8 +129,8 @@ def run_test(args):
stop_event.set()
for runner in runners:
runner.join()
- runner = None
- server.stop(0)
+ runner = None
+ server.stop(None)
if __name__ == '__main__':
run_test(_args())
diff --git a/src/python/grpcio_tests/tests/stress/metrics_server.py b/src/python/grpcio_tests/tests/stress/metrics_server.py
index b994e4643e..33dd1d6f2a 100644
--- a/src/python/grpcio_tests/tests/stress/metrics_server.py
+++ b/src/python/grpcio_tests/tests/stress/metrics_server.py
@@ -36,7 +36,7 @@ from src.proto.grpc.testing import metrics_pb2
GAUGE_NAME = 'python_overall_qps'
-class MetricsServer(metrics_pb2.BetaMetricsServiceServicer):
+class MetricsServer(metrics_pb2.MetricsServiceServicer):
def __init__(self, histogram):
self._start_time = time.time()
diff --git a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
index 3c00f686ce..9cae96a00d 100644
--- a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
+++ b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
@@ -32,12 +32,12 @@
import threading
import time
import unittest
-from concurrent import futures
import grpc
from grpc import _channel
from grpc import _server
from tests.unit.framework.common import test_constants
+from tests.unit import _thread_pool
def _ready_in_connectivities(connectivities):
@@ -104,7 +104,8 @@ class ChannelConnectivityTest(unittest.TestCase):
grpc.ChannelConnectivity.READY, fifth_connectivities)
def test_immediately_connectable_channel_connectivity(self):
- server = _server.Server(futures.ThreadPoolExecutor(max_workers=0), ())
+ thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
+ server = _server.Server(thread_pool, ())
port = server.add_insecure_port('[::]:0')
server.start()
first_callback = _Callback()
@@ -141,9 +142,11 @@ class ChannelConnectivityTest(unittest.TestCase):
fourth_connectivities)
self.assertNotIn(
grpc.ChannelConnectivity.SHUTDOWN, fourth_connectivities)
+ self.assertFalse(thread_pool.was_used())
def test_reachable_then_unreachable_channel_connectivity(self):
- server = _server.Server(futures.ThreadPoolExecutor(max_workers=0), ())
+ thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
+ server = _server.Server(thread_pool, ())
port = server.add_insecure_port('[::]:0')
server.start()
callback = _Callback()
@@ -155,6 +158,7 @@ class ChannelConnectivityTest(unittest.TestCase):
server.stop(None)
callback.block_until_connectivities_satisfy(_last_connectivity_is_not_ready)
channel.unsubscribe(callback.update)
+ self.assertFalse(thread_pool.was_used())
if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py
index e8982ed2de..24f5b45b18 100644
--- a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py
+++ b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py
@@ -31,12 +31,12 @@
import threading
import unittest
-from concurrent import futures
import grpc
from grpc import _channel
from grpc import _server
from tests.unit.framework.common import test_constants
+from tests.unit import _thread_pool
class _Callback(object):
@@ -78,7 +78,8 @@ class ChannelReadyFutureTest(unittest.TestCase):
self.assertFalse(ready_future.running())
def test_immediately_connectable_channel_connectivity(self):
- server = _server.Server(futures.ThreadPoolExecutor(max_workers=0), ())
+ thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
+ server = _server.Server(thread_pool, ())
port = server.add_insecure_port('[::]:0')
server.start()
channel = grpc.insecure_channel('localhost:{}'.format(port))
@@ -97,6 +98,7 @@ class ChannelReadyFutureTest(unittest.TestCase):
self.assertFalse(ready_future.cancelled())
self.assertTrue(ready_future.done())
self.assertFalse(ready_future.running())
+ self.assertFalse(thread_pool.was_used())
if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
index f9a8e2401b..2f50263730 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
@@ -30,6 +30,7 @@
import time
import threading
import unittest
+import platform
from grpc._cython import cygrpc
from tests.unit._cython import test_utilities
@@ -113,6 +114,9 @@ class TypeSmokeTest(unittest.TestCase):
lambda ignored_a, ignored_b: None, b'')
del plugin
+ @unittest.skipIf(
+ platform.python_implementation() == "PyPy",
+ 'TODO(issue 7672): figure out why this fails on PyPy')
def testCallCredentialsFromPluginUpDown(self):
plugin = cygrpc.CredentialsMetadataPlugin(_metadata_plugin_callback, b'')
call_credentials = cygrpc.call_credentials_metadata_plugin(plugin)
diff --git a/src/python/grpcio_tests/tests/unit/_thread_pool.py b/src/python/grpcio_tests/tests/unit/_thread_pool.py
new file mode 100644
index 0000000000..f13cc2f86f
--- /dev/null
+++ b/src/python/grpcio_tests/tests/unit/_thread_pool.py
@@ -0,0 +1,48 @@
+# Copyright 2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import threading
+from concurrent import futures
+
+
+class RecordingThreadPool(futures.Executor):
+ """A thread pool that records if used."""
+ def __init__(self, max_workers):
+ self._tp_executor = futures.ThreadPoolExecutor(max_workers=max_workers)
+ self._lock = threading.Lock()
+ self._was_used = False
+
+ def submit(self, fn, *args, **kwargs):
+ with self._lock:
+ self._was_used = True
+ self._tp_executor.submit(fn, *args, **kwargs)
+
+ def was_used(self):
+ with self._lock:
+ return self._was_used
diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py
index d32208f9eb..df620b19ba 100644
--- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py
+++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py
@@ -434,11 +434,13 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest.
for test_messages in test_messages_sequence:
request = test_messages.request()
callback = _Callback()
+ abortion_callback = _Callback()
with self._control.fail():
response_future = self._invoker.future(group, method)(
request, _3069_test_constant.REALLY_SHORT_TIMEOUT)
response_future.add_done_callback(callback)
+ response_future.add_abortion_callback(abortion_callback)
self.assertIs(callback.future(), response_future)
# Because the servicer fails outside of the thread from which the
@@ -450,6 +452,7 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest.
with self.assertRaises(face.ExpirationError):
response_future.result()
self.assertIsNotNone(response_future.traceback())
+ self.assertIsNotNone(abortion_callback.future())
def testFailedUnaryRequestStreamResponse(self):
for (group, method), test_messages_sequence in (
@@ -472,11 +475,13 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest.
for test_messages in test_messages_sequence:
requests = test_messages.requests()
callback = _Callback()
+ abortion_callback = _Callback()
with self._control.fail():
response_future = self._invoker.future(group, method)(
iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT)
response_future.add_done_callback(callback)
+ response_future.add_abortion_callback(abortion_callback)
self.assertIs(callback.future(), response_future)
# Because the servicer fails outside of the thread from which the
@@ -488,6 +493,7 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest.
with self.assertRaises(face.ExpirationError):
response_future.result()
self.assertIsNotNone(response_future.traceback())
+ self.assertIsNotNone(abortion_callback.future())
def testFailedStreamRequestStreamResponse(self):
for (group, method), test_messages_sequence in (
diff --git a/src/ruby/.rubocop.yml b/src/ruby/.rubocop.yml
index 34bb477543..0f61ccfa81 100644
--- a/src/ruby/.rubocop.yml
+++ b/src/ruby/.rubocop.yml
@@ -5,8 +5,8 @@ inherit_from: .rubocop_todo.yml
AllCops:
Exclude:
- 'bin/apis/**/*'
- - 'bin/math.rb'
- - 'bin/math_services.rb'
+ - 'bin/math_pb.rb'
+ - 'bin/math_services_pb.rb'
- 'pb/grpc/health/v1/*'
- 'pb/test/**/*'
diff --git a/src/ruby/bin/math_client.rb b/src/ruby/bin/math_client.rb
index d7e00e4293..1f238a798b 100755
--- a/src/ruby/bin/math_client.rb
+++ b/src/ruby/bin/math_client.rb
@@ -40,7 +40,7 @@ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
require 'grpc'
-require 'math_services'
+require 'math_services_pb'
require 'optparse'
include GRPC::Core::TimeConsts
diff --git a/src/ruby/bin/math.rb b/src/ruby/bin/math_pb.rb
index 60429a1505..60429a1505 100755..100644
--- a/src/ruby/bin/math.rb
+++ b/src/ruby/bin/math_pb.rb
diff --git a/src/ruby/bin/math_server.rb b/src/ruby/bin/math_server.rb
index 1ee4c5632d..751a6ebcab 100755
--- a/src/ruby/bin/math_server.rb
+++ b/src/ruby/bin/math_server.rb
@@ -42,7 +42,7 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
require 'forwardable'
require 'grpc'
require 'logger'
-require 'math_services'
+require 'math_services_pb'
require 'optparse'
# RubyLogger defines a logger for gRPC based on the standard ruby logger.
diff --git a/src/ruby/bin/math_services.rb b/src/ruby/bin/math_services_pb.rb
index 2b97602b6f..2ba1825d4f 100755..100644
--- a/src/ruby/bin/math_services.rb
+++ b/src/ruby/bin/math_services_pb.rb
@@ -32,7 +32,7 @@
#
require 'grpc'
-require 'math'
+require 'math_pb'
module Math
module Math
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index 18a15d0125..e6d30a174b 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -40,6 +40,7 @@
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
+#include <grpc/support/time.h>
#include "rb_grpc.h"
#include "rb_call.h"
#include "rb_channel_args.h"
@@ -71,6 +72,7 @@ typedef struct grpc_rb_channel {
/* The actual channel */
grpc_channel *wrapped;
+ grpc_completion_queue *queue;
} grpc_rb_channel;
/* Destroys Channel instances. */
@@ -83,6 +85,7 @@ static void grpc_rb_channel_free(void *p) {
if (ch->wrapped != NULL) {
grpc_channel_destroy(ch->wrapped);
+ grpc_rb_completion_queue_destroy(ch->queue);
}
xfree(p);
@@ -165,6 +168,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
}
rb_ivar_set(self, id_target, target);
wrapper->wrapped = ch;
+ wrapper->queue = grpc_completion_queue_create(NULL);
return self;
}
@@ -203,16 +207,18 @@ static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv,
the completion queue with success=0 */
static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self,
VALUE last_state,
- VALUE cqueue,
- VALUE deadline,
- VALUE tag) {
+ VALUE deadline) {
grpc_rb_channel *wrapper = NULL;
grpc_channel *ch = NULL;
grpc_completion_queue *cq = NULL;
- cq = grpc_rb_get_wrapped_completion_queue(cqueue);
+ void *tag = wrapper;
+
+ grpc_event event;
+
TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
ch = wrapper->wrapped;
+ cq = wrapper->queue;
if (ch == NULL) {
rb_raise(rb_eRuntimeError, "closed!");
return Qnil;
@@ -222,9 +228,16 @@ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self,
(grpc_connectivity_state)NUM2LONG(last_state),
grpc_rb_time_timeval(deadline, /* absolute time */ 0),
cq,
- ROBJECT(tag));
+ tag);
- return Qnil;
+ event = rb_completion_queue_pluck(cq, tag,
+ gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+
+ if (event.success) {
+ return Qtrue;
+ } else {
+ return Qfalse;
+ }
}
/* Create a call given a grpc_channel, in order to call method. The request
diff --git a/src/ruby/ext/grpc/rb_completion_queue.h b/src/ruby/ext/grpc/rb_completion_queue.h
index 9f8f6aa5ff..aa9dc6416a 100644
--- a/src/ruby/ext/grpc/rb_completion_queue.h
+++ b/src/ruby/ext/grpc/rb_completion_queue.h
@@ -38,9 +38,6 @@
#include <grpc/grpc.h>
-/* Gets the wrapped completion queue from the ruby wrapper */
-grpc_completion_queue *grpc_rb_get_wrapped_completion_queue(VALUE v);
-
void grpc_rb_completion_queue_destroy(grpc_completion_queue *cq);
/**
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 9748cb576b..aee57b11aa 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -61,15 +61,10 @@ census_trace_print_type census_trace_print_import;
census_trace_scan_start_type census_trace_scan_start_import;
census_get_trace_record_type census_get_trace_record_import;
census_trace_scan_end_type census_trace_scan_end_import;
+census_define_resource_type census_define_resource_import;
+census_delete_resource_type census_delete_resource_import;
+census_resource_id_type census_resource_id_import;
census_record_values_type census_record_values_import;
-census_view_create_type census_view_create_import;
-census_view_delete_type census_view_delete_import;
-census_view_metric_type census_view_metric_import;
-census_view_naggregations_type census_view_naggregations_import;
-census_view_tags_type census_view_tags_import;
-census_view_aggregrations_type census_view_aggregrations_import;
-census_view_get_data_type census_view_get_data_import;
-census_view_reset_type census_view_reset_import;
grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import;
grpc_compression_algorithm_name_type grpc_compression_algorithm_name_import;
grpc_compression_algorithm_for_level_type grpc_compression_algorithm_for_level_import;
@@ -186,6 +181,7 @@ gpr_set_log_function_type gpr_set_log_function_import;
gpr_slice_ref_type gpr_slice_ref_import;
gpr_slice_unref_type gpr_slice_unref_import;
gpr_slice_new_type gpr_slice_new_import;
+gpr_slice_new_with_user_data_type gpr_slice_new_with_user_data_import;
gpr_slice_new_with_len_type gpr_slice_new_with_len_import;
gpr_slice_malloc_type gpr_slice_malloc_import;
gpr_slice_from_copied_string_type gpr_slice_from_copied_string_import;
@@ -333,15 +329,10 @@ void grpc_rb_load_imports(HMODULE library) {
census_trace_scan_start_import = (census_trace_scan_start_type) GetProcAddress(library, "census_trace_scan_start");
census_get_trace_record_import = (census_get_trace_record_type) GetProcAddress(library, "census_get_trace_record");
census_trace_scan_end_import = (census_trace_scan_end_type) GetProcAddress(library, "census_trace_scan_end");
+ census_define_resource_import = (census_define_resource_type) GetProcAddress(library, "census_define_resource");
+ census_delete_resource_import = (census_delete_resource_type) GetProcAddress(library, "census_delete_resource");
+ census_resource_id_import = (census_resource_id_type) GetProcAddress(library, "census_resource_id");
census_record_values_import = (census_record_values_type) GetProcAddress(library, "census_record_values");
- census_view_create_import = (census_view_create_type) GetProcAddress(library, "census_view_create");
- census_view_delete_import = (census_view_delete_type) GetProcAddress(library, "census_view_delete");
- census_view_metric_import = (census_view_metric_type) GetProcAddress(library, "census_view_metric");
- census_view_naggregations_import = (census_view_naggregations_type) GetProcAddress(library, "census_view_naggregations");
- census_view_tags_import = (census_view_tags_type) GetProcAddress(library, "census_view_tags");
- census_view_aggregrations_import = (census_view_aggregrations_type) GetProcAddress(library, "census_view_aggregrations");
- census_view_get_data_import = (census_view_get_data_type) GetProcAddress(library, "census_view_get_data");
- census_view_reset_import = (census_view_reset_type) GetProcAddress(library, "census_view_reset");
grpc_compression_algorithm_parse_import = (grpc_compression_algorithm_parse_type) GetProcAddress(library, "grpc_compression_algorithm_parse");
grpc_compression_algorithm_name_import = (grpc_compression_algorithm_name_type) GetProcAddress(library, "grpc_compression_algorithm_name");
grpc_compression_algorithm_for_level_import = (grpc_compression_algorithm_for_level_type) GetProcAddress(library, "grpc_compression_algorithm_for_level");
@@ -458,6 +449,7 @@ void grpc_rb_load_imports(HMODULE library) {
gpr_slice_ref_import = (gpr_slice_ref_type) GetProcAddress(library, "gpr_slice_ref");
gpr_slice_unref_import = (gpr_slice_unref_type) GetProcAddress(library, "gpr_slice_unref");
gpr_slice_new_import = (gpr_slice_new_type) GetProcAddress(library, "gpr_slice_new");
+ gpr_slice_new_with_user_data_import = (gpr_slice_new_with_user_data_type) GetProcAddress(library, "gpr_slice_new_with_user_data");
gpr_slice_new_with_len_import = (gpr_slice_new_with_len_type) GetProcAddress(library, "gpr_slice_new_with_len");
gpr_slice_malloc_import = (gpr_slice_malloc_type) GetProcAddress(library, "gpr_slice_malloc");
gpr_slice_from_copied_string_import = (gpr_slice_from_copied_string_type) GetProcAddress(library, "gpr_slice_from_copied_string");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 6f0974e31b..3bb76fbb97 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -134,33 +134,18 @@ extern census_get_trace_record_type census_get_trace_record_import;
typedef void(*census_trace_scan_end_type)();
extern census_trace_scan_end_type census_trace_scan_end_import;
#define census_trace_scan_end census_trace_scan_end_import
+typedef int32_t(*census_define_resource_type)(const uint8_t *resource_pb, size_t resource_pb_size);
+extern census_define_resource_type census_define_resource_import;
+#define census_define_resource census_define_resource_import
+typedef void(*census_delete_resource_type)(int32_t resource_id);
+extern census_delete_resource_type census_delete_resource_import;
+#define census_delete_resource census_delete_resource_import
+typedef int32_t(*census_resource_id_type)(const char *name);
+extern census_resource_id_type census_resource_id_import;
+#define census_resource_id census_resource_id_import
typedef void(*census_record_values_type)(census_context *context, census_value *values, size_t nvalues);
extern census_record_values_type census_record_values_import;
#define census_record_values census_record_values_import
-typedef census_view *(*census_view_create_type)(uint32_t metric_id, const census_context *tags, const census_aggregation *aggregations, size_t naggregations);
-extern census_view_create_type census_view_create_import;
-#define census_view_create census_view_create_import
-typedef void(*census_view_delete_type)(census_view *view);
-extern census_view_delete_type census_view_delete_import;
-#define census_view_delete census_view_delete_import
-typedef size_t(*census_view_metric_type)(const census_view *view);
-extern census_view_metric_type census_view_metric_import;
-#define census_view_metric census_view_metric_import
-typedef size_t(*census_view_naggregations_type)(const census_view *view);
-extern census_view_naggregations_type census_view_naggregations_import;
-#define census_view_naggregations census_view_naggregations_import
-typedef const census_context *(*census_view_tags_type)(const census_view *view);
-extern census_view_tags_type census_view_tags_import;
-#define census_view_tags census_view_tags_import
-typedef const census_aggregation *(*census_view_aggregrations_type)(const census_view *view);
-extern census_view_aggregrations_type census_view_aggregrations_import;
-#define census_view_aggregrations census_view_aggregrations_import
-typedef const census_view_data *(*census_view_get_data_type)(const census_view *view);
-extern census_view_get_data_type census_view_get_data_import;
-#define census_view_get_data census_view_get_data_import
-typedef void(*census_view_reset_type)(census_view *view);
-extern census_view_reset_type census_view_reset_import;
-#define census_view_reset census_view_reset_import
typedef int(*grpc_compression_algorithm_parse_type)(const char *name, size_t name_length, grpc_compression_algorithm *algorithm);
extern grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import;
#define grpc_compression_algorithm_parse grpc_compression_algorithm_parse_import
@@ -509,6 +494,9 @@ extern gpr_slice_unref_type gpr_slice_unref_import;
typedef gpr_slice(*gpr_slice_new_type)(void *p, size_t len, void (*destroy)(void *));
extern gpr_slice_new_type gpr_slice_new_import;
#define gpr_slice_new gpr_slice_new_import
+typedef gpr_slice(*gpr_slice_new_with_user_data_type)(void *p, size_t len, void (*destroy)(void *), void *user_data);
+extern gpr_slice_new_with_user_data_type gpr_slice_new_with_user_data_import;
+#define gpr_slice_new_with_user_data gpr_slice_new_with_user_data_import
typedef gpr_slice(*gpr_slice_new_with_len_type)(void *p, size_t len, void (*destroy)(void *, size_t));
extern gpr_slice_new_with_len_type gpr_slice_new_with_len_import;
#define gpr_slice_new_with_len gpr_slice_new_with_len_import
diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb
index 4260d85437..23688dc924 100644
--- a/src/ruby/lib/grpc/generic/active_call.rb
+++ b/src/ruby/lib/grpc/generic/active_call.rb
@@ -58,7 +58,7 @@ module GRPC
include Core::TimeConsts
include Core::CallOps
extend Forwardable
- attr_reader(:deadline)
+ attr_reader :deadline, :metadata_sent, :metadata_to_send
def_delegators :@call, :cancel, :metadata, :write_flag, :write_flag=,
:peer, :peer_cert, :trailing_metadata
@@ -101,7 +101,7 @@ module GRPC
# @param metadata_received [true|false] indicates if metadata has already
# been received. Should always be true for server calls
def initialize(call, marshal, unmarshal, deadline, started: true,
- metadata_received: false)
+ metadata_received: false, metadata_to_send: nil)
fail(TypeError, '!Core::Call') unless call.is_a? Core::Call
@call = call
@deadline = deadline
@@ -110,6 +110,20 @@ module GRPC
@metadata_received = metadata_received
@metadata_sent = started
@op_notifier = nil
+
+ fail(ArgumentError, 'Already sent md') if started && metadata_to_send
+ @metadata_to_send = metadata_to_send || {} unless started
+ @send_initial_md_mutex = Mutex.new
+ end
+
+ # Sends the initial metadata that has yet to be sent.
+ # Does nothing if metadata has already been sent for this call.
+ def send_initial_metadata
+ @send_initial_md_mutex.synchronize do
+ return if @metadata_sent
+ @metadata_tag = ActiveCall.client_invoke(@call, @metadata_to_send)
+ @metadata_sent = true
+ end
end
# output_metadata are provides access to hash that can be used to
@@ -187,7 +201,7 @@ module GRPC
# @param marshalled [false, true] indicates if the object is already
# marshalled.
def remote_send(req, marshalled = false)
- # TODO(murgatroid99): ensure metadata was sent
+ send_initial_metadata
GRPC.logger.debug("sending #{req}, marshalled? #{marshalled}")
payload = marshalled ? req : @marshal.call(req)
@call.run_batch(SEND_MESSAGE => payload)
@@ -203,6 +217,7 @@ module GRPC
# list, mulitple metadata for its key are sent
def send_status(code = OK, details = '', assert_finished = false,
metadata: {})
+ send_initial_metadata
ops = {
SEND_STATUS_FROM_SERVER => Struct::Status.new(code, details, metadata)
}
@@ -303,7 +318,7 @@ module GRPC
# a list, multiple metadata for its key are sent
# @return [Object] the response received from the server
def request_response(req, metadata: {})
- start_call(metadata)
+ merge_metadata_to_send(metadata) && send_initial_metadata
remote_send(req)
writes_done(false)
response = remote_read
@@ -327,7 +342,7 @@ module GRPC
# a list, multiple metadata for its key are sent
# @return [Object] the response received from the server
def client_streamer(requests, metadata: {})
- start_call(metadata)
+ merge_metadata_to_send(metadata) && send_initial_metadata
requests.each { |r| remote_send(r) }
writes_done(false)
response = remote_read
@@ -353,7 +368,7 @@ module GRPC
# a list, multiple metadata for its key are sent
# @return [Enumerator|nil] a response Enumerator
def server_streamer(req, metadata: {})
- start_call(metadata)
+ merge_metadata_to_send(metadata) && send_initial_metadata
remote_send(req)
writes_done(false)
replies = enum_for(:each_remote_read_then_finish)
@@ -392,9 +407,12 @@ module GRPC
# a list, multiple metadata for its key are sent
# @return [Enumerator, nil] a response Enumerator
def bidi_streamer(requests, metadata: {}, &blk)
- start_call(metadata)
- bd = BidiCall.new(@call, @marshal, @unmarshal,
+ merge_metadata_to_send(metadata) && send_initial_metadata
+ bd = BidiCall.new(@call,
+ @marshal,
+ @unmarshal,
metadata_received: @metadata_received)
+
bd.run_on_client(requests, @op_notifier, &blk)
end
@@ -410,8 +428,12 @@ module GRPC
#
# @param gen_each_reply [Proc] generates the BiDi stream replies
def run_server_bidi(gen_each_reply)
- bd = BidiCall.new(@call, @marshal, @unmarshal,
- metadata_received: @metadata_received)
+ bd = BidiCall.new(@call,
+ @marshal,
+ @unmarshal,
+ metadata_received: @metadata_received,
+ req_view: MultiReqView.new(self))
+
bd.run_on_server(gen_each_reply)
end
@@ -428,15 +450,23 @@ module GRPC
@op_notifier.notify(self)
end
+ # Add to the metadata that will be sent from the server.
+ # Fails if metadata has already been sent.
+ # Unused by client calls.
+ def merge_metadata_to_send(new_metadata = {})
+ @send_initial_md_mutex.synchronize do
+ fail('cant change metadata after already sent') if @metadata_sent
+ @metadata_to_send.merge!(new_metadata)
+ end
+ end
+
private
# Starts the call if not already started
# @param metadata [Hash] metadata to be sent to the server. If a value is
# a list, multiple metadata for its key are sent
def start_call(metadata = {})
- return if @metadata_sent
- @metadata_tag = ActiveCall.client_invoke(@call, metadata)
- @metadata_sent = true
+ merge_metadata_to_send(metadata) && send_initial_metadata
end
def self.view_class(*visible_methods)
@@ -454,12 +484,20 @@ module GRPC
# SingleReqView limits access to an ActiveCall's methods for use in server
# handlers that receive just one request.
SingleReqView = view_class(:cancelled?, :deadline, :metadata,
- :output_metadata, :peer, :peer_cert)
+ :output_metadata, :peer, :peer_cert,
+ :send_initial_metadata,
+ :metadata_to_send,
+ :merge_metadata_to_send,
+ :metadata_sent)
# MultiReqView limits access to an ActiveCall's methods for use in
# server client_streamer handlers.
MultiReqView = view_class(:cancelled?, :deadline, :each_queued_msg,
- :each_remote_read, :metadata, :output_metadata)
+ :each_remote_read, :metadata, :output_metadata,
+ :send_initial_metadata,
+ :metadata_to_send,
+ :merge_metadata_to_send,
+ :metadata_sent)
# Operation limits access to an ActiveCall's methods for use as
# a Operation on the client.
diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb
index 425dc3e519..d7cd9e6df2 100644
--- a/src/ruby/lib/grpc/generic/bidi_call.rb
+++ b/src/ruby/lib/grpc/generic/bidi_call.rb
@@ -56,18 +56,19 @@ module GRPC
# @param unmarshal [Function] f(string)->obj that unmarshals responses
# @param metadata_received [true|false] indicates if metadata has already
# been received. Should always be true for server calls
- def initialize(call, marshal, unmarshal, metadata_received: false)
+ def initialize(call, marshal, unmarshal, metadata_received: false,
+ req_view: nil)
fail(ArgumentError, 'not a call') unless call.is_a? Core::Call
@call = call
@marshal = marshal
@op_notifier = nil # signals completion on clients
- @readq = Queue.new
@unmarshal = unmarshal
@metadata_received = metadata_received
@reads_complete = false
@writes_complete = false
@complete = false
@done_mutex = Mutex.new
+ @req_view = req_view
end
# Begins orchestration of the Bidi stream for a client sending requests.
@@ -76,13 +77,12 @@ module GRPC
# block that can be invoked with each response.
#
# @param requests the Enumerable of requests to send
- # @op_notifier a Notifier used to signal completion
+ # @param op_notifier a Notifier used to signal completion
# @return an Enumerator of requests to yield
def run_on_client(requests, op_notifier, &blk)
@op_notifier = op_notifier
@enq_th = Thread.new { write_loop(requests) }
- @loop_th = start_read_loop
- each_queued_msg(&blk)
+ read_loop(&blk)
end
# Begins orchestration of the Bidi stream for a server generating replies.
@@ -97,8 +97,15 @@ module GRPC
#
# @param gen_each_reply [Proc] generates the BiDi stream replies.
def run_on_server(gen_each_reply)
- replys = gen_each_reply.call(each_queued_msg)
- @loop_th = start_read_loop(is_client: false)
+ # Pass in the optional call object parameter if possible
+ if gen_each_reply.arity == 1
+ replys = gen_each_reply.call(read_loop(is_client: false))
+ elsif gen_each_reply.arity == 2
+ replys = gen_each_reply.call(read_loop(is_client: false), @req_view)
+ else
+ fail 'Illegal arity of reply generator'
+ end
+
write_loop(replys, is_client: false)
end
@@ -135,24 +142,6 @@ module GRPC
batch_result
end
- # each_queued_msg yields each message on this instances readq
- #
- # - messages are added to the readq by #read_loop
- # - iteration ends when the instance itself is added
- def each_queued_msg
- return enum_for(:each_queued_msg) unless block_given?
- count = 0
- loop do
- GRPC.logger.debug("each_queued_msg: waiting##{count}")
- count += 1
- req = @readq.pop
- GRPC.logger.debug("each_queued_msg: req = #{req}")
- fail req if req.is_a? StandardError
- break if req.equal?(END_OF_READS)
- yield req
- end
- end
-
def write_loop(requests, is_client: true)
GRPC.logger.debug('bidi-write-loop: starting')
count = 0
@@ -162,6 +151,7 @@ module GRPC
payload = @marshal.call(req)
# Fails if status already received
begin
+ @req_view.send_initial_metadata unless @req_view.nil?
@call.run_batch(SEND_MESSAGE => payload)
rescue GRPC::Core::CallError => e
# This is almost definitely caused by a status arriving while still
@@ -190,47 +180,45 @@ module GRPC
raise e
end
- # starts the read loop
- def start_read_loop(is_client: true)
- Thread.new do
- GRPC.logger.debug('bidi-read-loop: starting')
- begin
- count = 0
- # queue the initial read before beginning the loop
- loop do
- GRPC.logger.debug("bidi-read-loop: #{count}")
- count += 1
- batch_result = read_using_run_batch
-
- # handle the next message
- if batch_result.message.nil?
- GRPC.logger.debug("bidi-read-loop: null batch #{batch_result}")
-
- if is_client
- batch_result = @call.run_batch(RECV_STATUS_ON_CLIENT => nil)
- @call.status = batch_result.status
- batch_result.check_status
- GRPC.logger.debug("bidi-read-loop: done status #{@call.status}")
- end
-
- @readq.push(END_OF_READS)
- GRPC.logger.debug('bidi-read-loop: done reading!')
- break
+ # Provides an enumerator that yields results of remote reads
+ def read_loop(is_client: true)
+ return enum_for(:read_loop,
+ is_client: is_client) unless block_given?
+ GRPC.logger.debug('bidi-read-loop: starting')
+ begin
+ count = 0
+ # queue the initial read before beginning the loop
+ loop do
+ GRPC.logger.debug("bidi-read-loop: #{count}")
+ count += 1
+ batch_result = read_using_run_batch
+
+ # handle the next message
+ if batch_result.message.nil?
+ GRPC.logger.debug("bidi-read-loop: null batch #{batch_result}")
+
+ if is_client
+ batch_result = @call.run_batch(RECV_STATUS_ON_CLIENT => nil)
+ @call.status = batch_result.status
+ batch_result.check_status
+ GRPC.logger.debug("bidi-read-loop: done status #{@call.status}")
end
- # push the latest read onto the queue and continue reading
- res = @unmarshal.call(batch_result.message)
- @readq.push(res)
+ GRPC.logger.debug('bidi-read-loop: done reading!')
+ break
end
- rescue StandardError => e
- GRPC.logger.warn('bidi: read-loop failed')
- GRPC.logger.warn(e)
- @readq.push(e) # let each_queued_msg terminate with this error
+
+ res = @unmarshal.call(batch_result.message)
+ yield res
end
- GRPC.logger.debug('bidi-read-loop: finished')
- @reads_complete = true
- finished
+ rescue StandardError => e
+ GRPC.logger.warn('bidi: read-loop failed')
+ GRPC.logger.warn(e)
+ raise e
end
+ GRPC.logger.debug('bidi-read-loop: finished')
+ @reads_complete = true
+ finished
end
end
end
diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb
index 9d6bd3bf59..0d7c1f7805 100644
--- a/src/ruby/lib/grpc/generic/client_stub.rb
+++ b/src/ruby/lib/grpc/generic/client_stub.rb
@@ -34,7 +34,8 @@ require_relative '../version'
module GRPC
# rubocop:disable Metrics/ParameterLists
- # ClientStub represents an endpoint used to send requests to GRPC servers.
+ # ClientStub represents a client connection to a gRPC server, and can be used
+ # to send requests.
class ClientStub
include Core::StatusCodes
include Core::TimeConsts
@@ -75,8 +76,9 @@ module GRPC
# my_stub = ClientStub.new(example.host.com:50505,
# :this_channel_is_insecure)
#
- # Any arbitrary keyword arguments are treated as channel arguments used to
- # configure the RPC connection to the host.
+ # If a channel_override argument is passed, it will be used as the
+ # underlying channel. Otherwise, the channel_args argument will be used
+ # to construct a new underlying channel.
#
# There are some specific keyword args that are not used to configure the
# channel:
@@ -91,10 +93,17 @@ module GRPC
#
# @param host [String] the host the stub connects to
# @param creds [Core::ChannelCredentials|Symbol] the channel credentials, or
- # :this_channel_is_insecure
+ # :this_channel_is_insecure, which explicitly indicates that the client
+ # should be created with an insecure connection. Note: this argument is
+ # ignored if the channel_override argument is provided.
# @param channel_override [Core::Channel] a pre-created channel
# @param timeout [Number] the default timeout to use in requests
- # @param channel_args [Hash] the channel arguments
+ # @param propagate_mask [Number] A bitwise combination of flags in
+ # GRPC::Core::PropagateMasks. Indicates how data should be propagated
+ # from parent server calls to child client calls if this client is being
+ # used within a gRPC server.
+ # @param channel_args [Hash] the channel arguments. Note: this argument is
+ # ignored if the channel_override argument is provided.
def initialize(host, creds,
channel_override: nil,
timeout: nil,
@@ -389,11 +398,11 @@ module GRPC
# @param marshal [Function] f(obj)->string that marshals requests
# @param unmarshal [Function] f(string)->obj that unmarshals responses
# @param deadline [Time] (optional) the time the request should complete
+ # @param return_op [true|false] return an Operation if true
# @param parent [Core::Call] a prior call whose reserved metadata
# will be propagated by this one.
# @param credentials [Core::CallCredentials] credentials to use when making
# the call
- # @param return_op [true|false] return an Operation if true
# @param metadata [Hash] metadata to be sent to the server
# @param blk [Block] when provided, is executed for each response
# @return [Enumerator|nil|Operation] as discussed above
@@ -430,7 +439,8 @@ module GRPC
# @param unmarshal [Function] f(string)->obj that unmarshals responses
# @param parent [Grpc::Call] a parent call, available when calls are
# made from server
- # @param timeout [TimeConst]
+ # @param credentials [Core::CallCredentials] credentials to use when making
+ # the call
def new_active_call(method, marshal, unmarshal,
deadline: nil,
parent: nil,
diff --git a/src/ruby/lib/grpc/generic/rpc_desc.rb b/src/ruby/lib/grpc/generic/rpc_desc.rb
index 913f55d0d3..584fe78169 100644
--- a/src/ruby/lib/grpc/generic/rpc_desc.rb
+++ b/src/ruby/lib/grpc/generic/rpc_desc.rb
@@ -104,7 +104,14 @@ module GRPC
end
def assert_arity_matches(mth)
- if request_response? || server_streamer?
+ # A bidi handler function can optionally be passed a second
+ # call object parameter for access to metadata, cancelling, etc.
+ if bidi_streamer?
+ if mth.arity != 2 && mth.arity != 1
+ fail arity_error(mth, 2, "should be #{mth.name}(req, call) or " \
+ "#{mth.name}(req)")
+ end
+ elsif request_response? || server_streamer?
if mth.arity != 2
fail arity_error(mth, 2, "should be #{mth.name}(req, call)")
end
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index c92a532a50..8ea798dce0 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -172,22 +172,18 @@ module GRPC
# The RPC server is configured using keyword arguments.
#
# There are some specific keyword args used to configure the RpcServer
- # instance, however other arbitrary are allowed and when present are used
- # to configure the listeninng connection set up by the RpcServer.
- #
- # * poll_period: when present, the server polls for new events with this
- # period
+ # instance.
#
# * pool_size: the size of the thread pool the server uses to run its
# threads
#
- # * creds: [GRPC::Core::ServerCredentials]
- # the credentials used to secure the server
- #
# * max_waiting_requests: the maximum number of requests that are not
# being handled to allow. When this limit is exceeded, the server responds
# with not available to new requests
#
+ # * poll_period: when present, the server polls for new events with this
+ # period
+ #
# * connect_md_proc:
# when non-nil is a proc for determining metadata to to send back the client
# on receiving an invocation req. The proc signature is:
@@ -339,8 +335,11 @@ module GRPC
return an_rpc if @pool.jobs_waiting <= @max_waiting_requests
GRPC.logger.warn("NOT AVAILABLE: too many jobs_waiting: #{an_rpc}")
noop = proc { |x| x }
+
+ # Create a new active call that knows that metadata hasn't been
+ # sent yet
c = ActiveCall.new(an_rpc.call, noop, noop, an_rpc.deadline,
- metadata_received: true)
+ metadata_received: true, started: false)
c.send_status(GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED, '')
nil
end
@@ -351,8 +350,11 @@ module GRPC
return an_rpc if rpc_descs.key?(mth)
GRPC.logger.warn("UNIMPLEMENTED: #{an_rpc}")
noop = proc { |x| x }
+
+ # Create a new active call that knows that
+ # metadata hasn't been sent yet
c = ActiveCall.new(an_rpc.call, noop, noop, an_rpc.deadline,
- metadata_received: true)
+ metadata_received: true, started: false)
c.send_status(GRPC::Core::StatusCodes::UNIMPLEMENTED, '')
nil
end
@@ -400,17 +402,20 @@ module GRPC
unless @connect_md_proc.nil?
connect_md = @connect_md_proc.call(an_rpc.method, an_rpc.metadata)
end
- an_rpc.call.run_batch(SEND_INITIAL_METADATA => connect_md)
return nil unless available?(an_rpc)
return nil unless implemented?(an_rpc)
- # Create the ActiveCall
+ # Create the ActiveCall. Indicate that metadata hasnt been sent yet.
GRPC.logger.info("deadline is #{an_rpc.deadline}; (now=#{Time.now})")
rpc_desc = rpc_descs[an_rpc.method.to_sym]
- c = ActiveCall.new(an_rpc.call, rpc_desc.marshal_proc,
- rpc_desc.unmarshal_proc(:input), an_rpc.deadline,
- metadata_received: true)
+ c = ActiveCall.new(an_rpc.call,
+ rpc_desc.marshal_proc,
+ rpc_desc.unmarshal_proc(:input),
+ an_rpc.deadline,
+ metadata_received: true,
+ started: false,
+ metadata_to_send: connect_md)
mth = an_rpc.method.to_sym
[c, mth]
end
diff --git a/src/ruby/pb/grpc/health/checker.rb b/src/ruby/pb/grpc/health/checker.rb
index f7310d9289..4bce1744c4 100644
--- a/src/ruby/pb/grpc/health/checker.rb
+++ b/src/ruby/pb/grpc/health/checker.rb
@@ -28,7 +28,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc'
-require 'grpc/health/v1/health_services'
+require 'grpc/health/v1/health_services_pb'
require 'thread'
module Grpc
diff --git a/src/ruby/pb/grpc/health/v1/health.rb b/src/ruby/pb/grpc/health/v1/health_pb.rb
index aa87a93918..aa87a93918 100644
--- a/src/ruby/pb/grpc/health/v1/health.rb
+++ b/src/ruby/pb/grpc/health/v1/health_pb.rb
diff --git a/src/ruby/pb/grpc/health/v1/health_services.rb b/src/ruby/pb/grpc/health/v1/health_services_pb.rb
index 68a3956f54..8cc01e91dc 100644
--- a/src/ruby/pb/grpc/health/v1/health_services.rb
+++ b/src/ruby/pb/grpc/health/v1/health_services_pb.rb
@@ -32,7 +32,7 @@
#
require 'grpc'
-require 'grpc/health/v1/health'
+require 'grpc/health/v1/health_pb'
module Grpc
module Health
diff --git a/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services.rb b/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb
index eb523ffa6f..e51c2f087a 100644
--- a/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services.rb
+++ b/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb
@@ -1,5 +1,5 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
-# Source: grpc/testing/duplicate/echo_duplicate.proto for package 'grpc.testing.duplicate'
+# Source: src/proto/grpc/testing/duplicate/echo_duplicate.proto for package 'grpc.testing.duplicate'
# Original file comments:
# Copyright 2015, Google Inc.
# All rights reserved.
@@ -34,7 +34,7 @@
#
require 'grpc'
-require 'grpc/testing/duplicate/echo_duplicate'
+require 'src/proto/grpc/testing/duplicate/echo_duplicate_pb'
module Grpc
module Testing
diff --git a/src/ruby/pb/grpc/testing/metrics.rb b/src/ruby/pb/grpc/testing/metrics_pb.rb
index 3b3c8cd61b..77b6c90970 100644
--- a/src/ruby/pb/grpc/testing/metrics.rb
+++ b/src/ruby/pb/grpc/testing/metrics_pb.rb
@@ -1,5 +1,5 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: grpc/testing/metrics.proto
+# source: src/proto/grpc/testing/metrics.proto
require 'google/protobuf'
diff --git a/src/ruby/pb/grpc/testing/metrics_services.rb b/src/ruby/pb/grpc/testing/metrics_services_pb.rb
index 467b7b3ee5..e46366b1fb 100644
--- a/src/ruby/pb/grpc/testing/metrics_services.rb
+++ b/src/ruby/pb/grpc/testing/metrics_services_pb.rb
@@ -1,5 +1,5 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
-# Source: grpc/testing/metrics.proto for package 'grpc.testing'
+# Source: src/proto/grpc/testing/metrics.proto for package 'grpc.testing'
# Original file comments:
# Copyright 2015-2016, Google Inc.
# All rights reserved.
@@ -38,7 +38,7 @@
# service.
require 'grpc'
-require 'grpc/testing/metrics'
+require 'src/proto/grpc/testing/metrics_pb'
module Grpc
module Testing
diff --git a/src/ruby/pb/src/proto/grpc/testing/empty.rb b/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb
index 9c2568d605..9c2568d605 100644
--- a/src/ruby/pb/src/proto/grpc/testing/empty.rb
+++ b/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb
diff --git a/src/ruby/pb/src/proto/grpc/testing/messages.rb b/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb
index e27ccd0dc0..e27ccd0dc0 100644
--- a/src/ruby/pb/src/proto/grpc/testing/messages.rb
+++ b/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb
diff --git a/src/ruby/pb/src/proto/grpc/testing/test.rb b/src/ruby/pb/src/proto/grpc/testing/test_pb.rb
index 245b5ce00c..2cc9863031 100644
--- a/src/ruby/pb/src/proto/grpc/testing/test.rb
+++ b/src/ruby/pb/src/proto/grpc/testing/test_pb.rb
@@ -3,8 +3,8 @@
require 'google/protobuf'
-require 'src/proto/grpc/testing/empty'
-require 'src/proto/grpc/testing/messages'
+require 'src/proto/grpc/testing/empty_pb'
+require 'src/proto/grpc/testing/messages_pb'
Google::Protobuf::DescriptorPool.generated_pool.build do
end
diff --git a/src/ruby/pb/src/proto/grpc/testing/test_services.rb b/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb
index 2652de5e6d..fde328e4c5 100644
--- a/src/ruby/pb/src/proto/grpc/testing/test_services.rb
+++ b/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb
@@ -35,7 +35,7 @@
#
require 'grpc'
-require 'src/proto/grpc/testing/test'
+require 'src/proto/grpc/testing/test_pb'
module Grpc
module Testing
diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb
index 4c6d441dcb..1e3ae65630 100755
--- a/src/ruby/pb/test/client.rb
+++ b/src/ruby/pb/test/client.rb
@@ -52,9 +52,9 @@ require_relative '../../lib/grpc'
require 'googleauth'
require 'google/protobuf'
-require_relative '../src/proto/grpc/testing/empty'
-require_relative '../src/proto/grpc/testing/messages'
-require_relative '../src/proto/grpc/testing/test_services'
+require_relative '../src/proto/grpc/testing/empty_pb'
+require_relative '../src/proto/grpc/testing/messages_pb'
+require_relative '../src/proto/grpc/testing/test_services_pb'
AUTH_ENV = Google::Auth::CredentialsLoader::ENV_VAR
diff --git a/src/ruby/pb/test/server.rb b/src/ruby/pb/test/server.rb
index 11ee3d465d..0808121661 100755
--- a/src/ruby/pb/test/server.rb
+++ b/src/ruby/pb/test/server.rb
@@ -50,9 +50,9 @@ require 'optparse'
require 'grpc'
-require_relative '../src/proto/grpc/testing/empty'
-require_relative '../src/proto/grpc/testing/messages'
-require_relative '../src/proto/grpc/testing/test_services'
+require_relative '../src/proto/grpc/testing/empty_pb'
+require_relative '../src/proto/grpc/testing/messages_pb'
+require_relative '../src/proto/grpc/testing/test_services_pb'
# DebugIsTruncated extends the default Logger to truncate debug messages
class DebugIsTruncated < Logger
diff --git a/src/ruby/qps/client.rb b/src/ruby/qps/client.rb
index 917b01271e..7ed648acef 100644
--- a/src/ruby/qps/client.rb
+++ b/src/ruby/qps/client.rb
@@ -38,7 +38,7 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
require 'grpc'
require 'histogram'
-require 'src/proto/grpc/testing/services_services'
+require 'src/proto/grpc/testing/services_services_pb'
class Poisson
def interarrival
diff --git a/src/ruby/qps/server.rb b/src/ruby/qps/server.rb
index 52a89ce847..cd98ee1fd9 100644
--- a/src/ruby/qps/server.rb
+++ b/src/ruby/qps/server.rb
@@ -38,9 +38,9 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
require 'grpc'
require 'qps-common'
-require 'src/proto/grpc/testing/messages'
-require 'src/proto/grpc/testing/services_services'
-require 'src/proto/grpc/testing/stats'
+require 'src/proto/grpc/testing/messages_pb'
+require 'src/proto/grpc/testing/services_services_pb'
+require 'src/proto/grpc/testing/stats_pb'
class BenchmarkServiceImpl < Grpc::Testing::BenchmarkService::Service
def unary_call(req, _call)
diff --git a/src/ruby/qps/src/proto/grpc/testing/control.rb b/src/ruby/qps/src/proto/grpc/testing/control_pb.rb
index 958fca320b..02207a2b5d 100644
--- a/src/ruby/qps/src/proto/grpc/testing/control.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/control_pb.rb
@@ -3,8 +3,8 @@
require 'google/protobuf'
-require 'src/proto/grpc/testing/payloads'
-require 'src/proto/grpc/testing/stats'
+require 'src/proto/grpc/testing/payloads_pb'
+require 'src/proto/grpc/testing/stats_pb'
Google::Protobuf::DescriptorPool.generated_pool.build do
add_message "grpc.testing.PoissonParams" do
optional :offered_load, :double, 1
@@ -109,6 +109,8 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
repeated :server_stats, :message, 4, "grpc.testing.ServerStats"
repeated :server_cores, :int32, 5
optional :summary, :message, 6, "grpc.testing.ScenarioResultSummary"
+ repeated :client_success, :bool, 7
+ repeated :server_success, :bool, 8
end
add_enum "grpc.testing.ClientType" do
value :SYNC_CLIENT, 0
diff --git a/src/ruby/qps/src/proto/grpc/testing/messages.rb b/src/ruby/qps/src/proto/grpc/testing/messages_pb.rb
index e27ccd0dc0..e27ccd0dc0 100644
--- a/src/ruby/qps/src/proto/grpc/testing/messages.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/messages_pb.rb
diff --git a/src/ruby/qps/src/proto/grpc/testing/payloads.rb b/src/ruby/qps/src/proto/grpc/testing/payloads_pb.rb
index ae8855f685..ae8855f685 100644
--- a/src/ruby/qps/src/proto/grpc/testing/payloads.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/payloads_pb.rb
diff --git a/src/ruby/qps/src/proto/grpc/testing/services.rb b/src/ruby/qps/src/proto/grpc/testing/services_pb.rb
index b2675c2afe..5ce13bf8b0 100644
--- a/src/ruby/qps/src/proto/grpc/testing/services.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/services_pb.rb
@@ -3,8 +3,8 @@
require 'google/protobuf'
-require 'src/proto/grpc/testing/messages'
-require 'src/proto/grpc/testing/control'
+require 'src/proto/grpc/testing/messages_pb'
+require 'src/proto/grpc/testing/control_pb'
Google::Protobuf::DescriptorPool.generated_pool.build do
end
diff --git a/src/ruby/qps/src/proto/grpc/testing/services_services.rb b/src/ruby/qps/src/proto/grpc/testing/services_services_pb.rb
index 94b9a1e164..bdbb9c86d0 100644
--- a/src/ruby/qps/src/proto/grpc/testing/services_services.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/services_services_pb.rb
@@ -34,7 +34,7 @@
# of unary/streaming requests/responses.
require 'grpc'
-require 'src/proto/grpc/testing/services'
+require 'src/proto/grpc/testing/services_pb'
module Grpc
module Testing
diff --git a/src/ruby/qps/src/proto/grpc/testing/stats.rb b/src/ruby/qps/src/proto/grpc/testing/stats_pb.rb
index 41f75bedf0..41f75bedf0 100644
--- a/src/ruby/qps/src/proto/grpc/testing/stats.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/stats_pb.rb
diff --git a/src/ruby/qps/worker.rb b/src/ruby/qps/worker.rb
index 665fb86352..12b8087ca0 100755
--- a/src/ruby/qps/worker.rb
+++ b/src/ruby/qps/worker.rb
@@ -44,7 +44,7 @@ require 'facter'
require 'client'
require 'qps-common'
require 'server'
-require 'src/proto/grpc/testing/services_services'
+require 'src/proto/grpc/testing/services_services_pb'
class WorkerServiceImpl < Grpc::Testing::WorkerService::Service
def cpu_cores
diff --git a/src/ruby/spec/generic/active_call_spec.rb b/src/ruby/spec/generic/active_call_spec.rb
index 018580e0df..48bc61e494 100644
--- a/src/ruby/spec/generic/active_call_spec.rb
+++ b/src/ruby/spec/generic/active_call_spec.rb
@@ -60,8 +60,10 @@ describe GRPC::ActiveCall do
end
describe '#multi_req_view' do
- it 'exposes a fixed subset of the ActiveCall methods' do
- want = %w(cancelled?, deadline, each_remote_read, metadata, shutdown)
+ it 'exposes a fixed subset of the ActiveCall.methods' do
+ want = %w(cancelled?, deadline, each_remote_read, metadata, \
+ shutdown, peer, peer_cert, send_initial_metadata, \
+ initial_metadata_sent)
v = @client_call.multi_req_view
want.each do |w|
expect(v.methods.include?(w))
@@ -70,8 +72,10 @@ describe GRPC::ActiveCall do
end
describe '#single_req_view' do
- it 'exposes a fixed subset of the ActiveCall methods' do
- want = %w(cancelled?, deadline, metadata, shutdown)
+ it 'exposes a fixed subset of the ActiveCall.methods' do
+ want = %w(cancelled?, deadline, metadata, shutdown, \
+ send_initial_metadata, metadata_to_send, \
+ merge_metadata_to_send, initial_metadata_sent)
v = @client_call.single_req_view
want.each do |w|
expect(v.methods.include?(w))
@@ -149,6 +153,146 @@ describe GRPC::ActiveCall do
end
end
+ describe 'sending initial metadata', send_initial_metadata: true do
+ it 'sends metadata before sending a message if it hasnt been sent yet' do
+ call = make_test_call
+ @client_call = ActiveCall.new(
+ call,
+ @pass_through,
+ @pass_through,
+ deadline,
+ started: false)
+
+ metadata = { key: 'dummy_val', other: 'other_val' }
+ expect(@client_call.metadata_sent).to eq(false)
+ @client_call.merge_metadata_to_send(metadata)
+
+ message = 'dummy message'
+
+ expect(call).to(
+ receive(:run_batch)
+ .with(
+ hash_including(
+ CallOps::SEND_INITIAL_METADATA => metadata)).once)
+
+ expect(call).to(
+ receive(:run_batch).with(hash_including(
+ CallOps::SEND_MESSAGE => message)).once)
+ @client_call.remote_send(message)
+
+ expect(@client_call.metadata_sent).to eq(true)
+ end
+
+ it 'doesnt send metadata if it thinks its already been sent' do
+ call = make_test_call
+
+ @client_call = ActiveCall.new(call,
+ @pass_through,
+ @pass_through,
+ deadline)
+
+ expect(@client_call.metadata_sent).to eql(true)
+ expect(call).to(
+ receive(:run_batch).with(hash_including(
+ CallOps::SEND_INITIAL_METADATA)).never)
+
+ @client_call.remote_send('test message')
+ end
+
+ it 'sends metadata if it is explicitly sent and ok to do so' do
+ call = make_test_call
+
+ @client_call = ActiveCall.new(call,
+ @pass_through,
+ @pass_through,
+ deadline,
+ started: false)
+
+ expect(@client_call.metadata_sent).to eql(false)
+
+ metadata = { test_key: 'val' }
+ @client_call.merge_metadata_to_send(metadata)
+ expect(@client_call.metadata_to_send).to eq(metadata)
+
+ expect(call).to(
+ receive(:run_batch).with(hash_including(
+ CallOps::SEND_INITIAL_METADATA =>
+ metadata)).once)
+ @client_call.send_initial_metadata
+ end
+
+ it 'explicit sending does nothing if metadata has already been sent' do
+ call = make_test_call
+
+ @client_call = ActiveCall.new(call,
+ @pass_through,
+ @pass_through,
+ deadline)
+
+ expect(@client_call.metadata_sent).to eql(true)
+
+ blk = proc do
+ @client_call.send_initial_metadata
+ end
+
+ expect { blk.call }.to_not raise_error
+ end
+ end
+
+ describe '#merge_metadata_to_send', merge_metadata_to_send: true do
+ it 'adds to existing metadata when there is existing metadata to send' do
+ call = make_test_call
+ starting_metadata = {
+ k1: 'key1_val',
+ k2: 'key2_val',
+ k3: 'key3_val'
+ }
+
+ @client_call = ActiveCall.new(
+ call,
+ @pass_through, @pass_through,
+ deadline,
+ started: false,
+ metadata_to_send: starting_metadata)
+
+ expect(@client_call.metadata_to_send).to eq(starting_metadata)
+
+ @client_call.merge_metadata_to_send(
+ k3: 'key3_new_val',
+ k4: 'key4_val')
+
+ expected_md_to_send = {
+ k1: 'key1_val',
+ k2: 'key2_val',
+ k3: 'key3_new_val',
+ k4: 'key4_val' }
+
+ expect(@client_call.metadata_to_send).to eq(expected_md_to_send)
+
+ @client_call.merge_metadata_to_send(k5: 'key5_val')
+ expected_md_to_send.merge!(k5: 'key5_val')
+ expect(@client_call.metadata_to_send).to eq(expected_md_to_send)
+ end
+
+ it 'fails when initial metadata has already been sent' do
+ call = make_test_call
+ @client_call = ActiveCall.new(
+ call,
+ @pass_through,
+ @pass_through,
+ deadline,
+ started: true)
+
+ expect(@client_call.metadata_sent).to eq(true)
+
+ blk = proc do
+ @client_call.merge_metadata_to_send(k1: 'key1_val')
+ end
+
+ expect { blk.call }.to raise_error
+ end
+ end
+
describe '#client_invoke' do
it 'sends metadata to the server when present' do
call = make_test_call
@@ -163,7 +307,26 @@ describe GRPC::ActiveCall do
end
end
- describe '#remote_read' do
+ describe '#send_status', send_status: true do
+ it 'works when no metadata or messages have been sent yet' do
+ call = make_test_call
+ ActiveCall.client_invoke(call)
+
+ recvd_rpc = @server.request_call
+ server_call = ActiveCall.new(
+ recvd_rpc.call,
+ @pass_through,
+ @pass_through,
+ deadline,
+ started: false)
+
+ expect(server_call.metadata_sent).to eq(false)
+ blk = proc { server_call.send_status(OK) }
+ expect { blk.call }.to_not raise_error
+ end
+ end
+
+ describe '#remote_read', remote_read: true do
it 'reads the response sent by a server' do
call = make_test_call
ActiveCall.client_invoke(call)
@@ -205,6 +368,31 @@ describe GRPC::ActiveCall do
expect(client_call.metadata).to eq(expected)
end
+ it 'get a status from server when nothing else sent from server' do
+ client_call = make_test_call
+ ActiveCall.client_invoke(client_call)
+
+ recvd_rpc = @server.request_call
+ recvd_call = recvd_rpc.call
+
+ server_call = ActiveCall.new(
+ recvd_call,
+ @pass_through,
+ @pass_through,
+ deadline,
+ started: false)
+
+ server_call.send_status(OK, 'OK')
+
+ # Check that we can receive initial metadata and a status
+ client_call.run_batch(
+ CallOps::RECV_INITIAL_METADATA => nil)
+ batch_result = client_call.run_batch(
+ CallOps::RECV_STATUS_ON_CLIENT => nil)
+
+ expect(batch_result.status.code).to eq(OK)
+ end
+
it 'get a nil msg before a status when an OK status is sent' do
call = make_test_call
ActiveCall.client_invoke(call)
@@ -329,6 +517,86 @@ describe GRPC::ActiveCall do
end
end
+ # Test sending of the initial metadata in #run_server_bidi
+ # from the server handler both implicitly and explicitly.
+ describe '#run_server_bidi metadata sending tests', run_server_bidi: true do
+ before(:each) do
+ @requests = ['first message', 'second message']
+ @server_to_client_metadata = { 'test_key' => 'test_val' }
+ @server_status = OK
+
+ @client_call = make_test_call
+ @client_call.run_batch(CallOps::SEND_INITIAL_METADATA => {})
+
+ recvd_rpc = @server.request_call
+ recvd_call = recvd_rpc.call
+ @server_call = ActiveCall.new(
+ recvd_call,
+ @pass_through,
+ @pass_through,
+ deadline,
+ metadata_received: true,
+ started: false,
+ metadata_to_send: @server_to_client_metadata)
+ end
+
+ after(:each) do
+ # Send the requests and send a close so the server can send a status
+ @requests.each do |message|
+ @client_call.run_batch(CallOps::SEND_MESSAGE => message)
+ end
+ @client_call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
+
+ @server_thread.join
+
+ # Expect that initial metadata was sent,
+ # the requests were echoed, and a status was sent
+ batch_result = @client_call.run_batch(
+ CallOps::RECV_INITIAL_METADATA => nil)
+ expect(batch_result.metadata).to eq(@server_to_client_metadata)
+
+ @requests.each do |message|
+ batch_result = @client_call.run_batch(
+ CallOps::RECV_MESSAGE => nil)
+ expect(batch_result.message).to eq(message)
+ end
+
+ batch_result = @client_call.run_batch(
+ CallOps::RECV_STATUS_ON_CLIENT => nil)
+ expect(batch_result.status.code).to eq(@server_status)
+ end
+
+ it 'sends the initial metadata implicitly if not already sent' do
+ # Server handler that doesn't have access to a "call"
+ # It echoes the requests
+ fake_gen_each_reply_with_no_call_param = proc do |msgs|
+ msgs
+ end
+
+ @server_thread = Thread.new do
+ @server_call.run_server_bidi(
+ fake_gen_each_reply_with_no_call_param)
+ @server_call.send_status(@server_status)
+ end
+ end
+
+ it 'sends the metadata when sent explicitly and not already sent' do
+ # Fake server handler that has access to a "call" object and
+ # uses it to explicitly update and send the initial metadata
+ fake_gen_each_reply_with_call_param = proc do |msgs, call_param|
+ call_param.merge_metadata_to_send(@server_to_client_metadata)
+ call_param.send_initial_metadata
+ msgs
+ end
+
+ @server_thread = Thread.new do
+ @server_call.run_server_bidi(
+ fake_gen_each_reply_with_call_param)
+ @server_call.send_status(@server_status)
+ end
+ end
+ end
+
def expect_server_to_receive(sent_text, **kw)
c = expect_server_to_be_invoked(**kw)
expect(c.remote_read).to eq(sent_text)
diff --git a/src/ruby/spec/generic/rpc_desc_spec.rb b/src/ruby/spec/generic/rpc_desc_spec.rb
index d2080b7ca2..1a895005bc 100644
--- a/src/ruby/spec/generic/rpc_desc_spec.rb
+++ b/src/ruby/spec/generic/rpc_desc_spec.rb
@@ -196,6 +196,9 @@ describe GRPC::RpcDesc do
def fake_svstream(_arg1, _arg2)
end
+ def fake_three_args(_arg1, _arg2, _arg3)
+ end
+
it 'raises when a request_response does not have 2 args' do
[:fake_clstream, :no_arg].each do |mth|
blk = proc do
@@ -244,8 +247,8 @@ describe GRPC::RpcDesc do
expect(&blk).to_not raise_error
end
- it 'raises when a bidi streamer does not have 1 arg' do
- [:fake_svstream, :no_arg].each do |mth|
+ it 'raises when a bidi streamer does not have 1 or 2 args' do
+ [:fake_three_args, :no_arg].each do |mth|
blk = proc do
@bidi_streamer.assert_arity_matches(method(mth))
end
@@ -259,6 +262,13 @@ describe GRPC::RpcDesc do
end
expect(&blk).to_not raise_error
end
+
+ it 'passes when a bidi streamer has 2 args' do
+ blk = proc do
+ @bidi_streamer.assert_arity_matches(method(:fake_svstream))
+ end
+ expect(&blk).to_not raise_error
+ end
end
describe '#request_response?' do
diff --git a/src/ruby/spec/pb/duplicate/codegen_spec.rb b/src/ruby/spec/pb/duplicate/codegen_spec.rb
index 54c136c510..ea0240965c 100644
--- a/src/ruby/spec/pb/duplicate/codegen_spec.rb
+++ b/src/ruby/spec/pb/duplicate/codegen_spec.rb
@@ -44,7 +44,7 @@ describe 'Ping protobuf code generation' do
# Get the current content
service_path = File.join(root_dir, 'src', 'ruby', 'pb', 'grpc',
'testing', 'duplicate',
- 'echo_duplicate_services.rb')
+ 'echo_duplicate_services_pb.rb')
want = nil
File.open(service_path) { |f| want = f.read }
@@ -54,7 +54,7 @@ describe 'Ping protobuf code generation' do
got = nil
Dir.mktmpdir do |tmp_dir|
gen_out = File.join(tmp_dir, 'src', 'proto', 'grpc', 'testing',
- 'duplicate', 'echo_duplicate_services.rb')
+ 'duplicate', 'echo_duplicate_services_pb.rb')
pid = spawn(
'protoc',
'-I.',
diff --git a/src/ruby/spec/pb/health/checker_spec.rb b/src/ruby/spec/pb/health/checker_spec.rb
index de11c9fedf..1b2fa96827 100644
--- a/src/ruby/spec/pb/health/checker_spec.rb
+++ b/src/ruby/spec/pb/health/checker_spec.rb
@@ -28,7 +28,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc'
-require 'grpc/health/v1/health'
+require 'grpc/health/v1/health_pb'
require 'grpc/health/checker'
require 'open3'
require 'tmpdir'
@@ -43,7 +43,7 @@ describe 'Health protobuf code generation' do
skip 'protoc || grpc_ruby_plugin missing, cannot verify health code-gen'
else
it 'should already be loaded indirectly i.e, used by the other specs' do
- expect(require('grpc/health/v1/health_services')).to be(false)
+ expect(require('grpc/health/v1/health_services_pb')).to be(false)
end
it 'should have the same content as created by code generation' do
@@ -52,7 +52,7 @@ describe 'Health protobuf code generation' do
# Get the current content
service_path = File.join(root_dir, 'ruby', 'pb', 'grpc',
- 'health', 'v1', 'health_services.rb')
+ 'health', 'v1', 'health_services_pb.rb')
want = nil
File.open(service_path) { |f| want = f.read }
@@ -62,7 +62,7 @@ describe 'Health protobuf code generation' do
got = nil
Dir.mktmpdir do |tmp_dir|
gen_out = File.join(tmp_dir, 'grpc', 'health', 'v1',
- 'health_services.rb')
+ 'health_services_pb.rb')
pid = spawn(
'protoc',
'-I.',
diff --git a/src/ruby/stress/metrics_server.rb b/src/ruby/stress/metrics_server.rb
index 13638c4d21..2b7f78577d 100644
--- a/src/ruby/stress/metrics_server.rb
+++ b/src/ruby/stress/metrics_server.rb
@@ -27,8 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-require_relative '../pb/grpc/testing/metrics.rb'
-require_relative '../pb/grpc/testing/metrics_services.rb'
+require_relative '../pb/grpc/testing/metrics_pb.rb'
+require_relative '../pb/grpc/testing/metrics_services_pb.rb'
class Gauge
def get_name
diff --git a/src/ruby/tools/bin/grpc_tools_ruby_protoc b/src/ruby/tools/bin/grpc_tools_ruby_protoc
new file mode 100755
index 0000000000..dab06e7958
--- /dev/null
+++ b/src/ruby/tools/bin/grpc_tools_ruby_protoc
@@ -0,0 +1,48 @@
+#!/usr/bin/env ruby
+# Copyright 2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+require 'rbconfig'
+
+require_relative '../os_check'
+
+ext = RbConfig::CONFIG['EXEEXT']
+
+protoc_name = 'protoc' + ext
+
+plugin_name = 'grpc_ruby_plugin' + ext
+
+protoc_dir = File.join(File.dirname(__FILE__),
+ RbConfig::CONFIG['host_cpu'] + '-' + OS.os_name)
+
+protoc_path = File.join(protoc_dir, protoc_name)
+
+plugin_path = File.join(protoc_dir, plugin_name)
+
+exec([ protoc_path, protoc_path ], "--plugin=protoc-gen-grpc=#{plugin_path}", *ARGV)
diff --git a/src/ruby/tools/bin/grpc_tools_ruby_protoc_plugin.rb b/src/ruby/tools/bin/grpc_tools_ruby_protoc_plugin
index 4b296dedc7..4b296dedc7 100755
--- a/src/ruby/tools/bin/grpc_tools_ruby_protoc_plugin.rb
+++ b/src/ruby/tools/bin/grpc_tools_ruby_protoc_plugin
diff --git a/src/ruby/tools/grpc-tools.gemspec b/src/ruby/tools/grpc-tools.gemspec
index 9fa4b66392..68e2a7a113 100644
--- a/src/ruby/tools/grpc-tools.gemspec
+++ b/src/ruby/tools/grpc-tools.gemspec
@@ -18,5 +18,5 @@ Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
- s.executables = %w( grpc_tools_ruby_protoc.rb grpc_tools_ruby_protoc_plugin.rb )
+ s.executables = %w( grpc_tools_ruby_protoc grpc_tools_ruby_protoc_plugin )
end