Imported Upstream version 1.30.0 upstream/1.30.0
authorDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 23 Sep 2020 01:40:46 +0000 (10:40 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 23 Sep 2020 01:40:46 +0000 (10:40 +0900)
882 files changed:
.bazelci/presubmit.yml [new file with mode: 0644]
.github/ISSUE_TEMPLATE/bug_report.md
.github/ISSUE_TEMPLATE/cleanup_request.md
.github/ISSUE_TEMPLATE/feature_request.md
.github/ISSUE_TEMPLATE/question.md [new file with mode: 0644]
.github/pull_request_template.md
.github/stale.yml
.gitignore
.gitmodules
BUILD
BUILD.gn
BUILDING.md
CMakeLists.txt
CONTRIBUTING.md
Makefile
Rakefile
WORKSPACE
bazel/grpc_deps.bzl
bazel/update_mirror.sh [new file with mode: 0755]
build_autogenerated.yaml
build_handwritten.yaml
config.m4
config.w32
doc/PROTOCOL-HTTP2.md
doc/command_line_tool.md
doc/compression.md
doc/g_stands_for.md
doc/keepalive.md
doc/python/sphinx/conf.py
doc/python/sphinx/glossary.rst
doc/unit_testing.md
doc/xds-test-descriptions.md
examples/cpp/route_guide/README.md
examples/csharp/RouteGuide/RouteGuide/RouteGuide.csproj
examples/csharp/RouteGuide/RouteGuide/RouteGuideUtil.cs
examples/csharp/RouteGuide/RouteGuideClient/Program.cs
examples/csharp/RouteGuide/RouteGuideServer/Program.cs
examples/csharp/Xds/Greeter.sln [new file with mode: 0644]
examples/csharp/Xds/Greeter/Greeter.csproj [new file with mode: 0644]
examples/csharp/Xds/GreeterClient/GreeterClient.csproj [new file with mode: 0644]
examples/csharp/Xds/GreeterClient/Program.cs [new file with mode: 0644]
examples/csharp/Xds/GreeterServer/GreeterServer.csproj [new file with mode: 0644]
examples/csharp/Xds/GreeterServer/Program.cs [new file with mode: 0644]
examples/csharp/Xds/README.md [new file with mode: 0644]
examples/php/composer.json
examples/php/greeter_client.php
examples/php/greeter_proto_gen.sh
examples/python/data_transmission/BUILD [new file with mode: 0644]
examples/python/data_transmission/alts_client.py [new file with mode: 0644]
examples/python/data_transmission/alts_server.py [new file with mode: 0644]
examples/python/data_transmission/client.py
examples/python/data_transmission/server.py
examples/python/xds/README.md
examples/python/xds/client.py [new file with mode: 0644]
examples/python/xds/requirements.txt
examples/ruby/greeter_client.rb
gRPC-C++.podspec
gRPC-Core.podspec
gRPC-ProtoRPC.podspec
gRPC-RxLibrary.podspec
gRPC.podspec
grpc.gemspec
grpc.gyp
include/grpc/grpc_security_constants.h
include/grpc/impl/codegen/grpc_types.h
include/grpc/impl/codegen/port_platform.h
include/grpcpp/impl/codegen/call_op_set.h
include/grpcpp/impl/codegen/interceptor.h
include/grpcpp/impl/codegen/interceptor_common.h
include/grpcpp/security/tls_credentials_options.h
include/grpcpp/server_builder_impl.h
include/grpcpp/server_impl.h
package.xml
requirements.bazel.txt
setup.py
src/android/test/interop/app/CMakeLists.txt
src/boringssl/boringssl_prefix_symbols.h
src/compiler/cpp_plugin.h
src/compiler/csharp_plugin.cc
src/compiler/node_plugin.cc
src/compiler/objective_c_plugin.cc
src/compiler/php_generator.cc
src/compiler/php_plugin.cc
src/compiler/python_generator.cc
src/compiler/python_generator.h
src/compiler/ruby_generator_string-inl.h
src/compiler/ruby_plugin.cc
src/core/ext/filters/client_channel/backend_metric.cc
src/core/ext/filters/client_channel/client_channel.cc
src/core/ext/filters/client_channel/client_channel_plugin.cc
src/core/ext/filters/client_channel/health/health_check_client.cc
src/core/ext/filters/client_channel/health/health_check_client.h
src/core/ext/filters/client_channel/http_proxy.cc
src/core/ext/filters/client_channel/lb_policy.cc
src/core/ext/filters/client_channel/lb_policy.h
src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
src/core/ext/filters/client_channel/lb_policy_registry.cc
src/core/ext/filters/client_channel/local_subchannel_pool.h
src/core/ext/filters/client_channel/parse_address.cc
src/core/ext/filters/client_channel/resolver.cc
src/core/ext/filters/client_channel/resolver.h
src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc
src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h
src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
src/core/ext/filters/client_channel/resolver_factory.h
src/core/ext/filters/client_channel/resolver_registry.cc
src/core/ext/filters/client_channel/resolver_registry.h
src/core/ext/filters/client_channel/resolver_result_parsing.cc
src/core/ext/filters/client_channel/resolver_result_parsing.h
src/core/ext/filters/client_channel/resolving_lb_policy.cc
src/core/ext/filters/client_channel/resolving_lb_policy.h
src/core/ext/filters/client_channel/server_address.h
src/core/ext/filters/client_channel/service_config.cc
src/core/ext/filters/client_channel/service_config.h
src/core/ext/filters/client_channel/service_config_call_data.h [new file with mode: 0644]
src/core/ext/filters/client_channel/service_config_parser.cc [new file with mode: 0644]
src/core/ext/filters/client_channel/service_config_parser.h [new file with mode: 0644]
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel.h
src/core/ext/filters/client_channel/xds/xds_api.cc
src/core/ext/filters/client_channel/xds/xds_api.h
src/core/ext/filters/client_channel/xds/xds_bootstrap.cc
src/core/ext/filters/client_channel/xds/xds_bootstrap.h
src/core/ext/filters/client_channel/xds/xds_channel_secure.cc
src/core/ext/filters/client_channel/xds/xds_client.cc
src/core/ext/filters/client_channel/xds/xds_client.h
src/core/ext/filters/client_channel/xds/xds_client_stats.cc
src/core/ext/filters/client_channel/xds/xds_client_stats.h
src/core/ext/filters/http/client/http_client_filter.cc
src/core/ext/filters/http/client_authority_filter.cc
src/core/ext/filters/http/http_filters_plugin.cc
src/core/ext/filters/message_size/message_size_filter.cc
src/core/ext/filters/message_size/message_size_filter.h
src/core/ext/transport/chttp2/server/chttp2_server.cc
src/core/ext/transport/chttp2/transport/bin_encoder.cc
src/core/ext/transport/chttp2/transport/chttp2_transport.cc
src/core/ext/transport/chttp2/transport/frame_goaway.h
src/core/ext/transport/chttp2/transport/frame_ping.h
src/core/ext/transport/chttp2/transport/frame_rst_stream.h
src/core/ext/transport/chttp2/transport/frame_settings.h
src/core/ext/transport/chttp2/transport/frame_window_update.h
src/core/ext/transport/chttp2/transport/hpack_encoder.cc
src/core/ext/transport/chttp2/transport/hpack_encoder.h
src/core/ext/transport/chttp2/transport/hpack_parser.h
src/core/ext/transport/chttp2/transport/hpack_table.h
src/core/ext/transport/chttp2/transport/http2_settings.h
src/core/ext/transport/chttp2/transport/huffsyms.h
src/core/ext/transport/chttp2/transport/internal.h
src/core/ext/transport/chttp2/transport/stream_map.h
src/core/ext/transport/chttp2/transport/writing.cc
src/core/ext/transport/inproc/inproc_transport.cc
src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c
src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h
src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/cds.upb.c
src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c
src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h
src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c
src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c
src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c
src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c
src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c
src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h
src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c
src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c
src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c
src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h
src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c
src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c
src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h
src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h [new file with mode: 0644]
src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c
src/core/ext/upb-generated/envoy/api/v2/eds.upb.c
src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c
src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c
src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c
src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h
src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c
src/core/ext/upb-generated/envoy/api/v2/lds.upb.c
src/core/ext/upb-generated/envoy/api/v2/listener.upb.c
src/core/ext/upb-generated/envoy/api/v2/listener.upb.h
src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c
src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c
src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c
src/core/ext/upb-generated/envoy/api/v2/rds.upb.c
src/core/ext/upb-generated/envoy/api/v2/route.upb.c
src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c
src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c
src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h
src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c
src/core/ext/upb-generated/envoy/api/v2/srds.upb.c
src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c
src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c
src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h
src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c
src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h [new file with mode: 0644]
src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c
src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c
src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h
src/core/ext/upb-generated/envoy/type/http.upb.c
src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c
src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h
src/core/ext/upb-generated/envoy/type/matcher/string.upb.c
src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c
src/core/ext/upb-generated/envoy/type/percent.upb.c
src/core/ext/upb-generated/envoy/type/range.upb.c
src/core/ext/upb-generated/envoy/type/semantic_version.upb.c
src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c
src/core/ext/upb-generated/google/protobuf/descriptor.upb.c
src/core/ext/upb-generated/google/protobuf/descriptor.upb.h
src/core/ext/upb-generated/udpa/annotations/status.upb.c [new file with mode: 0644]
src/core/ext/upb-generated/udpa/annotations/status.upb.h [new file with mode: 0644]
src/core/ext/upb-generated/validate/validate.upb.c
src/core/ext/upb-generated/validate/validate.upb.h
src/core/lib/channel/channel_args.cc
src/core/lib/channel/channel_args.h
src/core/lib/channel/channel_stack.h
src/core/lib/channel/channelz.cc
src/core/lib/channel/channelz.h
src/core/lib/channel/channelz_registry.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/context.h
src/core/lib/channel/handshaker.cc
src/core/lib/channel/handshaker.h
src/core/lib/channel/handshaker_registry.cc
src/core/lib/channel/status_util.cc
src/core/lib/compression/message_compress.cc
src/core/lib/debug/stats.cc
src/core/lib/debug/stats.h
src/core/lib/gpr/spinlock.h
src/core/lib/gpr/string.cc
src/core/lib/gpr/string.h
src/core/lib/gpr/sync_abseil.cc
src/core/lib/gpr/time.cc
src/core/lib/gprpp/atomic.h
src/core/lib/gprpp/host_port.cc
src/core/lib/gprpp/host_port.h
src/core/lib/gprpp/inlined_vector.h [deleted file]
src/core/lib/gprpp/map.h
src/core/lib/gprpp/ref_counted_ptr.h
src/core/lib/gprpp/string_view.h [deleted file]
src/core/lib/http/format_request.cc
src/core/lib/http/httpcli.cc
src/core/lib/http/httpcli.h
src/core/lib/http/httpcli_security_connector.cc
src/core/lib/http/parser.h
src/core/lib/iomgr/buffer_list.h
src/core/lib/iomgr/call_combiner.h
src/core/lib/iomgr/closure.h
src/core/lib/iomgr/endpoint_cfstream.cc
src/core/lib/iomgr/endpoint_pair.h
src/core/lib/iomgr/error.cc
src/core/lib/iomgr/error.h
src/core/lib/iomgr/ev_epoll1_linux.cc
src/core/lib/iomgr/ev_epollex_linux.cc
src/core/lib/iomgr/ev_posix.cc
src/core/lib/iomgr/exec_ctx.h
src/core/lib/iomgr/resolve_address.h
src/core/lib/iomgr/resolve_address_custom.cc
src/core/lib/iomgr/resolve_address_custom.h
src/core/lib/iomgr/resolve_address_posix.cc
src/core/lib/iomgr/resolve_address_windows.cc
src/core/lib/iomgr/resource_quota.cc
src/core/lib/iomgr/sockaddr_utils.cc
src/core/lib/iomgr/sockaddr_utils.h
src/core/lib/iomgr/socket_factory_posix.h
src/core/lib/iomgr/socket_mutator.h
src/core/lib/iomgr/socket_utils_common_posix.cc
src/core/lib/iomgr/tcp_client_cfstream.cc
src/core/lib/iomgr/tcp_client_posix.cc
src/core/lib/iomgr/tcp_client_windows.cc
src/core/lib/iomgr/tcp_custom.cc
src/core/lib/iomgr/tcp_server_custom.cc
src/core/lib/iomgr/tcp_server_posix.cc
src/core/lib/iomgr/tcp_server_utils_posix_common.cc
src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc
src/core/lib/iomgr/tcp_uv.cc
src/core/lib/iomgr/time_averaged_stats.h
src/core/lib/iomgr/timer_generic.cc
src/core/lib/iomgr/timer_heap.h
src/core/lib/iomgr/udp_server.cc
src/core/lib/json/json.h
src/core/lib/json/json_reader.cc
src/core/lib/json/json_writer.cc
src/core/lib/security/credentials/composite/composite_credentials.h
src/core/lib/security/credentials/credentials.h
src/core/lib/security/credentials/google_default/google_default_credentials.cc
src/core/lib/security/credentials/jwt/json_token.h
src/core/lib/security/credentials/jwt/jwt_verifier.cc
src/core/lib/security/credentials/jwt/jwt_verifier.h
src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
src/core/lib/security/credentials/oauth2/oauth2_credentials.h
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h
src/core/lib/security/security_connector/alts/alts_security_connector.cc
src/core/lib/security/security_connector/fake/fake_security_connector.cc
src/core/lib/security/security_connector/load_system_roots_linux.cc
src/core/lib/security/security_connector/local/local_security_connector.cc
src/core/lib/security/security_connector/security_connector.h
src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
src/core/lib/security/security_connector/ssl/ssl_security_connector.h
src/core/lib/security/security_connector/ssl_utils.cc
src/core/lib/security/security_connector/ssl_utils.h
src/core/lib/security/security_connector/tls/tls_security_connector.cc
src/core/lib/security/security_connector/tls/tls_security_connector.h
src/core/lib/security/transport/client_auth_filter.cc
src/core/lib/slice/slice_intern.cc
src/core/lib/slice/slice_utils.h
src/core/lib/surface/call.cc
src/core/lib/surface/call_log_batch.cc
src/core/lib/surface/channel.cc
src/core/lib/surface/channel_ping.cc
src/core/lib/surface/completion_queue.cc
src/core/lib/surface/event_string.cc
src/core/lib/surface/event_string.h
src/core/lib/surface/server.cc
src/core/lib/surface/server.h
src/core/lib/surface/version.cc
src/core/lib/transport/connectivity_state.cc
src/core/lib/transport/connectivity_state.h
src/core/lib/transport/metadata_batch.h
src/core/lib/transport/status_conversion.cc
src/core/lib/transport/transport.cc
src/core/lib/transport/transport.h
src/core/lib/transport/transport_op_string.cc
src/core/lib/uri/uri_parser.h
src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h
src/core/tsi/fake_transport_security.cc
src/core/tsi/ssl_transport_security.cc
src/core/tsi/ssl_transport_security.h
src/core/tsi/transport_security.h
src/core/tsi/transport_security_grpc.h
src/core/tsi/transport_security_interface.h
src/cpp/Protobuf-C++.podspec
src/cpp/README.md
src/cpp/common/tls_credentials_options.cc
src/cpp/common/tls_credentials_options_util.cc
src/cpp/common/version_cc.cc
src/cpp/server/server_cc.cc
src/csharp/BUILD-INTEGRATION.md
src/csharp/Grpc.Core.Api/IAsyncStreamWriter.cs
src/csharp/Grpc.Core.Api/Metadata.cs
src/csharp/Grpc.Core.Api/Status.cs
src/csharp/Grpc.Core.Api/VersionInfo.cs
src/csharp/Grpc.Core.Tests/ClientServerTest.cs
src/csharp/Grpc.Core.Tests/MetadataTest.cs
src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
src/csharp/Grpc.Core/Internal/CoreErrorDetailException.cs [new file with mode: 0644]
src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs
src/csharp/Grpc.Core/SourceLink.csproj.include
src/csharp/Grpc.Core/build/net45/Grpc.Core.targets
src/csharp/Grpc.IntegrationTesting.XdsClient/.gitignore [new file with mode: 0644]
src/csharp/Grpc.IntegrationTesting.XdsClient/Grpc.IntegrationTesting.XdsClient.csproj [new file with mode: 0755]
src/csharp/Grpc.IntegrationTesting.XdsClient/Program.cs [new file with mode: 0644]
src/csharp/Grpc.IntegrationTesting.XdsClient/Properties/AssemblyInfo.cs [new file with mode: 0644]
src/csharp/Grpc.IntegrationTesting/XdsInteropClient.cs [new file with mode: 0644]
src/csharp/Grpc.IntegrationTesting/XdsInteropClientTest.cs [new file with mode: 0644]
src/csharp/Grpc.Tools.Tests/CppGeneratorTest.cs
src/csharp/Grpc.Tools/GeneratorServices.cs
src/csharp/Grpc.Tools/build/_protobuf/Google.Protobuf.Tools.targets
src/csharp/Grpc.sln
src/csharp/build/dependencies.props
src/csharp/build_unitypackage.bat
src/csharp/ext/grpc_csharp_ext.c
src/csharp/generate_proto_csharp.sh
src/csharp/tests.json
src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/grpc_csharp_ext_dummy_stubs.c
src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec
src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
src/objective-c/!ProtoCompiler.podspec
src/objective-c/BUILD
src/objective-c/BoringSSL-GRPC.podspec
src/objective-c/GRPCClient/GRPCCall.m
src/objective-c/GRPCClient/GRPCTypes.h
src/objective-c/GRPCClient/GRPCTypes.m [moved from src/core/lib/gprpp/optional.h with 63% similarity]
src/objective-c/GRPCClient/version.h
src/objective-c/README-CFSTREAM.md
src/objective-c/tests/CronetTests/CoreCronetEnd2EndTests.mm
src/objective-c/tests/CronetTests/CronetUnitTests.mm
src/objective-c/tests/build_one_example.sh
src/objective-c/tests/version.h
src/php/README.md
src/php/bin/build_all_docker_images.sh
src/php/bin/generate_proto_php.sh
src/php/bin/run_all_docker_images.sh
src/php/bin/run_tests.sh
src/php/composer.json
src/php/docker/README.md
src/php/docker/centos7/Dockerfile [new file with mode: 0644]
src/php/docker/php-future/Dockerfile
src/php/ext/grpc/php_grpc.c
src/php/ext/grpc/version.h
src/php/lib/Grpc/AbstractCall.php
src/php/lib/Grpc/RpcServer.php [new file with mode: 0644]
src/php/tests/generated_code/GPBMetadata/Math.php [new file with mode: 0644]
src/php/tests/generated_code/Math/DivArgs.php [new file with mode: 0644]
src/php/tests/generated_code/Math/DivReply.php [new file with mode: 0644]
src/php/tests/generated_code/Math/FibArgs.php [new file with mode: 0644]
src/php/tests/generated_code/Math/FibReply.php [new file with mode: 0644]
src/php/tests/generated_code/Math/MathClient.php [moved from src/php/tests/qps/generated_code/Grpc/Testing/EchoTestServiceClient.php with 50% similarity]
src/php/tests/generated_code/Math/Num.php [new file with mode: 0644]
src/php/tests/interop/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php [new file with mode: 0644]
src/php/tests/interop/GPBMetadata/Src/Proto/Grpc/Testing/PBEmpty.php [moved from src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/GPBEmpty.php with 69% similarity]
src/php/tests/interop/GPBMetadata/Src/Proto/Grpc/Testing/Test.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/BoolValue.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/EchoStatus.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/EmptyMessage.php [moved from src/php/tests/qps/generated_code/Grpc/Testing/PBEmpty.php with 57% similarity]
src/php/tests/interop/Grpc/Testing/EmptyMessageMessage.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/GrpclbRouteType.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/LoadBalancerStatsRequest.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/LoadBalancerStatsResponse.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceClient.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceStub.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/Payload.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/PayloadType.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/ReconnectInfo.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/ReconnectParams.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/ReconnectServiceClient.php [moved from src/php/tests/qps/generated_code/Grpc/Testing/MetricsServiceClient.php with 61% similarity]
src/php/tests/interop/Grpc/Testing/ResponseParameters.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/SimpleRequest.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/SimpleResponse.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/StreamingInputCallRequest.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/StreamingInputCallResponse.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/StreamingOutputCallRequest.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/StreamingOutputCallResponse.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/TestServiceClient.php [new file with mode: 0644]
src/php/tests/interop/Grpc/Testing/UnimplementedServiceClient.php [moved from src/php/tests/qps/generated_code/Grpc/Testing/UnimplementedEchoServiceClient.php with 66% similarity]
src/php/tests/interop/interop_client.php
src/php/tests/interop/xds_client.php [new file with mode: 0644]
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Core/Stats.php
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/BenchmarkService.php
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/CompilerTest.php
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Echo.php [deleted file]
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/EchoMessages.php
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/EmptyService.php [new file with mode: 0644]
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Metrics.php [deleted file]
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/PBEmpty.php [new file with mode: 0644]
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Payloads.php
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ProxyService.php
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ReportQpsScenarioService.php
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Stats.php
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Test.php
src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/WorkerService.php
src/php/tests/qps/generated_code/Grpc/Core/Bucket.php
src/php/tests/qps/generated_code/Grpc/Core/Histogram.php
src/php/tests/qps/generated_code/Grpc/Core/Metric.php
src/php/tests/qps/generated_code/Grpc/Core/Stats.php
src/php/tests/qps/generated_code/Grpc/Testing/BenchmarkServiceClient.php
src/php/tests/qps/generated_code/Grpc/Testing/BoolValue.php
src/php/tests/qps/generated_code/Grpc/Testing/ByteBufferParams.php
src/php/tests/qps/generated_code/Grpc/Testing/ChannelArg.php
src/php/tests/qps/generated_code/Grpc/Testing/ClientArgs.php
src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php
src/php/tests/qps/generated_code/Grpc/Testing/ClientStats.php
src/php/tests/qps/generated_code/Grpc/Testing/ClientStatus.php
src/php/tests/qps/generated_code/Grpc/Testing/ClientType.php
src/php/tests/qps/generated_code/Grpc/Testing/ClosedLoopParams.php
src/php/tests/qps/generated_code/Grpc/Testing/ComplexProtoParams.php
src/php/tests/qps/generated_code/Grpc/Testing/CoreRequest.php
src/php/tests/qps/generated_code/Grpc/Testing/CoreResponse.php
src/php/tests/qps/generated_code/Grpc/Testing/DebugInfo.php
src/php/tests/qps/generated_code/Grpc/Testing/EchoRequest.php
src/php/tests/qps/generated_code/Grpc/Testing/EchoResponse.php
src/php/tests/qps/generated_code/Grpc/Testing/EchoStatus.php
src/php/tests/qps/generated_code/Grpc/Testing/EmptyMessage.php
src/php/tests/qps/generated_code/Grpc/Testing/EmptyServiceClient.php [moved from src/php/tests/qps/generated_code/Grpc/Testing/NoRpcServiceClient.php with 85% similarity]
src/php/tests/qps/generated_code/Grpc/Testing/ErrorStatus.php
src/php/tests/qps/generated_code/Grpc/Testing/GaugeRequest.php [deleted file]
src/php/tests/qps/generated_code/Grpc/Testing/GaugeResponse.php [deleted file]
src/php/tests/qps/generated_code/Grpc/Testing/GrpclbRouteType.php [new file with mode: 0644]
src/php/tests/qps/generated_code/Grpc/Testing/HistogramData.php
src/php/tests/qps/generated_code/Grpc/Testing/HistogramParams.php
src/php/tests/qps/generated_code/Grpc/Testing/LoadBalancerStatsRequest.php [new file with mode: 0644]
src/php/tests/qps/generated_code/Grpc/Testing/LoadBalancerStatsResponse.php [new file with mode: 0644]
src/php/tests/qps/generated_code/Grpc/Testing/LoadBalancerStatsServiceClient.php [new file with mode: 0644]
src/php/tests/qps/generated_code/Grpc/Testing/LoadParams.php
src/php/tests/qps/generated_code/Grpc/Testing/Mark.php
src/php/tests/qps/generated_code/Grpc/Testing/PBVoid.php
src/php/tests/qps/generated_code/Grpc/Testing/Payload.php
src/php/tests/qps/generated_code/Grpc/Testing/PayloadConfig.php
src/php/tests/qps/generated_code/Grpc/Testing/PayloadType.php
src/php/tests/qps/generated_code/Grpc/Testing/PoissonParams.php
src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php
src/php/tests/qps/generated_code/Grpc/Testing/ProxyStat.php
src/php/tests/qps/generated_code/Grpc/Testing/ReconnectInfo.php
src/php/tests/qps/generated_code/Grpc/Testing/ReconnectParams.php
src/php/tests/qps/generated_code/Grpc/Testing/ReconnectServiceClient.php
src/php/tests/qps/generated_code/Grpc/Testing/ReportQpsScenarioServiceClient.php
src/php/tests/qps/generated_code/Grpc/Testing/Request.php
src/php/tests/qps/generated_code/Grpc/Testing/RequestParams.php
src/php/tests/qps/generated_code/Grpc/Testing/RequestResultCount.php
src/php/tests/qps/generated_code/Grpc/Testing/Response.php
src/php/tests/qps/generated_code/Grpc/Testing/ResponseParameters.php
src/php/tests/qps/generated_code/Grpc/Testing/ResponseParams.php
src/php/tests/qps/generated_code/Grpc/Testing/RpcType.php
src/php/tests/qps/generated_code/Grpc/Testing/Scenario.php
src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResult.php
src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResultSummary.php
src/php/tests/qps/generated_code/Grpc/Testing/Scenarios.php
src/php/tests/qps/generated_code/Grpc/Testing/SecurityParams.php
src/php/tests/qps/generated_code/Grpc/Testing/ServerArgs.php
src/php/tests/qps/generated_code/Grpc/Testing/ServerConfig.php
src/php/tests/qps/generated_code/Grpc/Testing/ServerStats.php
src/php/tests/qps/generated_code/Grpc/Testing/ServerStatus.php
src/php/tests/qps/generated_code/Grpc/Testing/ServerType.php
src/php/tests/qps/generated_code/Grpc/Testing/ServiceAClient.php
src/php/tests/qps/generated_code/Grpc/Testing/ServiceBClient.php
src/php/tests/qps/generated_code/Grpc/Testing/SimpleProtoParams.php
src/php/tests/qps/generated_code/Grpc/Testing/SimpleRequest.php
src/php/tests/qps/generated_code/Grpc/Testing/SimpleResponse.php
src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallRequest.php
src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallResponse.php
src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallRequest.php
src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallResponse.php
src/php/tests/qps/generated_code/Grpc/Testing/TestServiceClient.php
src/php/tests/qps/generated_code/Grpc/Testing/UnimplementedServiceClient.php
src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php
src/proto/grpc/testing/test.proto
src/proto/grpc/testing/xds/lds_rds_for_test.proto
src/proto/grpc/testing/xds/lrs_for_test.proto
src/python/grpcio/README.rst
src/python/grpcio/grpc/__init__.py
src/python/grpcio/grpc/_channel.py
src/python/grpcio/grpc/_common.py
src/python/grpcio/grpc/_cython/_cygrpc/aio/common.pyx.pxi
src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/iomgr.pyx.pxi
src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/resolver.pxd.pxi
src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/resolver.pyx.pxi
src/python/grpcio/grpc/_cython/_cygrpc/aio/server.pxd.pxi
src/python/grpcio/grpc/_cython/_cygrpc/aio/server.pyx.pxi
src/python/grpcio/grpc/_cython/_cygrpc/credentials.pxd.pxi
src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd.pxi
src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx.pxi
src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi
src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pyx.pxi
src/python/grpcio/grpc/_grpcio_metadata.py
src/python/grpcio/grpc/_simple_stubs.py
src/python/grpcio/grpc/experimental/__init__.py
src/python/grpcio/grpc/experimental/aio/__init__.py
src/python/grpcio/grpc/experimental/aio/_base_channel.py
src/python/grpcio/grpc/experimental/aio/_call.py
src/python/grpcio/grpc/experimental/aio/_channel.py
src/python/grpcio/grpc/experimental/aio/_interceptor.py
src/python/grpcio/grpc/experimental/aio/_server.py
src/python/grpcio/grpc/experimental/aio/_typing.py
src/python/grpcio/grpc_core_dependencies.py
src/python/grpcio/grpc_version.py
src/python/grpcio_channelz/grpc_channelz/v1/BUILD.bazel
src/python/grpcio_channelz/grpc_channelz/v1/_async.py [new file with mode: 0644]
src/python/grpcio_channelz/grpc_channelz/v1/_servicer.py [new file with mode: 0644]
src/python/grpcio_channelz/grpc_channelz/v1/channelz.py
src/python/grpcio_channelz/grpc_version.py
src/python/grpcio_health_checking/grpc_version.py
src/python/grpcio_reflection/grpc_reflection/v1alpha/BUILD.bazel
src/python/grpcio_reflection/grpc_reflection/v1alpha/_async.py [new file with mode: 0644]
src/python/grpcio_reflection/grpc_reflection/v1alpha/_base.py [new file with mode: 0644]
src/python/grpcio_reflection/grpc_reflection/v1alpha/reflection.py
src/python/grpcio_reflection/grpc_version.py
src/python/grpcio_status/grpc_status/BUILD.bazel
src/python/grpcio_status/grpc_status/_async.py [new file with mode: 0644]
src/python/grpcio_status/grpc_status/_common.py [new file with mode: 0644]
src/python/grpcio_status/grpc_status/rpc_status.py
src/python/grpcio_status/grpc_version.py
src/python/grpcio_testing/grpc_version.py
src/python/grpcio_tests/grpc_version.py
src/python/grpcio_tests/setup.py
src/python/grpcio_tests/tests/interop/client.py
src/python/grpcio_tests/tests/interop/server.py
src/python/grpcio_tests/tests/unit/_api_test.py
src/python/grpcio_tests/tests/unit/_channel_args_test.py
src/python/grpcio_tests/tests/unit/_metadata_flags_test.py
src/python/grpcio_tests/tests_aio/channelz/BUILD.bazel [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/channelz/__init__.py [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/channelz/channelz_servicer_test.py [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/health_check/health_servicer_test.py
src/python/grpcio_tests/tests_aio/interop/client.py
src/python/grpcio_tests/tests_aio/interop/server.py
src/python/grpcio_tests/tests_aio/reflection/BUILD.bazel [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/reflection/__init__.py [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/reflection/reflection_servicer_test.py [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/status/BUILD.bazel [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/status/__init__.py [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/status/grpc_status_test.py [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/tests.json
src/python/grpcio_tests/tests_aio/unit/_common.py
src/python/grpcio_tests/tests_aio/unit/_test_server.py
src/python/grpcio_tests/tests_aio/unit/call_test.py
src/python/grpcio_tests/tests_aio/unit/channel_ready_test.py
src/python/grpcio_tests/tests_aio/unit/client_stream_stream_interceptor_test.py [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/unit/client_stream_unary_interceptor_test.py [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/unit/client_unary_stream_interceptor_test.py [new file with mode: 0644]
src/python/grpcio_tests/tests_aio/unit/client_unary_unary_interceptor_test.py [moved from src/python/grpcio_tests/tests_aio/unit/client_interceptor_test.py with 100% similarity]
src/python/grpcio_tests/tests_aio/unit/compatibility_test.py
src/python/grpcio_tests/tests_aio/unit/done_callback_test.py
src/python/grpcio_tests/tests_aio/unit/server_interceptor_test.py
src/python/grpcio_tests/tests_py3_only/unit/_leak_test.py [new file with mode: 0644]
src/ruby/ext/grpc/rb_call.c
src/ruby/lib/grpc/errors.rb
src/ruby/lib/grpc/generic/active_call.rb
src/ruby/lib/grpc/generic/interceptors.rb
src/ruby/lib/grpc/generic/rpc_server.rb
src/ruby/lib/grpc/generic/service.rb
src/ruby/lib/grpc/structs.rb
src/ruby/lib/grpc/version.rb
src/ruby/pb/test/xds_client.rb [new file with mode: 0755]
src/ruby/spec/debug_message_spec.rb [new file with mode: 0644]
src/ruby/spec/generic/service_spec.rb
src/ruby/spec/pb/codegen/grpc/testing/package_options_ruby_style.proto
src/ruby/spec/pb/codegen/package_option_spec.rb
src/ruby/tools/version.rb
templates/CMakeLists.txt.template
templates/gRPC-Core.podspec.template
templates/gRPC.podspec.template
templates/grpc.gemspec.template
templates/src/csharp/Grpc.Core/Internal/native_methods.include
templates/src/csharp/build/dependencies.props.template
templates/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec.template
templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.template
templates/src/objective-c/BoringSSL-GRPC.podspec.template
templates/src/php/docker/centos7/Dockerfile.template [new file with mode: 0644]
templates/src/php/docker/php-future/Dockerfile.template
templates/tools/dockerfile/gcp_api_libraries.include
templates/tools/dockerfile/java_build_interop.sh.include
templates/tools/dockerfile/python_debian10.include
templates/tools/dockerfile/python_deps.include
templates/tools/dockerfile/python_stretch.include
templates/tools/dockerfile/test/csharp_stretch_x64/Dockerfile.template
templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template
templates/tools/dockerfile/test/cxx_buster_x64/Dockerfile.template
templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template
templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template
templates/tools/dockerfile/test/cxx_sanitizers_jessie_x64/Dockerfile.template
templates/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile.template
templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template
templates/tools/dockerfile/test/cxx_ubuntu1804_x64/Dockerfile.template
templates/tools/dockerfile/test/fuzzer/Dockerfile.template
templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template
templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template
templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template
templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template
test/core/bad_client/tests/large_metadata.cc
test/core/bad_ssl/bad_ssl_test.cc
test/core/bad_ssl/generate_tests.bzl
test/core/bad_ssl/servers/alpn.cc
test/core/bad_ssl/servers/cert.cc
test/core/channel/BUILD
test/core/channel/channelz_test.cc
test/core/channel/minimal_stack_is_minimal_test.cc
test/core/client_channel/parse_address_with_named_scope_id_test.cc
test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc
test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
test/core/client_channel/resolvers/dns_resolver_test.cc
test/core/client_channel/resolvers/fake_resolver_test.cc
test/core/client_channel/resolvers/sockaddr_resolver_test.cc
test/core/client_channel/service_config_test.cc
test/core/compression/message_compress_test.cc
test/core/end2end/bad_server_response_test.cc
test/core/end2end/connection_refused_test.cc
test/core/end2end/cq_verifier.cc
test/core/end2end/cq_verifier.h
test/core/end2end/data/ssl_test_data.h
test/core/end2end/dualstack_socket_test.cc
test/core/end2end/end2end_nosec_tests.cc
test/core/end2end/end2end_tests.cc
test/core/end2end/fixtures/h2_census.cc
test/core/end2end/fixtures/h2_compress.cc
test/core/end2end/fixtures/h2_fakesec.cc
test/core/end2end/fixtures/h2_full+pipe.cc
test/core/end2end/fixtures/h2_full+trace.cc
test/core/end2end/fixtures/h2_full+workarounds.cc
test/core/end2end/fixtures/h2_full.cc
test/core/end2end/fixtures/h2_http_proxy.cc
test/core/end2end/fixtures/h2_local_ipv4.cc
test/core/end2end/fixtures/h2_local_ipv6.cc
test/core/end2end/fixtures/h2_local_uds.cc
test/core/end2end/fixtures/h2_oauth2.cc
test/core/end2end/fixtures/h2_ssl.cc
test/core/end2end/fixtures/h2_ssl_cred_reload.cc
test/core/end2end/fixtures/h2_tls.cc
test/core/end2end/fixtures/http_proxy_fixture.cc
test/core/end2end/fixtures/local_util.cc
test/core/end2end/fixtures/local_util.h
test/core/end2end/fixtures/proxy.cc
test/core/end2end/fuzzers/client_fuzzer_corpus/error_refcount [new file with mode: 0644]
test/core/end2end/generate_tests.bzl
test/core/end2end/goaway_server_test.cc
test/core/end2end/h2_ssl_cert_test.cc
test/core/end2end/h2_ssl_session_reuse_test.cc
test/core/end2end/invalid_call_argument_test.cc
test/core/end2end/tests/client_streaming.cc [new file with mode: 0644]
test/core/end2end/tests/simple_request.cc
test/core/end2end/tests/streaming_error_response.cc
test/core/fling/fling_stream_test.cc
test/core/fling/fling_test.cc
test/core/fling/server.cc
test/core/gpr/arena_test.cc
test/core/gprpp/BUILD
test/core/gprpp/host_port_test.cc
test/core/gprpp/optional_test.cc [deleted file]
test/core/gprpp/string_view_test.cc [deleted file]
test/core/iomgr/sockaddr_utils_test.cc
test/core/iomgr/tcp_server_posix_test.cc
test/core/json/fuzzer.cc
test/core/security/BUILD
test/core/security/credentials_test.cc
test/core/security/json_token_test.cc
test/core/security/security_connector_test.cc
test/core/security/verify_jwt.cc
test/core/slice/slice_test.cc
test/core/surface/BUILD
test/core/surface/num_external_connectivity_watchers_test.cc
test/core/surface/sequential_connectivity_test.cc
test/core/surface/server_chttp2_test.cc
test/core/surface/server_test.cc
test/core/transport/chttp2/hpack_encoder_test.cc
test/core/transport/status_conversion_test.cc
test/core/tsi/alts/handshaker/alts_concurrent_connectivity_test.cc
test/core/tsi/ssl_transport_security_test.cc
test/core/util/cmdline.cc
test/core/util/cmdline.h
test/core/util/cmdline_test.cc
test/core/util/test_config.cc
test/core/util/test_lb_policies.cc
test/cpp/client/credentials_test.cc
test/cpp/cocoapods/Podfile
test/cpp/end2end/client_callback_end2end_test.cc
test/cpp/end2end/client_interceptors_end2end_test.cc
test/cpp/end2end/client_lb_end2end_test.cc
test/cpp/end2end/grpclb_end2end_test.cc
test/cpp/end2end/interceptors_util.cc
test/cpp/end2end/interceptors_util.h
test/cpp/end2end/xds_end2end_test.cc
test/cpp/interop/client.cc
test/cpp/interop/interop_client.cc
test/cpp/interop/interop_client.h
test/cpp/interop/xds_interop_client.cc
test/cpp/microbenchmarks/BUILD
test/cpp/microbenchmarks/bm_opencensus_plugin.cc
test/cpp/naming/BUILD
test/cpp/naming/address_sorting_test.cc
test/cpp/naming/cancel_ares_query_test.cc
test/cpp/naming/gen_build_yaml.py
test/cpp/naming/resolver_component_test.cc
test/cpp/naming/resolver_component_tests_runner.py
test/cpp/naming/resolver_test_record_groups.yaml
test/cpp/qps/driver.cc
test/cpp/qps/qps_worker.cc
test/cpp/qps/server_async.cc
test/cpp/qps/server_callback.cc
test/cpp/qps/server_sync.cc
test/cpp/util/BUILD
test/cpp/util/cli_credentials.cc
test/cpp/util/grpc_cli.cc
test/cpp/util/grpc_tool.cc
test/cpp/util/grpc_tool_test.cc
test/distrib/csharp/DistribTest/DistribTest.csproj
test/distrib/csharp/DistribTest/DistribTestDotNet.csproj
test/distrib/csharp/DistribTest/packages.config
third_party/toolchains/BUILD
third_party/toolchains/README.md [new file with mode: 0644]
third_party/toolchains/rbe_win2019/Dockerfile [moved from third_party/toolchains/bazel_0.26.0_rbe_windows/Dockerfile with 64% similarity]
tools/bazel
tools/codegen/core/gen_upb_api.sh
tools/distrib/check_copyright.py
tools/distrib/python/grpc_prefixed/.gitignore [new file with mode: 0644]
tools/distrib/python/grpc_prefixed/generate.py [new file with mode: 0644]
tools/distrib/python/grpc_prefixed/templates/MANIFEST.in.template [new file with mode: 0644]
tools/distrib/python/grpc_prefixed/templates/README.rst.template [new file with mode: 0644]
tools/distrib/python/grpc_prefixed/templates/setup.py.template [new file with mode: 0644]
tools/distrib/python/grpcio_tools/grpc_version.py
tools/distrib/python/grpcio_tools/protoc_lib_deps.py
tools/distrib/yapf_code.sh
tools/dockerfile/distribtest/python_dev_alpine3.7_x64/Dockerfile
tools/dockerfile/grpc_artifact_python_manylinux2010_x64/Dockerfile
tools/dockerfile/grpc_artifact_python_manylinux2010_x86/Dockerfile
tools/dockerfile/grpc_clang_tidy/Dockerfile
tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile
tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile
tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile
tools/dockerfile/interoptest/grpc_interop_go/Dockerfile
tools/dockerfile/interoptest/grpc_interop_go1.11/Dockerfile
tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile
tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile
tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile
tools/dockerfile/interoptest/grpc_interop_java/build_interop.sh
tools/dockerfile/interoptest/grpc_interop_node/Dockerfile
tools/dockerfile/interoptest/grpc_interop_php/build_interop.sh
tools/dockerfile/interoptest/grpc_interop_php7/build_interop.sh
tools/dockerfile/interoptest/grpc_interop_python/Dockerfile
tools/dockerfile/interoptest/grpc_interop_pythonasyncio/Dockerfile
tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile
tools/dockerfile/push_testing_images.sh
tools/dockerfile/test/bazel/Dockerfile
tools/dockerfile/test/csharp_stretch_x64/Dockerfile
tools/dockerfile/test/cxx_alpine_x64/Dockerfile
tools/dockerfile/test/cxx_buster_x64/Dockerfile
tools/dockerfile/test/cxx_jessie_x64/Dockerfile
tools/dockerfile/test/cxx_jessie_x86/Dockerfile
tools/dockerfile/test/cxx_sanitizers_jessie_x64/Dockerfile
tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile
tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
tools/dockerfile/test/cxx_ubuntu1804_x64/Dockerfile
tools/dockerfile/test/fuzzer/Dockerfile
tools/dockerfile/test/node_jessie_x64/Dockerfile
tools/dockerfile/test/php73_zts_stretch_x64/Dockerfile [new file with mode: 0644]
tools/dockerfile/test/php7_jessie_x64/Dockerfile
tools/dockerfile/test/php_jessie_x64/Dockerfile
tools/dockerfile/test/python_alpine_x64/Dockerfile
tools/dockerfile/test/python_stretch_2.7_x64/Dockerfile
tools/dockerfile/test/python_stretch_3.5_x64/Dockerfile
tools/dockerfile/test/python_stretch_3.6_x64/Dockerfile
tools/dockerfile/test/python_stretch_3.7_x64/Dockerfile
tools/dockerfile/test/python_stretch_3.8_x64/Dockerfile
tools/dockerfile/test/python_stretch_default_x64/Dockerfile
tools/dockerfile/test/ruby_jessie_x64/Dockerfile
tools/dockerfile/test/sanity/Dockerfile
tools/doxygen/Doxyfile.c++
tools/doxygen/Doxyfile.c++.internal
tools/doxygen/Doxyfile.core.internal
tools/doxygen/Doxyfile.objc
tools/doxygen/Doxyfile.objc.internal
tools/gce/create_win2019_container_vm.sh [new file with mode: 0755]
tools/internal_ci/helper_scripts/prepare_build_macos_rc
tools/internal_ci/linux/grpc_xds_bazel_python_test_in_docker.sh
tools/internal_ci/linux/grpc_xds_bazel_test_in_docker.sh
tools/internal_ci/linux/grpc_xds_csharp.cfg [new file with mode: 0644]
tools/internal_ci/linux/grpc_xds_csharp.sh [new file with mode: 0755]
tools/internal_ci/linux/grpc_xds_csharp_test_in_docker.sh [new file with mode: 0755]
tools/internal_ci/linux/grpc_xds_php.cfg [new file with mode: 0644]
tools/internal_ci/linux/grpc_xds_php.sh [new file with mode: 0755]
tools/internal_ci/linux/grpc_xds_php_test_in_docker.sh [new file with mode: 0755]
tools/internal_ci/linux/grpc_xds_ruby.cfg [new file with mode: 0644]
tools/internal_ci/linux/grpc_xds_ruby.sh [new file with mode: 0644]
tools/internal_ci/linux/grpc_xds_ruby_test_in_docker.sh [new file with mode: 0644]
tools/interop_matrix/client_matrix.py
tools/remote_build/windows.bazelrc
tools/run_tests/dockerize/build_and_run_docker.sh
tools/run_tests/dockerize/build_docker_and_run_tests.sh
tools/run_tests/dockerize/build_interop_image.sh
tools/run_tests/generated/tests.json
tools/run_tests/helper_scripts/build_python.sh
tools/run_tests/run_build_statistics.py [deleted file]
tools/run_tests/run_interop_tests.py
tools/run_tests/run_xds_tests.py
tools/run_tests/sanity/check_bazel_workspace.py
tools/run_tests/sanity/check_submodules.sh

diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
new file mode 100644 (file)
index 0000000..ab0bfd3
--- /dev/null
@@ -0,0 +1,23 @@
+# Configuration file for Bazel CI [1].
+#
+# Also testing on Bazel CI in addition of our normal CI workflow
+# ensures that gRPC is tested against Bazel@HEAD and stays compatible
+# with the latest release.
+#
+# See [2,3] in case you have questions.
+#
+# [1] https://github.com/bazelbuild/continuous-integration
+# [2] https://github.com/grpc/grpc/issues/19171
+# [3] https://github.com/grpc/grpc/pull/20784
+---
+# TODO(yannic): Ideally, we should also enable buildifier and all platforms should test `//...`.
+platforms:
+  ubuntu1604:
+    build_targets:
+      - //:all
+      - //src/proto/...
+      - //src/python/...
+    test_targets:
+      - //:all
+      - //src/proto/...
+      - //src/python/...
index f02cf70..dbec90a 100644 (file)
@@ -2,15 +2,17 @@
 name: Report a bug
 about: Create a report to help us improve
 labels: kind/bug, priority/P2
-assignees: nicolasnoble
+assignees: veblush
 
 ---
 
 <!--
+PLEASE DO NOT POST A QUESTION HERE.
 This form is for bug reports and feature requests ONLY!
-For general questions and troubleshooting, please ask/look for answers here:
-- grpc.io mailing list: https://groups.google.com/forum/#!forum/grpc-io
-- StackOverflow, with "grpc" tag: https://stackoverflow.com/questions/tagged/grpc
+
+For general questions and troubleshooting, please ask/look for answers at StackOverflow, with "grpc" tag: https://stackoverflow.com/questions/tagged/grpc
+
+For questions that specifically need to be answered by gRPC team members, please ask/look for answers at grpc.io mailing list: https://groups.google.com/forum/#!forum/grpc-io
 
 Issues specific to *grpc-java*, *grpc-go*, *grpc-node*, *grpc-dart*, *grpc-web* should be created in the repository they belong to (e.g. https://github.com/grpc/grpc-LANGUAGE/issues/new)
 -->
index 11e8be8..d821fef 100644 (file)
@@ -2,16 +2,17 @@
 name: Request a cleanup
 about: Suggest a cleanup in our repository
 labels: kind/internal cleanup, priority/P2
-assignees: nicolasnoble
+assignees: veblush
 
 ---
 
 <!--
-
+PLEASE DO NOT POST A QUESTION HERE.
 This form is for bug reports and feature requests ONLY!
-For general questions and troubleshooting, please ask/look for answers here:
-- grpc.io mailing list: https://groups.google.com/forum/#!forum/grpc-io
-- StackOverflow, with "grpc" tag: https://stackoverflow.com/questions/tagged/grpc
+
+For general questions and troubleshooting, please ask/look for answers at StackOverflow, with "grpc" tag: https://stackoverflow.com/questions/tagged/grpc
+
+For questions that specifically need to be answered by gRPC team members, please ask/look for answers at grpc.io mailing list: https://groups.google.com/forum/#!forum/grpc-io
 
 Issues specific to *grpc-java*, *grpc-go*, *grpc-node*, *grpc-dart*, *grpc-web* should be created in the repository they belong to (e.g. https://github.com/grpc/grpc-LANGUAGE/issues/new)
 -->
index fb3dae7..5a2f61d 100644 (file)
@@ -2,16 +2,17 @@
 name: Request a feature
 about: Suggest an idea for this project
 labels: kind/enhancement, priority/P2
-assignees: nicolasnoble
+assignees: veblush
 
 ---
 
 <!--
-
+PLEASE DO NOT POST A QUESTION HERE.
 This form is for bug reports and feature requests ONLY!
-For general questions and troubleshooting, please ask/look for answers here:
-- grpc.io mailing list: https://groups.google.com/forum/#!forum/grpc-io
-- StackOverflow, with "grpc" tag: https://stackoverflow.com/questions/tagged/grpc
+
+For general questions and troubleshooting, please ask/look for answers at StackOverflow, with "grpc" tag: https://stackoverflow.com/questions/tagged/grpc
+
+For questions that specifically need to be answered by gRPC team members, please ask/look for answers at grpc.io mailing list: https://groups.google.com/forum/#!forum/grpc-io
 
 Issues specific to *grpc-java*, *grpc-go*, *grpc-node*, *grpc-dart*, *grpc-web* should be created in the repository they belong to (e.g. https://github.com/grpc/grpc-LANGUAGE/issues/new)
 -->
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
new file mode 100644 (file)
index 0000000..68f5dfb
--- /dev/null
@@ -0,0 +1,17 @@
+---
+name: Ask a question
+about: Ask a question
+labels: kind/question, priority/P3
+assignees: veblush
+
+---
+
+PLEASE DO NOT POST A QUESTION HERE.
+This form is for bug reports and feature requests ONLY!
+
+For general questions and troubleshooting, please ask/look for answers at StackOverflow, with "grpc" tag: https://stackoverflow.com/questions/tagged/grpc
+
+For questions that specifically need to be answered by gRPC team members, please ask/look for answers at grpc.io mailing list: https://groups.google.com/forum/#!forum/grpc-io
+
+This issue will be closed down once seen by the repo managers.
+
index 57af6c2..366b686 100644 (file)
@@ -8,4 +8,4 @@ If you know who should review your pull request, please remove the mentioning be
 
 -->
 
-@nicolasnoble
+@veblush
index 1220393..081cb6d 100644 (file)
@@ -1,7 +1,7 @@
 # Configuration for probot-stale - https://github.com/probot/stale
 
 # Number of days of inactivity before an Issue or Pull Request becomes stale
-daysUntilStale: 180
+daysUntilStale: 90
 
 # Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
 # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
@@ -13,6 +13,7 @@ onlyLabels: []
 # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
 exemptLabels:
   - "disposition/never stale"
+  - "kind/bug"
 
 # Set to true to ignore issues in a project (defaults to false)
 exemptProjects: false
@@ -29,8 +30,8 @@ staleLabel: "disposition/stale"
 # Comment to post when marking as stale. Set to `false` to disable
 markComment: >
   This issue/PR has been automatically marked as stale because it has not had any update (including
-  commits, comments, labels, milestones, etc) for 180 days. It will be closed automatically if no
-  further update occurs in 1 day. Thank you for your contributions!
+  commits, comments, labels, milestones, etc) for 30 days. It will be closed automatically if no
+  further update occurs in 7 day. Thank you for your contributions!
 
 # Comment to post when removing the stale label.
 # unmarkComment: >
@@ -56,4 +57,4 @@ limitPerRun: 30
 
 # issues:
 #   exemptLabels:
-#     - confirmed
\ No newline at end of file
+#     - confirmed
index 32d26a4..c0ec881 100644 (file)
@@ -23,6 +23,7 @@ a.out
 src/python/grpcio_*/LICENSE
 src/python/grpcio_status/grpc_status/google/rpc/status.proto
 .pytype
+*.egg-info
 
 # Node installation output
 node_modules
index 9097319..aefc8f9 100644 (file)
@@ -8,7 +8,6 @@
 [submodule "third_party/protobuf"]
        path = third_party/protobuf
        url = https://github.com/google/protobuf.git
-       branch = 3.0.x
 [submodule "third_party/gflags"]
        path = third_party/gflags
        url = https://github.com/gflags/gflags.git
diff --git a/BUILD b/BUILD
index f0b11d1..e8d8cd8 100644 (file)
--- a/BUILD
+++ b/BUILD
@@ -75,11 +75,11 @@ config_setting(
 python_config_settings()
 
 # This should be updated along with build.yaml
-g_stands_for = "gringotts"
+g_stands_for = "gradius"
 
 core_version = "10.0.0"
 
-version = "1.29.1"
+version = "1.30.0"
 
 GPR_PUBLIC_HDRS = [
     "include/grpc/support/alloc.h",
@@ -554,7 +554,6 @@ grpc_cc_library(
         "src/core/lib/gprpp/map.h",
         "src/core/lib/gprpp/memory.h",
         "src/core/lib/gprpp/mpscq.h",
-        "src/core/lib/gprpp/string_view.h",
         "src/core/lib/gprpp/sync.h",
         "src/core/lib/gprpp/thd.h",
         "src/core/lib/profiling/timers.h",
@@ -619,40 +618,12 @@ grpc_cc_library(
 )
 
 grpc_cc_library(
-    name = "inlined_vector",
-    external_deps = [
-        "absl/container:inlined_vector",
-    ],
-    language = "c++",
-    public_hdrs = [
-        "src/core/lib/gprpp/inlined_vector.h",
-    ],
-    deps = [
-        "gpr_base",
-    ],
-)
-
-grpc_cc_library(
     name = "debug_location",
     language = "c++",
     public_hdrs = ["src/core/lib/gprpp/debug_location.h"],
 )
 
 grpc_cc_library(
-    name = "optional",
-    external_deps = [
-        "absl/types:optional",
-    ],
-    language = "c++",
-    public_hdrs = [
-        "src/core/lib/gprpp/optional.h",
-    ],
-    deps = [
-        "gpr_base",
-    ],
-)
-
-grpc_cc_library(
     name = "orphanable",
     language = "c++",
     public_hdrs = ["src/core/lib/gprpp/orphanable.h"],
@@ -990,6 +961,8 @@ grpc_cc_library(
     ],
     external_deps = [
         "madler_zlib",
+        "absl/container:inlined_vector",
+        "absl/types:optional",
     ],
     language = "c++",
     public_hdrs = GRPC_PUBLIC_HDRS,
@@ -998,8 +971,6 @@ grpc_cc_library(
         "gpr_base",
         "grpc_codegen",
         "grpc_trace",
-        "inlined_vector",
-        "optional",
         "orphanable",
         "ref_counted",
         "ref_counted_ptr",
@@ -1073,6 +1044,7 @@ grpc_cc_library(
         "src/core/ext/filters/client_channel/retry_throttle.cc",
         "src/core/ext/filters/client_channel/server_address.cc",
         "src/core/ext/filters/client_channel/service_config.cc",
+        "src/core/ext/filters/client_channel/service_config_parser.cc",
         "src/core/ext/filters/client_channel/subchannel.cc",
         "src/core/ext/filters/client_channel/subchannel_pool_interface.cc",
     ],
@@ -1103,10 +1075,15 @@ grpc_cc_library(
         "src/core/ext/filters/client_channel/retry_throttle.h",
         "src/core/ext/filters/client_channel/server_address.h",
         "src/core/ext/filters/client_channel/service_config.h",
+        "src/core/ext/filters/client_channel/service_config_call_data.h",
+        "src/core/ext/filters/client_channel/service_config_parser.h",
         "src/core/ext/filters/client_channel/subchannel.h",
         "src/core/ext/filters/client_channel/subchannel_interface.h",
         "src/core/ext/filters/client_channel/subchannel_pool_interface.h",
     ],
+    external_deps = [
+        "absl/container:inlined_vector",
+    ],
     language = "c++",
     deps = [
         "gpr_base",
@@ -1114,7 +1091,6 @@ grpc_cc_library(
         "grpc_client_authority_filter",
         "grpc_deadline_filter",
         "grpc_health_upb",
-        "inlined_vector",
         "orphanable",
         "ref_counted",
         "ref_counted_ptr",
@@ -2509,6 +2485,9 @@ grpc_cc_library(
     name = "envoy_ads_upb",
     srcs = [
         "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/cds.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c",
@@ -2534,11 +2513,15 @@ grpc_cc_library(
         "src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c",
         "src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c",
         "src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c",
+        "src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c",
         "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c",
         "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c",
     ],
     hdrs = [
         "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/cds.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h",
@@ -2564,6 +2547,7 @@ grpc_cc_library(
         "src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h",
         "src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h",
         "src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h",
+        "src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h",
         "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h",
         "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h",
     ],
@@ -2604,21 +2588,27 @@ grpc_cc_library(
     name = "envoy_core_upb",
     srcs = [
         "src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c",
     ],
     hdrs = [
         "src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h",
     ],
     external_deps = [
         "upb_lib",
@@ -2714,10 +2704,12 @@ grpc_cc_library(
     srcs = [
         "src/core/ext/upb-generated/udpa/annotations/migrate.upb.c",
         "src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c",
+        "src/core/ext/upb-generated/udpa/annotations/status.upb.c",
     ],
     hdrs = [
         "src/core/ext/upb-generated/udpa/annotations/migrate.upb.h",
         "src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h",
+        "src/core/ext/upb-generated/udpa/annotations/status.upb.h",
     ],
     external_deps = [
         "upb_lib",
index 6c3db9a..a16d298 100644 (file)
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -160,7 +160,6 @@ config("grpc_config") {
         "src/core/lib/gprpp/memory.h",
         "src/core/lib/gprpp/mpscq.cc",
         "src/core/lib/gprpp/mpscq.h",
-        "src/core/lib/gprpp/string_view.h",
         "src/core/lib/gprpp/sync.h",
         "src/core/lib/gprpp/thd.h",
         "src/core/lib/gprpp/thd_posix.cc",
@@ -293,6 +292,9 @@ config("grpc_config") {
         "src/core/ext/filters/client_channel/server_address.h",
         "src/core/ext/filters/client_channel/service_config.cc",
         "src/core/ext/filters/client_channel/service_config.h",
+        "src/core/ext/filters/client_channel/service_config_call_data.h",
+        "src/core/ext/filters/client_channel/service_config_parser.cc",
+        "src/core/ext/filters/client_channel/service_config_parser.h",
         "src/core/ext/filters/client_channel/subchannel.cc",
         "src/core/ext/filters/client_channel/subchannel.h",
         "src/core/ext/filters/client_channel/subchannel_interface.h",
@@ -398,6 +400,12 @@ config("grpc_config") {
         "src/core/ext/upb-generated/envoy/annotations/resource.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/cds.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/cds.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c",
@@ -410,10 +418,14 @@ config("grpc_config") {
         "src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c",
@@ -422,6 +434,8 @@ config("grpc_config") {
         "src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h",
         "src/core/ext/upb-generated/envoy/api/v2/eds.upb.c",
@@ -462,6 +476,8 @@ config("grpc_config") {
         "src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h",
         "src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c",
         "src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h",
+        "src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c",
+        "src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h",
         "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c",
         "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h",
         "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c",
@@ -518,6 +534,8 @@ config("grpc_config") {
         "src/core/ext/upb-generated/udpa/annotations/migrate.upb.h",
         "src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c",
         "src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h",
+        "src/core/ext/upb-generated/udpa/annotations/status.upb.c",
+        "src/core/ext/upb-generated/udpa/annotations/status.upb.h",
         "src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c",
         "src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h",
         "src/core/ext/upb-generated/validate/validate.upb.c",
@@ -570,8 +588,6 @@ config("grpc_config") {
         "src/core/lib/debug/trace.h",
         "src/core/lib/gprpp/atomic.h",
         "src/core/lib/gprpp/debug_location.h",
-        "src/core/lib/gprpp/inlined_vector.h",
-        "src/core/lib/gprpp/optional.h",
         "src/core/lib/gprpp/orphanable.h",
         "src/core/lib/gprpp/ref_counted.h",
         "src/core/lib/gprpp/ref_counted_ptr.h",
index a113700..4a8d144 100644 (file)
@@ -172,13 +172,23 @@ If you want to build DLLs, run `cmake` with `-DBUILD_SHARED_LIBS=ON`.
 
 ### Dependency management
 
-gRPC's CMake build system provides two modes for handling dependencies.
-* module - build dependencies alongside gRPC.
-* package - use external copies of dependencies that are already available
-on your system.
+gRPC's CMake build system has two options for handling dependencies.
+CMake can build the dependencies for you, or it can search for libraries
+that are already installed on your system and use them to build gRPC.
 
 This behavior is controlled by the `gRPC_<depname>_PROVIDER` CMake variables,
-ie `gRPC_CARES_PROVIDER`.
+e.g. `gRPC_CARES_PROVIDER`. The options that these variables take are as follows:
+
+* module - build dependencies alongside gRPC. The source code is obtained from
+gRPC's git submodules.
+* package - use external copies of dependencies that are already available
+on your system. These could come from your system package manager, or perhaps
+you pre-installed them using CMake with the `CMAKE_INSTALL_PREFIX` option.
+
+For example, if you set `gRPC_CARES_PROVIDER=module`, then CMake will build
+c-ares before building gRPC. On the other hand, if you set
+`gRPC_CARES_PROVIDER=package`, then CMake will search for a copy of c-ares
+that's already installed on your system and use it to build gRPC.
 
 ### Install after build
 
@@ -193,8 +203,8 @@ If you are running CMake v3.13 or newer you can build gRPC's dependencies
 in "module" mode and install them alongside gRPC in a single step.
 [Example](test/distrib/cpp/run_distrib_test_cmake_module_install.sh)
 
-If you are using an older version of gRPC, you will need to select "package"
-mode (rather than "module" mode) for the dependencies.
+If you are building gRPC < 1.27 or if you are using CMake < 3.13 you will need
+to select "package" mode (rather than "module" mode) for the dependencies.
 This means you will need to have external copies of these libraries available
 on your system. This [example](test/distrib/cpp/run_distrib_test_cmake.sh) shows
 how to install dependencies with cmake before proceeding to installing gRPC itself. 
index 8561c67..9902152 100644 (file)
 cmake_minimum_required(VERSION 3.5.1)
 
 set(PACKAGE_NAME          "grpc")
-set(PACKAGE_VERSION       "1.29.1")
+set(PACKAGE_VERSION       "1.30.0")
 set(gRPC_CORE_VERSION     "10.0.0")
 set(gRPC_CORE_SOVERSION   "10")
-set(gRPC_CPP_VERSION      "1.29.1")
+set(gRPC_CPP_VERSION      "1.30.0")
 set(gRPC_CPP_SOVERSION    "1")
-set(gRPC_CSHARP_VERSION   "2.29.1")
+set(gRPC_CSHARP_VERSION   "2.30.0")
 set(gRPC_CSHARP_SOVERSION "2")
 set(PACKAGE_STRING        "${PACKAGE_NAME} ${PACKAGE_VERSION}")
 set(PACKAGE_TARNAME       "${PACKAGE_NAME}-${PACKAGE_VERSION}")
@@ -153,14 +153,28 @@ if(WIN32)
 endif()
 
  # Use C99 standard
-set(CMAKE_C_STANDARD 99)
+if (NOT DEFINED CMAKE_C_STANDARD)
+  set(CMAKE_C_STANDARD 99)
+endif()
 
 # Add c++11 flags
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_CXX_EXTENSIONS OFF)
+if (NOT DEFINED CMAKE_CXX_STANDARD)
+  set(CMAKE_CXX_STANDARD 11)
+else()
+  if (CMAKE_CXX_STANDARD LESS 11)
+    message(FATAL_ERROR "CMAKE_CXX_STANDARD is less than 11, please specify at least SET(CMAKE_CXX_STANDARD 11)")
+  endif()
+endif()
+if (NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED)
+  set(CMAKE_CXX_STANDARD_REQUIRED ON)
+endif()
+if (NOT DEFINED CMAKE_CXX_EXTENSIONS)
+  set(CMAKE_CXX_EXTENSIONS OFF)
+endif()
 
-set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
+if (NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
+  set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
+endif()
 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
 
 if(MSVC)
@@ -175,6 +189,9 @@ if(MSVC)
   # TODO(jtattermusch): needed to build boringssl with VS2017, revisit later
   set(_gRPC_C_CXX_FLAGS "${_gRPC_C_CXX_FLAGS} /wd4987 /wd4774 /wd4819 /wd4996 /wd4619")
 endif()
+if (MINGW)
+  add_definitions(-D_WIN32_WINNT=0x600)
+endif()
 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_gRPC_C_CXX_FLAGS}")
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_gRPC_C_CXX_FLAGS}")
 
@@ -217,7 +234,7 @@ elseif(UNIX)
   set(_gRPC_ALLTARGETS_LIBRARIES ${CMAKE_DL_LIBS} rt m pthread)
 endif()
 
-if(WIN32 AND MSVC)
+if(WIN32)
   set(_gRPC_BASELIB_LIBRARIES wsock32 ws2_32 crypt32)
 endif()
 
@@ -756,7 +773,6 @@ if(gRPC_BUILD_TESTS)
   add_dependencies(buildtests_cxx mock_test)
   add_dependencies(buildtests_cxx nonblocking_test)
   add_dependencies(buildtests_cxx noop-benchmark)
-  add_dependencies(buildtests_cxx optional_test)
   add_dependencies(buildtests_cxx orphanable_test)
   add_dependencies(buildtests_cxx out_of_bounds_bad_client_test)
   add_dependencies(buildtests_cxx pid_controller_test)
@@ -799,7 +815,6 @@ if(gRPC_BUILD_TESTS)
     add_dependencies(buildtests_cxx streaming_throughput_test)
   endif()
   add_dependencies(buildtests_cxx string_ref_test)
-  add_dependencies(buildtests_cxx string_view_test)
   add_dependencies(buildtests_cxx test_cpp_client_credentials_test)
   add_dependencies(buildtests_cxx test_cpp_util_slice_test)
   add_dependencies(buildtests_cxx test_cpp_util_time_test)
@@ -919,6 +934,7 @@ add_library(end2end_nosec_tests
   test/core/end2end/tests/cancel_in_a_vacuum.cc
   test/core/end2end/tests/cancel_with_status.cc
   test/core/end2end/tests/channelz.cc
+  test/core/end2end/tests/client_streaming.cc
   test/core/end2end/tests/compressed_payload.cc
   test/core/end2end/tests/connectivity.cc
   test/core/end2end/tests/default_host.cc
@@ -1050,6 +1066,7 @@ add_library(end2end_tests
   test/core/end2end/tests/cancel_in_a_vacuum.cc
   test/core/end2end/tests/cancel_with_status.cc
   test/core/end2end/tests/channelz.cc
+  test/core/end2end/tests/client_streaming.cc
   test/core/end2end/tests/compressed_payload.cc
   test/core/end2end/tests/connectivity.cc
   test/core/end2end/tests/default_host.cc
@@ -1357,6 +1374,7 @@ add_library(grpc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/server_address.cc
   src/core/ext/filters/client_channel/service_config.cc
+  src/core/ext/filters/client_channel/service_config_parser.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_pool_interface.cc
   src/core/ext/filters/client_channel/xds/xds_api.cc
@@ -1414,18 +1432,24 @@ add_library(grpc
   src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c
   src/core/ext/upb-generated/envoy/annotations/resource.upb.c
   src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c
   src/core/ext/upb-generated/envoy/api/v2/cds.upb.c
   src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c
   src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c
   src/core/ext/upb-generated/envoy/api/v2/eds.upb.c
   src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c
@@ -1446,6 +1470,7 @@ add_library(grpc
   src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c
   src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c
   src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c
+  src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c
   src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c
   src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c
   src/core/ext/upb-generated/envoy/type/http.upb.c
@@ -1474,6 +1499,7 @@ add_library(grpc
   src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
   src/core/ext/upb-generated/udpa/annotations/migrate.upb.c
   src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c
+  src/core/ext/upb-generated/udpa/annotations/status.upb.c
   src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
   src/core/ext/upb-generated/validate/validate.upb.c
   src/core/lib/avl/avl.cc
@@ -2019,6 +2045,7 @@ add_library(grpc_unsecure
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/server_address.cc
   src/core/ext/filters/client_channel/service_config.cc
+  src/core/ext/filters/client_channel/service_config_parser.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_pool_interface.cc
   src/core/ext/filters/client_channel/xds/xds_api.cc
@@ -2074,18 +2101,24 @@ add_library(grpc_unsecure
   src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c
   src/core/ext/upb-generated/envoy/annotations/resource.upb.c
   src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c
   src/core/ext/upb-generated/envoy/api/v2/cds.upb.c
   src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c
   src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c
   src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c
   src/core/ext/upb-generated/envoy/api/v2/eds.upb.c
   src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c
@@ -2106,6 +2139,7 @@ add_library(grpc_unsecure
   src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c
   src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c
   src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c
+  src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c
   src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c
   src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c
   src/core/ext/upb-generated/envoy/type/http.upb.c
@@ -2131,6 +2165,7 @@ add_library(grpc_unsecure
   src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
   src/core/ext/upb-generated/udpa/annotations/migrate.upb.c
   src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c
+  src/core/ext/upb-generated/udpa/annotations/status.upb.c
   src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
   src/core/ext/upb-generated/validate/validate.upb.c
   src/core/lib/avl/avl.cc
@@ -6767,10 +6802,6 @@ endif()
 if(gRPC_BUILD_TESTS)
 
 add_executable(sequential_connectivity_test
-  test/core/end2end/data/client_certs.cc
-  test/core/end2end/data/server1_cert.cc
-  test/core/end2end/data/server1_key.cc
-  test/core/end2end/data/test_root_cert.cc
   test/core/surface/sequential_connectivity_test.cc
 )
 
@@ -11073,10 +11104,6 @@ endif()
 if(gRPC_BUILD_TESTS)
 
 add_executable(grpc_tls_credentials_options_test
-  test/core/end2end/data/client_certs.cc
-  test/core/end2end/data/server1_cert.cc
-  test/core/end2end/data/server1_key.cc
-  test/core/end2end/data/test_root_cert.cc
   test/core/security/grpc_tls_credentials_options_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
@@ -12167,44 +12194,6 @@ target_link_libraries(noop-benchmark
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(optional_test
-  test/core/gprpp/optional_test.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
-
-target_include_directories(optional_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-    third_party/googletest/googletest/include
-    third_party/googletest/googletest
-    third_party/googletest/googlemock/include
-    third_party/googletest/googlemock
-    ${_gRPC_PROTO_GENS_DIR}
-)
-
-target_link_libraries(optional_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-  grpc
-  gpr
-  address_sorting
-  upb
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
 add_executable(orphanable_test
   test/core/gprpp/orphanable_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -13806,44 +13795,6 @@ target_link_libraries(string_ref_test
 endif()
 if(gRPC_BUILD_TESTS)
 
-add_executable(string_view_test
-  test/core/gprpp/string_view_test.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-  third_party/googletest/googlemock/src/gmock-all.cc
-)
-
-target_include_directories(string_view_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-    third_party/googletest/googletest/include
-    third_party/googletest/googletest
-    third_party/googletest/googlemock/include
-    third_party/googletest/googlemock
-    ${_gRPC_PROTO_GENS_DIR}
-)
-
-target_link_libraries(string_view_test
-  ${_gRPC_PROTOBUF_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-  grpc
-  gpr
-  address_sorting
-  upb
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-
-endif()
-if(gRPC_BUILD_TESTS)
-
 add_executable(test_cpp_client_credentials_test
   test/cpp/client/credentials_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -14143,10 +14094,6 @@ endif()
 if(gRPC_BUILD_TESTS)
 
 add_executable(tls_security_connector_test
-  test/core/end2end/data/client_certs.cc
-  test/core/end2end/data/server1_cert.cc
-  test/core/end2end/data/server1_key.cc
-  test/core/end2end/data/test_root_cert.cc
   test/core/security/tls_security_connector_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
@@ -15038,10 +14985,6 @@ endif()
 if(gRPC_BUILD_TESTS)
 
 add_executable(ssl_server_fuzzer_one_entry
-  test/core/end2end/data/client_certs.cc
-  test/core/end2end/data/server1_cert.cc
-  test/core/end2end/data/server1_key.cc
-  test/core/end2end/data/test_root_cert.cc
   test/core/security/ssl_server_fuzzer.cc
   test/core/util/one_corpus_entry_fuzzer.cc
   third_party/googletest/googletest/src/gtest-all.cc
index c524257..1d074d8 100644 (file)
@@ -7,6 +7,9 @@ and [contribution guidelines](https://github.com/grpc/grpc-community/blob/master
 If you are new to github, please start by reading [Pull Request
 howto](https://help.github.com/articles/about-pull-requests/)
 
+If you are looking for features to work on, please filter the issues list with the label ["disposition/help wanted"](https://github.com/grpc/grpc/issues?q=label%3A%22disposition%2Fhelp+wanted%22).
+Please note that some of these feature requests might have been closed in the past as a result of them being marked as stale due to there being no activity, but these are still valid feature requests.
+
 ## Legal requirements
 
 In order to protect both you and ourselves, you will need to sign the
index a69c2b0..9b839bd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -470,8 +470,8 @@ Q = @
 endif
 
 CORE_VERSION = 10.0.0
-CPP_VERSION = 1.29.1
-CSHARP_VERSION = 2.29.1
+CPP_VERSION = 1.30.0
+CSHARP_VERSION = 2.30.0
 
 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
 CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -1251,7 +1251,6 @@ nanopb_fuzzer_response_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test
 nanopb_fuzzer_serverlist_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test
 nonblocking_test: $(BINDIR)/$(CONFIG)/nonblocking_test
 noop-benchmark: $(BINDIR)/$(CONFIG)/noop-benchmark
-optional_test: $(BINDIR)/$(CONFIG)/optional_test
 orphanable_test: $(BINDIR)/$(CONFIG)/orphanable_test
 out_of_bounds_bad_client_test: $(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test
 percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer
@@ -1290,7 +1289,6 @@ status_metadata_test: $(BINDIR)/$(CONFIG)/status_metadata_test
 status_util_test: $(BINDIR)/$(CONFIG)/status_util_test
 streaming_throughput_test: $(BINDIR)/$(CONFIG)/streaming_throughput_test
 string_ref_test: $(BINDIR)/$(CONFIG)/string_ref_test
-string_view_test: $(BINDIR)/$(CONFIG)/string_view_test
 test_cpp_client_credentials_test: $(BINDIR)/$(CONFIG)/test_cpp_client_credentials_test
 test_cpp_util_slice_test: $(BINDIR)/$(CONFIG)/test_cpp_util_slice_test
 test_cpp_util_time_test: $(BINDIR)/$(CONFIG)/test_cpp_util_time_test
@@ -1616,7 +1614,6 @@ buildtests_cxx: privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/mock_test \
   $(BINDIR)/$(CONFIG)/nonblocking_test \
   $(BINDIR)/$(CONFIG)/noop-benchmark \
-  $(BINDIR)/$(CONFIG)/optional_test \
   $(BINDIR)/$(CONFIG)/orphanable_test \
   $(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test \
   $(BINDIR)/$(CONFIG)/pid_controller_test \
@@ -1651,7 +1648,6 @@ buildtests_cxx: privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/status_util_test \
   $(BINDIR)/$(CONFIG)/streaming_throughput_test \
   $(BINDIR)/$(CONFIG)/string_ref_test \
-  $(BINDIR)/$(CONFIG)/string_view_test \
   $(BINDIR)/$(CONFIG)/test_cpp_client_credentials_test \
   $(BINDIR)/$(CONFIG)/test_cpp_util_slice_test \
   $(BINDIR)/$(CONFIG)/test_cpp_util_time_test \
@@ -1774,7 +1770,6 @@ buildtests_cxx: privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/mock_test \
   $(BINDIR)/$(CONFIG)/nonblocking_test \
   $(BINDIR)/$(CONFIG)/noop-benchmark \
-  $(BINDIR)/$(CONFIG)/optional_test \
   $(BINDIR)/$(CONFIG)/orphanable_test \
   $(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test \
   $(BINDIR)/$(CONFIG)/pid_controller_test \
@@ -1809,7 +1804,6 @@ buildtests_cxx: privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/status_util_test \
   $(BINDIR)/$(CONFIG)/streaming_throughput_test \
   $(BINDIR)/$(CONFIG)/string_ref_test \
-  $(BINDIR)/$(CONFIG)/string_view_test \
   $(BINDIR)/$(CONFIG)/test_cpp_client_credentials_test \
   $(BINDIR)/$(CONFIG)/test_cpp_util_slice_test \
   $(BINDIR)/$(CONFIG)/test_cpp_util_time_test \
@@ -1916,8 +1910,6 @@ test_c: buildtests_c
        $(Q) $(BINDIR)/$(CONFIG)/combiner_test || ( echo test combiner_test failed ; exit 1 )
        $(E) "[RUN]     Testing compression_test"
        $(Q) $(BINDIR)/$(CONFIG)/compression_test || ( echo test compression_test failed ; exit 1 )
-       $(E) "[RUN]     Testing concurrent_connectivity_test"
-       $(Q) $(BINDIR)/$(CONFIG)/concurrent_connectivity_test || ( echo test concurrent_connectivity_test failed ; exit 1 )
        $(E) "[RUN]     Testing connection_refused_test"
        $(Q) $(BINDIR)/$(CONFIG)/connection_refused_test || ( echo test connection_refused_test failed ; exit 1 )
        $(E) "[RUN]     Testing cpu_test"
@@ -2190,8 +2182,6 @@ test_cxx: buildtests_cxx
        $(Q) $(BINDIR)/$(CONFIG)/byte_buffer_test || ( echo test byte_buffer_test failed ; exit 1 )
        $(E) "[RUN]     Testing byte_stream_test"
        $(Q) $(BINDIR)/$(CONFIG)/byte_stream_test || ( echo test byte_stream_test failed ; exit 1 )
-       $(E) "[RUN]     Testing cancel_ares_query_test"
-       $(Q) $(BINDIR)/$(CONFIG)/cancel_ares_query_test || ( echo test cancel_ares_query_test failed ; exit 1 )
        $(E) "[RUN]     Testing channel_arguments_test"
        $(Q) $(BINDIR)/$(CONFIG)/channel_arguments_test || ( echo test channel_arguments_test failed ; exit 1 )
        $(E) "[RUN]     Testing channel_filter_test"
@@ -2202,6 +2192,8 @@ test_cxx: buildtests_cxx
        $(Q) $(BINDIR)/$(CONFIG)/channelz_registry_test || ( echo test channelz_registry_test failed ; exit 1 )
        $(E) "[RUN]     Testing channelz_service_test"
        $(Q) $(BINDIR)/$(CONFIG)/channelz_service_test || ( echo test channelz_service_test failed ; exit 1 )
+       $(E) "[RUN]     Testing channelz_test"
+       $(Q) $(BINDIR)/$(CONFIG)/channelz_test || ( echo test channelz_test failed ; exit 1 )
        $(E) "[RUN]     Testing cli_call_test"
        $(Q) $(BINDIR)/$(CONFIG)/cli_call_test || ( echo test cli_call_test failed ; exit 1 )
        $(E) "[RUN]     Testing client_callback_end2end_test"
@@ -2276,8 +2268,6 @@ test_cxx: buildtests_cxx
        $(Q) $(BINDIR)/$(CONFIG)/nonblocking_test || ( echo test nonblocking_test failed ; exit 1 )
        $(E) "[RUN]     Testing noop-benchmark"
        $(Q) $(BINDIR)/$(CONFIG)/noop-benchmark || ( echo test noop-benchmark failed ; exit 1 )
-       $(E) "[RUN]     Testing optional_test"
-       $(Q) $(BINDIR)/$(CONFIG)/optional_test || ( echo test optional_test failed ; exit 1 )
        $(E) "[RUN]     Testing orphanable_test"
        $(Q) $(BINDIR)/$(CONFIG)/orphanable_test || ( echo test orphanable_test failed ; exit 1 )
        $(E) "[RUN]     Testing out_of_bounds_bad_client_test"
@@ -2340,8 +2330,6 @@ test_cxx: buildtests_cxx
        $(Q) $(BINDIR)/$(CONFIG)/streaming_throughput_test || ( echo test streaming_throughput_test failed ; exit 1 )
        $(E) "[RUN]     Testing string_ref_test"
        $(Q) $(BINDIR)/$(CONFIG)/string_ref_test || ( echo test string_ref_test failed ; exit 1 )
-       $(E) "[RUN]     Testing string_view_test"
-       $(Q) $(BINDIR)/$(CONFIG)/string_view_test || ( echo test string_view_test failed ; exit 1 )
        $(E) "[RUN]     Testing test_cpp_client_credentials_test"
        $(Q) $(BINDIR)/$(CONFIG)/test_cpp_client_credentials_test || ( echo test test_cpp_client_credentials_test failed ; exit 1 )
        $(E) "[RUN]     Testing test_cpp_util_slice_test"
@@ -3290,6 +3278,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \
     test/core/end2end/tests/cancel_in_a_vacuum.cc \
     test/core/end2end/tests/cancel_with_status.cc \
     test/core/end2end/tests/channelz.cc \
+    test/core/end2end/tests/client_streaming.cc \
     test/core/end2end/tests/compressed_payload.cc \
     test/core/end2end/tests/connectivity.cc \
     test/core/end2end/tests/default_host.cc \
@@ -3402,6 +3391,7 @@ LIBEND2END_TESTS_SRC = \
     test/core/end2end/tests/cancel_in_a_vacuum.cc \
     test/core/end2end/tests/cancel_with_status.cc \
     test/core/end2end/tests/channelz.cc \
+    test/core/end2end/tests/client_streaming.cc \
     test/core/end2end/tests/compressed_payload.cc \
     test/core/end2end/tests/connectivity.cc \
     test/core/end2end/tests/default_host.cc \
@@ -3682,6 +3672,7 @@ LIBGRPC_SRC = \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/server_address.cc \
     src/core/ext/filters/client_channel/service_config.cc \
+    src/core/ext/filters/client_channel/service_config_parser.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
     src/core/ext/filters/client_channel/xds/xds_api.cc \
@@ -3739,18 +3730,24 @@ LIBGRPC_SRC = \
     src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c \
     src/core/ext/upb-generated/envoy/annotations/resource.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cds.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/eds.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c \
@@ -3771,6 +3768,7 @@ LIBGRPC_SRC = \
     src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c \
     src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c \
     src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c \
+    src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c \
     src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c \
     src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c \
     src/core/ext/upb-generated/envoy/type/http.upb.c \
@@ -3799,6 +3797,7 @@ LIBGRPC_SRC = \
     src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
     src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
     src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/status.upb.c \
     src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
     src/core/ext/upb-generated/validate/validate.upb.c \
     src/core/lib/avl/avl.cc \
@@ -4318,6 +4317,7 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/server_address.cc \
     src/core/ext/filters/client_channel/service_config.cc \
+    src/core/ext/filters/client_channel/service_config_parser.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
     src/core/ext/filters/client_channel/xds/xds_api.cc \
@@ -4373,18 +4373,24 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c \
     src/core/ext/upb-generated/envoy/annotations/resource.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cds.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/eds.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c \
@@ -4405,6 +4411,7 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c \
     src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c \
     src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c \
+    src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c \
     src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c \
     src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c \
     src/core/ext/upb-generated/envoy/type/http.upb.c \
@@ -4430,6 +4437,7 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
     src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
     src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/status.upb.c \
     src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
     src/core/ext/upb-generated/validate/validate.upb.c \
     src/core/lib/avl/avl.cc \
@@ -5903,6 +5911,7 @@ LIBBORINGSSL_SRC = \
     third_party/boringssl-with-bazel/src/crypto/cpu-intel.c \
     third_party/boringssl-with-bazel/src/crypto/cpu-ppc64le.c \
     third_party/boringssl-with-bazel/src/crypto/crypto.c \
+    third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519.c \
     third_party/boringssl-with-bazel/src/crypto/curve25519/spake25519.c \
     third_party/boringssl-with-bazel/src/crypto/dh/check.c \
     third_party/boringssl-with-bazel/src/crypto/dh/dh.c \
@@ -5913,6 +5922,7 @@ LIBBORINGSSL_SRC = \
     third_party/boringssl-with-bazel/src/crypto/dsa/dsa_asn1.c \
     third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_asn1.c \
     third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_derive.c \
+    third_party/boringssl-with-bazel/src/crypto/ec_extra/hash_to_curve.c \
     third_party/boringssl-with-bazel/src/crypto/ecdh_extra/ecdh_extra.c \
     third_party/boringssl-with-bazel/src/crypto/ecdsa_extra/ecdsa_asn1.c \
     third_party/boringssl-with-bazel/src/crypto/engine/engine.c \
@@ -5977,6 +5987,8 @@ LIBBORINGSSL_SRC = \
     third_party/boringssl-with-bazel/src/crypto/thread_none.c \
     third_party/boringssl-with-bazel/src/crypto/thread_pthread.c \
     third_party/boringssl-with-bazel/src/crypto/thread_win.c \
+    third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c \
+    third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token.c \
     third_party/boringssl-with-bazel/src/crypto/x509/a_digest.c \
     third_party/boringssl-with-bazel/src/crypto/x509/a_sign.c \
     third_party/boringssl-with-bazel/src/crypto/x509/a_strex.c \
@@ -6095,7 +6107,6 @@ LIBBORINGSSL_SRC = \
     third_party/boringssl-with-bazel/src/ssl/tls13_server.cc \
     third_party/boringssl-with-bazel/src/ssl/tls_method.cc \
     third_party/boringssl-with-bazel/src/ssl/tls_record.cc \
-    third_party/boringssl-with-bazel/src/third_party/fiat/curve25519.c \
 
 PUBLIC_HEADERS_C += \
 
@@ -10007,10 +10018,6 @@ endif
 
 
 SEQUENTIAL_CONNECTIVITY_TEST_SRC = \
-    test/core/end2end/data/client_certs.cc \
-    test/core/end2end/data/server1_cert.cc \
-    test/core/end2end/data/server1_key.cc \
-    test/core/end2end/data/test_root_cert.cc \
     test/core/surface/sequential_connectivity_test.cc \
 
 SEQUENTIAL_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SEQUENTIAL_CONNECTIVITY_TEST_SRC))))
@@ -10031,14 +10038,6 @@ $(BINDIR)/$(CONFIG)/sequential_connectivity_test: $(SEQUENTIAL_CONNECTIVITY_TEST
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/client_certs.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_cert.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_key.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/test_root_cert.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
 $(OBJDIR)/$(CONFIG)/test/core/surface/sequential_connectivity_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
 
 deps_sequential_connectivity_test: $(SEQUENTIAL_CONNECTIVITY_TEST_OBJS:.o=.dep)
@@ -14709,10 +14708,6 @@ endif
 
 
 GRPC_TLS_CREDENTIALS_OPTIONS_TEST_SRC = \
-    test/core/end2end/data/client_certs.cc \
-    test/core/end2end/data/server1_cert.cc \
-    test/core/end2end/data/server1_key.cc \
-    test/core/end2end/data/test_root_cert.cc \
     test/core/security/grpc_tls_credentials_options_test.cc \
 
 GRPC_TLS_CREDENTIALS_OPTIONS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_TLS_CREDENTIALS_OPTIONS_TEST_SRC))))
@@ -14744,14 +14739,6 @@ endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/client_certs.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_cert.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_key.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/test_root_cert.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
 $(OBJDIR)/$(CONFIG)/test/core/security/grpc_tls_credentials_options_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
 
 deps_grpc_tls_credentials_options_test: $(GRPC_TLS_CREDENTIALS_OPTIONS_TEST_OBJS:.o=.dep)
@@ -16211,49 +16198,6 @@ endif
 endif
 
 
-OPTIONAL_TEST_SRC = \
-    test/core/gprpp/optional_test.cc \
-
-OPTIONAL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(OPTIONAL_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/optional_test: openssl_dep_error
-
-else
-
-
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
-
-$(BINDIR)/$(CONFIG)/optional_test: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/optional_test: $(PROTOBUF_DEP) $(OPTIONAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-       $(E) "[LD]      Linking $@"
-       $(Q) mkdir -p `dirname $@`
-       $(Q) $(LDXX) $(LDFLAGS) $(OPTIONAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/optional_test
-
-endif
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/gprpp/optional_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-deps_optional_test: $(OPTIONAL_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(OPTIONAL_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 ORPHANABLE_TEST_SRC = \
     test/core/gprpp/orphanable_test.cc \
 
@@ -17915,10 +17859,6 @@ endif
 
 
 SSL_SERVER_FUZZER_SRC = \
-    test/core/end2end/data/client_certs.cc \
-    test/core/end2end/data/server1_cert.cc \
-    test/core/end2end/data/server1_key.cc \
-    test/core/end2end/data/test_root_cert.cc \
     test/core/security/ssl_server_fuzzer.cc \
     test/core/util/fuzzer_corpus_test.cc \
 
@@ -17951,14 +17891,6 @@ endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/client_certs.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_cert.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_key.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/test_root_cert.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
 $(OBJDIR)/$(CONFIG)/test/core/security/ssl_server_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
 
 $(OBJDIR)/$(CONFIG)/test/core/util/fuzzer_corpus_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
@@ -18243,49 +18175,6 @@ endif
 endif
 
 
-STRING_VIEW_TEST_SRC = \
-    test/core/gprpp/string_view_test.cc \
-
-STRING_VIEW_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STRING_VIEW_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/string_view_test: openssl_dep_error
-
-else
-
-
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
-
-$(BINDIR)/$(CONFIG)/string_view_test: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/string_view_test: $(PROTOBUF_DEP) $(STRING_VIEW_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-       $(E) "[LD]      Linking $@"
-       $(Q) mkdir -p `dirname $@`
-       $(Q) $(LDXX) $(LDFLAGS) $(STRING_VIEW_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/string_view_test
-
-endif
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/gprpp/string_view_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-deps_string_view_test: $(STRING_VIEW_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(STRING_VIEW_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 TEST_CPP_CLIENT_CREDENTIALS_TEST_SRC = \
     test/cpp/client/credentials_test.cc \
 
@@ -18601,10 +18490,6 @@ endif
 
 
 TLS_SECURITY_CONNECTOR_TEST_SRC = \
-    test/core/end2end/data/client_certs.cc \
-    test/core/end2end/data/server1_cert.cc \
-    test/core/end2end/data/server1_key.cc \
-    test/core/end2end/data/test_root_cert.cc \
     test/core/security/tls_security_connector_test.cc \
 
 TLS_SECURITY_CONNECTOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TLS_SECURITY_CONNECTOR_TEST_SRC))))
@@ -18636,14 +18521,6 @@ endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/client_certs.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_cert.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_key.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/test_root_cert.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
 $(OBJDIR)/$(CONFIG)/test/core/security/tls_security_connector_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
 
 deps_tls_security_connector_test: $(TLS_SECURITY_CONNECTOR_TEST_OBJS:.o=.dep)
@@ -19286,6 +19163,7 @@ BORINGSSL_CRYPTO_TEST_SRC = \
     third_party/boringssl-with-bazel/src/crypto/fipsmodule/md5/md5_test.cc \
     third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/gcm_test.cc \
     third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/ctrdrbg_test.cc \
+    third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/fork_detect_test.cc \
     third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/sha_test.cc \
     third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf_test.cc \
     third_party/boringssl-with-bazel/src/crypto/hmac_extra/hmac_test.cc \
@@ -19309,6 +19187,7 @@ BORINGSSL_CRYPTO_TEST_SRC = \
     third_party/boringssl-with-bazel/src/crypto/test/file_test_gtest.cc \
     third_party/boringssl-with-bazel/src/crypto/test/gtest_main.cc \
     third_party/boringssl-with-bazel/src/crypto/thread_test.cc \
+    third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token_test.cc \
     third_party/boringssl-with-bazel/src/crypto/x509/x509_test.cc \
     third_party/boringssl-with-bazel/src/crypto/x509/x509_time_test.cc \
     third_party/boringssl-with-bazel/src/crypto/x509v3/tab_test.cc \
@@ -19410,6 +19289,8 @@ $(OBJDIR)/$(CONFIG)/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes
 
 $(OBJDIR)/$(CONFIG)/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/ctrdrbg_test.o:  $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a
 
+$(OBJDIR)/$(CONFIG)/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/fork_detect_test.o:  $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a
+
 $(OBJDIR)/$(CONFIG)/third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/sha_test.o:  $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a
 
 $(OBJDIR)/$(CONFIG)/third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf_test.o:  $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a
@@ -19456,6 +19337,8 @@ $(OBJDIR)/$(CONFIG)/third_party/boringssl-with-bazel/src/crypto/test/gtest_main.
 
 $(OBJDIR)/$(CONFIG)/third_party/boringssl-with-bazel/src/crypto/thread_test.o:  $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a
 
+$(OBJDIR)/$(CONFIG)/third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token_test.o:  $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a
+
 $(OBJDIR)/$(CONFIG)/third_party/boringssl-with-bazel/src/crypto/x509/x509_test.o:  $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a
 
 $(OBJDIR)/$(CONFIG)/third_party/boringssl-with-bazel/src/crypto/x509/x509_time_test.o:  $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a
@@ -19978,10 +19861,6 @@ endif
 
 
 SSL_SERVER_FUZZER_ONE_ENTRY_SRC = \
-    test/core/end2end/data/client_certs.cc \
-    test/core/end2end/data/server1_cert.cc \
-    test/core/end2end/data/server1_key.cc \
-    test/core/end2end/data/test_root_cert.cc \
     test/core/security/ssl_server_fuzzer.cc \
     test/core/util/one_corpus_entry_fuzzer.cc \
 
@@ -20014,14 +19893,6 @@ endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/client_certs.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_cert.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_key.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/data/test_root_cert.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
 $(OBJDIR)/$(CONFIG)/test/core/security/ssl_server_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
 
 $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
index 3b23d0b..a488eb0 100755 (executable)
--- a/Rakefile
+++ b/Rakefile
@@ -142,7 +142,7 @@ task 'gem:native' do
 
         gem update --system --no-document && \
         bundle && \
-        rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem \
+        rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem pkg/#{spec.full_name}.gem \
           RUBY_CC_VERSION=2.7.0:2.6.0:2.5.0:2.4.0:2.3.0 \
           V=#{verbose} \
           GRPC_CONFIG=#{grpc_config}
index f1eeb51..c3aa3b2 100644 (file)
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -39,6 +39,11 @@ rbe_autoconfig(
         # that want to use other machines (such as LARGE_MACHINE) will override
         # this value.
         gce_machine_type = "n1-highmem-2",
+        # WARNING: the os_family constraint has only been introduced recently
+        # and older release branches select workers solely based on gce_machine_type.
+        # Worker pools needs to be configured with care to avoid accidentally running
+        # linux jobs on windows pool and vice versa (which would lead to a test breakage)
+        os_family = "Linux",
     ),
     # use exec_properties instead of deprecated remote_execution_properties
     use_legacy_platform_definition = False,
index bc66dfe..05c2cc2 100644 (file)
@@ -131,9 +131,12 @@ def grpc_deps():
             name = "boringssl",
             # Use github mirror instead of https://boringssl.googlesource.com/boringssl
             # to obtain a boringssl archive with consistent sha256
-            sha256 = "a3d4de4f03cb321ef943678d72a045c9a19d26b23d6f4e313f97600c65201a27",
-            strip_prefix = "boringssl-1c2769383f027befac5b75b6cedd25daf3bf4dcf",
-            url = "https://github.com/google/boringssl/archive/1c2769383f027befac5b75b6cedd25daf3bf4dcf.tar.gz",
+            sha256 = "3909329105e28cfeedcd8028865c92f1081ae2524a0ad6c09eba5d91d9ae3869",
+            strip_prefix = "boringssl-3ab047a8e377083a9b38dc908fe1612d5743a021",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/3ab047a8e377083a9b38dc908fe1612d5743a021.tar.gz",
+                "https://github.com/google/boringssl/archive/3ab047a8e377083a9b38dc908fe1612d5743a021.tar.gz",
+            ],
         )
 
     if "zlib" not in native.existing_rules():
@@ -142,15 +145,21 @@ def grpc_deps():
             build_file = "@com_github_grpc_grpc//third_party:zlib.BUILD",
             sha256 = "6d4d6640ca3121620995ee255945161821218752b551a1a180f4215f7d124d45",
             strip_prefix = "zlib-cacf7f1d4e3d44d871b605da3b647f07d718623f",
-            url = "https://github.com/madler/zlib/archive/cacf7f1d4e3d44d871b605da3b647f07d718623f.tar.gz",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/madler/zlib/archive/cacf7f1d4e3d44d871b605da3b647f07d718623f.tar.gz",
+                "https://github.com/madler/zlib/archive/cacf7f1d4e3d44d871b605da3b647f07d718623f.tar.gz",
+            ],
         )
 
     if "com_google_protobuf" not in native.existing_rules():
         http_archive(
             name = "com_google_protobuf",
-            sha256 = "51398b0b97b353c1c226d0ade0bae80c80380e691cba7c1a108918986784a1c7",
-            strip_prefix = "protobuf-29cd005ce1fe1a8fabf11e325cb13006a6646d59",
-            url = "https://github.com/google/protobuf/archive/29cd005ce1fe1a8fabf11e325cb13006a6646d59.tar.gz",
+            sha256 = "efaf69303e01caccc2447064fc1832dfd23c0c130df0dc5fc98a13185bb7d1a7",
+            strip_prefix = "protobuf-678da4f76eb9168c9965afc2149944a66cd48546",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/protobuf/archive/678da4f76eb9168c9965afc2149944a66cd48546.tar.gz",
+                "https://github.com/google/protobuf/archive/678da4f76eb9168c9965afc2149944a66cd48546.tar.gz",
+            ],
         )
 
     if "com_github_google_googletest" not in native.existing_rules():
@@ -158,7 +167,11 @@ def grpc_deps():
             name = "com_github_google_googletest",
             sha256 = "443d383db648ebb8e391382c0ab63263b7091d03197f304390baac10f178a468",
             strip_prefix = "googletest-c9ccac7cb7345901884aabf5d1a786cfa6e2f397",
-            url = "https://github.com/google/googletest/archive/c9ccac7cb7345901884aabf5d1a786cfa6e2f397.tar.gz",  # 2019-08-19
+            urls = [
+                # 2019-08-19
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/googletest/archive/c9ccac7cb7345901884aabf5d1a786cfa6e2f397.tar.gz",
+                "https://github.com/google/googletest/archive/c9ccac7cb7345901884aabf5d1a786cfa6e2f397.tar.gz",
+            ],
         )
 
     if "rules_cc" not in native.existing_rules():
@@ -166,7 +179,11 @@ def grpc_deps():
             name = "rules_cc",
             sha256 = "35f2fb4ea0b3e61ad64a369de284e4fbbdcdba71836a5555abb5e194cf119509",
             strip_prefix = "rules_cc-624b5d59dfb45672d4239422fa1e3de1822ee110",
-            url = "https://github.com/bazelbuild/rules_cc/archive/624b5d59dfb45672d4239422fa1e3de1822ee110.tar.gz",  #2019-08-15
+            urls = [
+                #2019-08-15
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/rules_cc/archive/624b5d59dfb45672d4239422fa1e3de1822ee110.tar.gz",
+                "https://github.com/bazelbuild/rules_cc/archive/624b5d59dfb45672d4239422fa1e3de1822ee110.tar.gz",
+            ],
         )
 
     if "com_github_gflags_gflags" not in native.existing_rules():
@@ -174,7 +191,10 @@ def grpc_deps():
             name = "com_github_gflags_gflags",
             sha256 = "63ae70ea3e05780f7547d03503a53de3a7d2d83ad1caaa443a31cb20aea28654",
             strip_prefix = "gflags-28f50e0fed19872e0fd50dd23ce2ee8cd759338e",
-            url = "https://github.com/gflags/gflags/archive/28f50e0fed19872e0fd50dd23ce2ee8cd759338e.tar.gz",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/gflags/gflags/archive/28f50e0fed19872e0fd50dd23ce2ee8cd759338e.tar.gz",
+                "https://github.com/gflags/gflags/archive/28f50e0fed19872e0fd50dd23ce2ee8cd759338e.tar.gz",
+            ],
         )
 
     if "com_github_google_benchmark" not in native.existing_rules():
@@ -182,7 +202,10 @@ def grpc_deps():
             name = "com_github_google_benchmark",
             sha256 = "f68aec93154d010324c05bcd8c5cc53468b87af88d87acb5ddcfaa1bba044837",
             strip_prefix = "benchmark-090faecb454fbd6e6e17a75ef8146acb037118d4",
-            url = "https://github.com/google/benchmark/archive/090faecb454fbd6e6e17a75ef8146acb037118d4.tar.gz",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/benchmark/archive/090faecb454fbd6e6e17a75ef8146acb037118d4.tar.gz",
+                "https://github.com/google/benchmark/archive/090faecb454fbd6e6e17a75ef8146acb037118d4.tar.gz",
+            ],
         )
 
     if "com_github_cares_cares" not in native.existing_rules():
@@ -191,7 +214,10 @@ def grpc_deps():
             build_file = "@com_github_grpc_grpc//third_party:cares/cares.BUILD",
             sha256 = "e8c2751ddc70fed9dc6f999acd92e232d5846f009ee1674f8aee81f19b2b915a",
             strip_prefix = "c-ares-e982924acee7f7313b4baa4ee5ec000c5e373c30",
-            url = "https://github.com/c-ares/c-ares/archive/e982924acee7f7313b4baa4ee5ec000c5e373c30.tar.gz",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/c-ares/c-ares/archive/e982924acee7f7313b4baa4ee5ec000c5e373c30.tar.gz",
+                "https://github.com/c-ares/c-ares/archive/e982924acee7f7313b4baa4ee5ec000c5e373c30.tar.gz",
+            ],
         )
 
     if "com_google_absl" not in native.existing_rules():
@@ -199,7 +225,10 @@ def grpc_deps():
             name = "com_google_absl",
             sha256 = "f368a8476f4e2e0eccf8a7318b98dafbe30b2600f4e3cf52636e5eb145aba06a",
             strip_prefix = "abseil-cpp-df3ea785d8c30a9503321a3d35ee7d35808f190d",
-            url = "https://github.com/abseil/abseil-cpp/archive/df3ea785d8c30a9503321a3d35ee7d35808f190d.tar.gz",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/abseil/abseil-cpp/archive/df3ea785d8c30a9503321a3d35ee7d35808f190d.tar.gz",
+                "https://github.com/abseil/abseil-cpp/archive/df3ea785d8c30a9503321a3d35ee7d35808f190d.tar.gz",
+            ],
         )
 
     if "bazel_toolchains" not in native.existing_rules():
@@ -209,8 +238,8 @@ def grpc_deps():
             sha256 = "0b36eef8a66f39c8dbae88e522d5bbbef49d5e66e834a982402c79962281be10",
             strip_prefix = "bazel-toolchains-1.0.1",
             urls = [
-                "https://github.com/bazelbuild/bazel-toolchains/releases/download/1.0.1/bazel-toolchains-1.0.1.tar.gz",
                 "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/1.0.1.tar.gz",
+                "https://github.com/bazelbuild/bazel-toolchains/releases/download/1.0.1/bazel-toolchains-1.0.1.tar.gz",
             ],
         )
 
@@ -229,43 +258,59 @@ def grpc_deps():
             name = "io_opencensus_cpp",
             sha256 = "90d6fafa8b1a2ea613bf662731d3086e1c2ed286f458a95c81744df2dbae41b1",
             strip_prefix = "opencensus-cpp-c9a4da319bc669a772928ffc55af4a61be1a1176",
-            url = "https://github.com/census-instrumentation/opencensus-cpp/archive/c9a4da319bc669a772928ffc55af4a61be1a1176.tar.gz",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/census-instrumentation/opencensus-cpp/archive/c9a4da319bc669a772928ffc55af4a61be1a1176.tar.gz",
+                "https://github.com/census-instrumentation/opencensus-cpp/archive/c9a4da319bc669a772928ffc55af4a61be1a1176.tar.gz",
+            ],
         )
     if "upb" not in native.existing_rules():
         http_archive(
             name = "upb",
             sha256 = "e9c136e56b98c8eb48ad1c9f8df4a6348e99f9f336ee6199c4259a312c2e3598",
             strip_prefix = "upb-d8f3d6f9d415b31f3ce56d46791706c38fa311bc",
-            url = "https://github.com/protocolbuffers/upb/archive/d8f3d6f9d415b31f3ce56d46791706c38fa311bc.tar.gz",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/protocolbuffers/upb/archive/d8f3d6f9d415b31f3ce56d46791706c38fa311bc.tar.gz",
+                "https://github.com/protocolbuffers/upb/archive/d8f3d6f9d415b31f3ce56d46791706c38fa311bc.tar.gz",
+            ],
         )
 
     if "envoy_api" not in native.existing_rules():
         http_archive(
             name = "envoy_api",
-            sha256 = "4ba23e0370ec358d1050c020e00cd020f03644a733aaf8fd85cc43d17b92236a",
-            strip_prefix = "data-plane-api-0487bbb43c3e8b54c7332f74ba7344d8265774f7",
-            url = "https://github.com/envoyproxy/data-plane-api/archive/0487bbb43c3e8b54c7332f74ba7344d8265774f7.tar.gz",
+            sha256 = "9150f920abd3e710e0e58519cd769822f13d7a56988f2c34c2008815ec8d9c88",
+            strip_prefix = "data-plane-api-8dcc476be69437b505af181a6e8b167fdb101d7e",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/envoyproxy/data-plane-api/archive/8dcc476be69437b505af181a6e8b167fdb101d7e.tar.gz",
+                "https://github.com/envoyproxy/data-plane-api/archive/8dcc476be69437b505af181a6e8b167fdb101d7e.tar.gz",
+            ],
         )
 
     if "io_bazel_rules_go" not in native.existing_rules():
         http_archive(
             name = "io_bazel_rules_go",
-            urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.18.5/rules_go-0.18.5.tar.gz"],
             sha256 = "a82a352bffae6bee4e95f68a8d80a70e87f42c4741e6a448bec11998fcc82329",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/rules_go/releases/download/0.18.5/rules_go-0.18.5.tar.gz",
+                "https://github.com/bazelbuild/rules_go/releases/download/0.18.5/rules_go-0.18.5.tar.gz",
+            ],
         )
 
     if "build_bazel_rules_apple" not in native.existing_rules():
         http_archive(
             name = "build_bazel_rules_apple",
-            url = "https://github.com/bazelbuild/rules_apple/archive/b869b0d3868d78a1d4ffd866ccb304fb68aa12c3.tar.gz",
             strip_prefix = "rules_apple-b869b0d3868d78a1d4ffd866ccb304fb68aa12c3",
             sha256 = "bdc8e66e70b8a75da23b79f1f8c6207356df07d041d96d2189add7ee0780cf4e",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/rules_apple/archive/b869b0d3868d78a1d4ffd866ccb304fb68aa12c3.tar.gz",
+                "https://github.com/bazelbuild/rules_apple/archive/b869b0d3868d78a1d4ffd866ccb304fb68aa12c3.tar.gz",
+            ],
         )
 
     if "build_bazel_apple_support" not in native.existing_rules():
         http_archive(
             name = "build_bazel_apple_support",
             urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/apple_support/releases/download/0.7.1/apple_support.0.7.1.tar.gz",
                 "https://github.com/bazelbuild/apple_support/releases/download/0.7.1/apple_support.0.7.1.tar.gz",
             ],
             sha256 = "122ebf7fe7d1c8e938af6aeaee0efe788a3a2449ece5a8d6a428cb18d6f88033",
@@ -277,7 +322,10 @@ def grpc_deps():
             build_file = "@com_github_grpc_grpc//third_party:libuv.BUILD",
             sha256 = "dfb4fe1ff0b47340978490a14bf253475159ecfcbad46ab2a350c78f9ce3360f",
             strip_prefix = "libuv-15ae750151ac9341e5945eb38f8982d59fb99201",
-            url = "https://github.com/libuv/libuv/archive/15ae750151ac9341e5945eb38f8982d59fb99201.tar.gz",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/libuv/libuv/archive/15ae750151ac9341e5945eb38f8982d59fb99201.tar.gz",
+                "https://github.com/libuv/libuv/archive/15ae750151ac9341e5945eb38f8982d59fb99201.tar.gz",
+            ],
         )
 
     grpc_python_deps()
@@ -301,7 +349,10 @@ def grpc_test_only_deps():
             name = "com_github_twisted_twisted",
             sha256 = "ca17699d0d62eafc5c28daf2c7d0a18e62ae77b4137300b6c7d7868b39b06139",
             strip_prefix = "twisted-twisted-17.5.0",
-            url = "https://github.com/twisted/twisted/archive/twisted-17.5.0.zip",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/twisted/twisted/archive/twisted-17.5.0.zip",
+                "https://github.com/twisted/twisted/archive/twisted-17.5.0.zip",
+            ],
             build_file = "@com_github_grpc_grpc//third_party:twisted.BUILD",
         )
 
@@ -310,7 +361,10 @@ def grpc_test_only_deps():
             name = "com_github_yaml_pyyaml",
             sha256 = "6b4314b1b2051ddb9d4fcd1634e1fa9c1bb4012954273c9ff3ef689f6ec6c93e",
             strip_prefix = "pyyaml-3.12",
-            url = "https://github.com/yaml/pyyaml/archive/3.12.zip",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/yaml/pyyaml/archive/3.12.zip",
+                "https://github.com/yaml/pyyaml/archive/3.12.zip",
+            ],
             build_file = "@com_github_grpc_grpc//third_party:yaml.BUILD",
         )
 
@@ -319,7 +373,10 @@ def grpc_test_only_deps():
             name = "com_github_twisted_incremental",
             sha256 = "f0ca93359ee70243ff7fbf2d904a6291810bd88cb80ed4aca6fa77f318a41a36",
             strip_prefix = "incremental-incremental-17.5.0",
-            url = "https://github.com/twisted/incremental/archive/incremental-17.5.0.zip",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/twisted/incremental/archive/incremental-17.5.0.zip",
+                "https://github.com/twisted/incremental/archive/incremental-17.5.0.zip",
+            ],
             build_file = "@com_github_grpc_grpc//third_party:incremental.BUILD",
         )
 
@@ -328,7 +385,10 @@ def grpc_test_only_deps():
             name = "com_github_zopefoundation_zope_interface",
             sha256 = "e9579fc6149294339897be3aa9ecd8a29217c0b013fe6f44fcdae00e3204198a",
             strip_prefix = "zope.interface-4.4.3",
-            url = "https://github.com/zopefoundation/zope.interface/archive/4.4.3.zip",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/zopefoundation/zope.interface/archive/4.4.3.zip",
+                "https://github.com/zopefoundation/zope.interface/archive/4.4.3.zip",
+            ],
             build_file = "@com_github_grpc_grpc//third_party:zope_interface.BUILD",
         )
 
@@ -337,6 +397,9 @@ def grpc_test_only_deps():
             name = "com_github_twisted_constantly",
             sha256 = "2702cd322161a579d2c0dbf94af4e57712eedc7bd7bbbdc554a230544f7d346c",
             strip_prefix = "constantly-15.1.0",
-            url = "https://github.com/twisted/constantly/archive/15.1.0.zip",
+            urls = [
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/twisted/constantly/archive/15.1.0.zip",
+                "https://github.com/twisted/constantly/archive/15.1.0.zip",
+            ],
             build_file = "@com_github_grpc_grpc//third_party:constantly.BUILD",
         )
diff --git a/bazel/update_mirror.sh b/bazel/update_mirror.sh
new file mode 100755 (executable)
index 0000000..7c2fe46
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/bash
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Script to upload github archives for bazel dependencies to GCS, creating a reliable mirror link.
+# Archives are copied to "grpc-bazel-mirror" GCS bucket (https://console.cloud.google.com/storage/browser/grpc-bazel-mirror?project=grpc-testing)
+# and will by downloadable with the https://storage.googleapis.com/grpc-bazel-mirror/ prefix.
+#
+# This script should be run each time bazel dependencies are updated.
+
+set -e
+
+cd $(dirname $0)/..
+
+# Create a temp directory to hold the versioned tarball,
+# and clean it up when the script exits.
+tmpdir="$(mktemp -d)"
+function cleanup {
+  rm -rf "$tmpdir"
+}
+trap cleanup EXIT
+
+function upload {
+  local file="$1"
+
+  echo "Downloading https://${file}"
+  curl -L --fail --output "${tmpdir}/archive" "https://${file}"
+
+  echo "Uploading https://${file} to https://storage.googleapis.com/grpc-bazel-mirror/${file}"
+  gsutil cp -n "${tmpdir}/archive" "gs://grpc-bazel-mirror/${file}"  # "-n" will skip existing files
+
+  rm -rf "${tmpdir}/archive"
+}
+
+# How to check that all mirror URLs work:
+# 1. clean $HOME/.cache/bazel
+# 2. bazel clean --expunge
+# 3. bazel sync (failed downloads will print warnings)
+
+# A specific link can be upload manually by running e.g.
+# upload "github.com/google/boringssl/archive/1c2769383f027befac5b75b6cedd25daf3bf4dcf.tar.gz"
+
+# bazel binaries used by the tools/bazel wrapper script
+upload github.com/bazelbuild/bazel/releases/download/1.0.0/bazel-1.0.0-linux-x86_64
+upload github.com/bazelbuild/bazel/releases/download/1.0.0/bazel-1.0.0-darwin-x86_64
+upload github.com/bazelbuild/bazel/releases/download/1.0.0/bazel-1.0.0-windows-x86_64.exe
+
+# Collect the github archives to mirror from grpc_deps.bzl
+grep -o '"https://github.com/[^"]*"' bazel/grpc_deps.bzl | sed 's/^"https:\/\///' | sed 's/"$//' | while read -r line ; do
+    echo "Updating mirror for ${line}"
+    upload "${line}"
+done
index 65467e9..631005f 100644 (file)
@@ -49,6 +49,7 @@ libs:
   - test/core/end2end/tests/cancel_in_a_vacuum.cc
   - test/core/end2end/tests/cancel_with_status.cc
   - test/core/end2end/tests/channelz.cc
+  - test/core/end2end/tests/client_streaming.cc
   - test/core/end2end/tests/compressed_payload.cc
   - test/core/end2end/tests/connectivity.cc
   - test/core/end2end/tests/default_host.cc
@@ -157,6 +158,7 @@ libs:
   - test/core/end2end/tests/cancel_in_a_vacuum.cc
   - test/core/end2end/tests/cancel_with_status.cc
   - test/core/end2end/tests/channelz.cc
+  - test/core/end2end/tests/client_streaming.cc
   - test/core/end2end/tests/compressed_payload.cc
   - test/core/end2end/tests/connectivity.cc
   - test/core/end2end/tests/default_host.cc
@@ -300,7 +302,6 @@ libs:
   - src/core/lib/gprpp/map.h
   - src/core/lib/gprpp/memory.h
   - src/core/lib/gprpp/mpscq.h
-  - src/core/lib/gprpp/string_view.h
   - src/core/lib/gprpp/sync.h
   - src/core/lib/gprpp/thd.h
   - src/core/lib/profiling/timers.h
@@ -410,6 +411,8 @@ libs:
   - src/core/ext/filters/client_channel/retry_throttle.h
   - src/core/ext/filters/client_channel/server_address.h
   - src/core/ext/filters/client_channel/service_config.h
+  - src/core/ext/filters/client_channel/service_config_call_data.h
+  - src/core/ext/filters/client_channel/service_config_parser.h
   - src/core/ext/filters/client_channel/subchannel.h
   - src/core/ext/filters/client_channel/subchannel_interface.h
   - src/core/ext/filters/client_channel/subchannel_pool_interface.h
@@ -458,18 +461,24 @@ libs:
   - src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h
   - src/core/ext/upb-generated/envoy/annotations/resource.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/cds.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/eds.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h
@@ -490,6 +499,7 @@ libs:
   - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h
   - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h
   - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h
+  - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h
   - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h
   - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h
   - src/core/ext/upb-generated/envoy/type/http.upb.h
@@ -518,6 +528,7 @@ libs:
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h
   - src/core/ext/upb-generated/udpa/annotations/migrate.upb.h
   - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h
+  - src/core/ext/upb-generated/udpa/annotations/status.upb.h
   - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h
   - src/core/ext/upb-generated/validate/validate.upb.h
   - src/core/lib/avl/avl.h
@@ -546,8 +557,6 @@ libs:
   - src/core/lib/debug/trace.h
   - src/core/lib/gprpp/atomic.h
   - src/core/lib/gprpp/debug_location.h
-  - src/core/lib/gprpp/inlined_vector.h
-  - src/core/lib/gprpp/optional.h
   - src/core/lib/gprpp/orphanable.h
   - src/core/lib/gprpp/ref_counted.h
   - src/core/lib/gprpp/ref_counted_ptr.h
@@ -784,6 +793,7 @@ libs:
   - src/core/ext/filters/client_channel/retry_throttle.cc
   - src/core/ext/filters/client_channel/server_address.cc
   - src/core/ext/filters/client_channel/service_config.cc
+  - src/core/ext/filters/client_channel/service_config_parser.cc
   - src/core/ext/filters/client_channel/subchannel.cc
   - src/core/ext/filters/client_channel/subchannel_pool_interface.cc
   - src/core/ext/filters/client_channel/xds/xds_api.cc
@@ -841,18 +851,24 @@ libs:
   - src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c
   - src/core/ext/upb-generated/envoy/annotations/resource.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/cds.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/eds.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c
@@ -873,6 +889,7 @@ libs:
   - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c
   - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c
   - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c
+  - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c
   - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c
   - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c
   - src/core/ext/upb-generated/envoy/type/http.upb.c
@@ -901,6 +918,7 @@ libs:
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
   - src/core/ext/upb-generated/udpa/annotations/migrate.upb.c
   - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c
+  - src/core/ext/upb-generated/udpa/annotations/status.upb.c
   - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
   - src/core/ext/upb-generated/validate/validate.upb.c
   - src/core/lib/avl/avl.cc
@@ -1316,6 +1334,8 @@ libs:
   - src/core/ext/filters/client_channel/retry_throttle.h
   - src/core/ext/filters/client_channel/server_address.h
   - src/core/ext/filters/client_channel/service_config.h
+  - src/core/ext/filters/client_channel/service_config_call_data.h
+  - src/core/ext/filters/client_channel/service_config_parser.h
   - src/core/ext/filters/client_channel/subchannel.h
   - src/core/ext/filters/client_channel/subchannel_interface.h
   - src/core/ext/filters/client_channel/subchannel_pool_interface.h
@@ -1364,18 +1384,24 @@ libs:
   - src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h
   - src/core/ext/upb-generated/envoy/annotations/resource.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/cds.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/eds.upb.h
   - src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h
@@ -1396,6 +1422,7 @@ libs:
   - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h
   - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h
   - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h
+  - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h
   - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h
   - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h
   - src/core/ext/upb-generated/envoy/type/http.upb.h
@@ -1421,6 +1448,7 @@ libs:
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h
   - src/core/ext/upb-generated/udpa/annotations/migrate.upb.h
   - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h
+  - src/core/ext/upb-generated/udpa/annotations/status.upb.h
   - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h
   - src/core/ext/upb-generated/validate/validate.upb.h
   - src/core/lib/avl/avl.h
@@ -1449,8 +1477,6 @@ libs:
   - src/core/lib/debug/trace.h
   - src/core/lib/gprpp/atomic.h
   - src/core/lib/gprpp/debug_location.h
-  - src/core/lib/gprpp/inlined_vector.h
-  - src/core/lib/gprpp/optional.h
   - src/core/lib/gprpp/orphanable.h
   - src/core/lib/gprpp/ref_counted.h
   - src/core/lib/gprpp/ref_counted_ptr.h
@@ -1626,6 +1652,7 @@ libs:
   - src/core/ext/filters/client_channel/retry_throttle.cc
   - src/core/ext/filters/client_channel/server_address.cc
   - src/core/ext/filters/client_channel/service_config.cc
+  - src/core/ext/filters/client_channel/service_config_parser.cc
   - src/core/ext/filters/client_channel/subchannel.cc
   - src/core/ext/filters/client_channel/subchannel_pool_interface.cc
   - src/core/ext/filters/client_channel/xds/xds_api.cc
@@ -1681,18 +1708,24 @@ libs:
   - src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c
   - src/core/ext/upb-generated/envoy/annotations/resource.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/cds.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/eds.upb.c
   - src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c
@@ -1713,6 +1746,7 @@ libs:
   - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c
   - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c
   - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c
+  - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c
   - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c
   - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c
   - src/core/ext/upb-generated/envoy/type/http.upb.c
@@ -1738,6 +1772,7 @@ libs:
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
   - src/core/ext/upb-generated/udpa/annotations/migrate.upb.c
   - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c
+  - src/core/ext/upb-generated/udpa/annotations/status.upb.c
   - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
   - src/core/ext/upb-generated/validate/validate.upb.c
   - src/core/lib/avl/avl.cc
@@ -3141,6 +3176,7 @@ targets:
   uses_polling: false
 - name: concurrent_connectivity_test
   build: test
+  run: false
   language: c
   headers: []
   src:
@@ -4089,13 +4125,8 @@ targets:
   build: test
   run: false
   language: c
-  headers:
-  - test/core/end2end/data/ssl_test_data.h
+  headers: []
   src:
-  - test/core/end2end/data/client_certs.cc
-  - test/core/end2end/data/server1_cert.cc
-  - test/core/end2end/data/server1_key.cc
-  - test/core/end2end/data/test_root_cert.cc
   - test/core/surface/sequential_connectivity_test.cc
   deps:
   - grpc_test_util
@@ -5318,6 +5349,7 @@ targets:
 - name: cancel_ares_query_test
   gtest: true
   build: test
+  run: false
   language: c++
   headers:
   - test/core/end2end/cq_verifier.h
@@ -5442,7 +5474,6 @@ targets:
 - name: channelz_test
   gtest: true
   build: test
-  run: false
   language: c++
   headers:
   - test/cpp/util/channel_trace_proto_helper.h
@@ -5992,13 +6023,8 @@ targets:
   gtest: true
   build: test
   language: c++
-  headers:
-  - test/core/end2end/data/ssl_test_data.h
+  headers: []
   src:
-  - test/core/end2end/data/client_certs.cc
-  - test/core/end2end/data/server1_cert.cc
-  - test/core/end2end/data/server1_key.cc
-  - test/core/end2end/data/test_root_cert.cc
   - test/core/security/grpc_tls_credentials_options_test.cc
   deps:
   - grpc_test_util
@@ -6536,19 +6562,6 @@ targets:
   - benchmark
   benchmark: true
   defaults: benchmark
-- name: optional_test
-  gtest: true
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/core/gprpp/optional_test.cc
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr
-  - address_sorting
-  - upb
 - name: orphanable_test
   gtest: true
   build: test
@@ -7144,13 +7157,8 @@ targets:
 - name: ssl_server_fuzzer
   build: fuzzer
   language: c++
-  headers:
-  - test/core/end2end/data/ssl_test_data.h
+  headers: []
   src:
-  - test/core/end2end/data/client_certs.cc
-  - test/core/end2end/data/server1_cert.cc
-  - test/core/end2end/data/server1_key.cc
-  - test/core/end2end/data/test_root_cert.cc
   - test/core/security/ssl_server_fuzzer.cc
   - test/core/util/fuzzer_corpus_test.cc
   deps:
@@ -7256,19 +7264,6 @@ targets:
   - address_sorting
   - upb
   uses_polling: false
-- name: string_view_test
-  gtest: true
-  build: test
-  language: c++
-  headers: []
-  src:
-  - test/core/gprpp/string_view_test.cc
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr
-  - address_sorting
-  - upb
 - name: test_cpp_client_credentials_test
   gtest: true
   build: test
@@ -7391,13 +7386,8 @@ targets:
   gtest: true
   build: test
   language: c++
-  headers:
-  - test/core/end2end/data/ssl_test_data.h
+  headers: []
   src:
-  - test/core/end2end/data/client_certs.cc
-  - test/core/end2end/data/server1_cert.cc
-  - test/core/end2end/data/server1_key.cc
-  - test/core/end2end/data/test_root_cert.cc
   - test/core/security/tls_security_connector_test.cc
   deps:
   - grpc_test_util
index 55660c9..83bddd0 100644 (file)
@@ -14,8 +14,8 @@ settings:
   '#10': See the expand_version.py for all the quirks here
   core_version: 10.0.0
   csharp_major_version: 2
-  g_stands_for: gringotts
-  version: 1.29.1
+  g_stands_for: gradius
+  version: 1.30.0
 targets:
 - name: check_epollexclusive
   build: tool
index 325945b..cd1019a 100644 (file)
--- a/config.m4
+++ b/config.m4
@@ -92,6 +92,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/server_address.cc \
     src/core/ext/filters/client_channel/service_config.cc \
+    src/core/ext/filters/client_channel/service_config_parser.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
     src/core/ext/filters/client_channel/xds/xds_api.cc \
@@ -149,18 +150,24 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c \
     src/core/ext/upb-generated/envoy/annotations/resource.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cds.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/eds.upb.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c \
@@ -181,6 +188,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c \
     src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c \
     src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c \
+    src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c \
     src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c \
     src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c \
     src/core/ext/upb-generated/envoy/type/http.upb.c \
@@ -209,6 +217,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
     src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
     src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/status.upb.c \
     src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
     src/core/ext/upb-generated/validate/validate.upb.c \
     src/core/lib/avl/avl.cc \
@@ -618,6 +627,7 @@ if test "$PHP_GRPC" != "no"; then
     third_party/boringssl-with-bazel/src/crypto/cpu-intel.c \
     third_party/boringssl-with-bazel/src/crypto/cpu-ppc64le.c \
     third_party/boringssl-with-bazel/src/crypto/crypto.c \
+    third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519.c \
     third_party/boringssl-with-bazel/src/crypto/curve25519/spake25519.c \
     third_party/boringssl-with-bazel/src/crypto/dh/check.c \
     third_party/boringssl-with-bazel/src/crypto/dh/dh.c \
@@ -628,6 +638,7 @@ if test "$PHP_GRPC" != "no"; then
     third_party/boringssl-with-bazel/src/crypto/dsa/dsa_asn1.c \
     third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_asn1.c \
     third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_derive.c \
+    third_party/boringssl-with-bazel/src/crypto/ec_extra/hash_to_curve.c \
     third_party/boringssl-with-bazel/src/crypto/ecdh_extra/ecdh_extra.c \
     third_party/boringssl-with-bazel/src/crypto/ecdsa_extra/ecdsa_asn1.c \
     third_party/boringssl-with-bazel/src/crypto/engine/engine.c \
@@ -692,6 +703,8 @@ if test "$PHP_GRPC" != "no"; then
     third_party/boringssl-with-bazel/src/crypto/thread_none.c \
     third_party/boringssl-with-bazel/src/crypto/thread_pthread.c \
     third_party/boringssl-with-bazel/src/crypto/thread_win.c \
+    third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c \
+    third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token.c \
     third_party/boringssl-with-bazel/src/crypto/x509/a_digest.c \
     third_party/boringssl-with-bazel/src/crypto/x509/a_sign.c \
     third_party/boringssl-with-bazel/src/crypto/x509/a_strex.c \
@@ -810,7 +823,6 @@ if test "$PHP_GRPC" != "no"; then
     third_party/boringssl-with-bazel/src/ssl/tls13_server.cc \
     third_party/boringssl-with-bazel/src/ssl/tls_method.cc \
     third_party/boringssl-with-bazel/src/ssl/tls_record.cc \
-    third_party/boringssl-with-bazel/src/third_party/fiat/curve25519.c \
     third_party/upb/upb/decode.c \
     third_party/upb/upb/encode.c \
     third_party/upb/upb/msg.c \
@@ -868,6 +880,7 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/filter/accesslog/v2)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/listener/v2)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/trace/v2)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/discovery/v2)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/load_stats/v2)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/type)
@@ -977,9 +990,9 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/rsa_extra)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/siphash)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/stack)
+  PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/trust_token)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/x509)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/x509v3)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/ssl)
-  PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/third_party/fiat)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/upb/upb)
 fi
index 45e9798..8109f91 100644 (file)
@@ -61,6 +61,7 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " +
     "src\\core\\ext\\filters\\client_channel\\server_address.cc " +
     "src\\core\\ext\\filters\\client_channel\\service_config.cc " +
+    "src\\core\\ext\\filters\\client_channel\\service_config_parser.cc " +
     "src\\core\\ext\\filters\\client_channel\\subchannel.cc " +
     "src\\core\\ext\\filters\\client_channel\\subchannel_pool_interface.cc " +
     "src\\core\\ext\\filters\\client_channel\\xds\\xds_api.cc " +
@@ -118,18 +119,24 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\upb-generated\\envoy\\annotations\\deprecation.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\annotations\\resource.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\cert.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\common.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\secret.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\tls.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cds.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster\\circuit_breaker.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster\\filter.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster\\outlier_detection.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\address.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\backoff.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\base.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\config_source.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\event_service_config.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\grpc_service.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\health_check.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\http_uri.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\protocol.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\socket_option.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\discovery.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\eds.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\endpoint.upb.c " +
@@ -150,6 +157,7 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\upb-generated\\envoy\\config\\filter\\accesslog\\v2\\accesslog.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\config\\filter\\network\\http_connection_manager\\v2\\http_connection_manager.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\config\\listener\\v2\\api_listener.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\config\\trace\\v2\\http_tracer.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\service\\discovery\\v2\\ads.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\service\\load_stats\\v2\\lrs.upb.c " +
     "src\\core\\ext\\upb-generated\\envoy\\type\\http.upb.c " +
@@ -178,6 +186,7 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lb\\v1\\load_balancer.upb.c " +
     "src\\core\\ext\\upb-generated\\udpa\\annotations\\migrate.upb.c " +
     "src\\core\\ext\\upb-generated\\udpa\\annotations\\sensitive.upb.c " +
+    "src\\core\\ext\\upb-generated\\udpa\\annotations\\status.upb.c " +
     "src\\core\\ext\\upb-generated\\udpa\\data\\orca\\v1\\orca_load_report.upb.c " +
     "src\\core\\ext\\upb-generated\\validate\\validate.upb.c " +
     "src\\core\\lib\\avl\\avl.cc " +
@@ -587,6 +596,7 @@ if (PHP_GRPC != "no") {
     "third_party\\boringssl-with-bazel\\src\\crypto\\cpu-intel.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\cpu-ppc64le.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\crypto.c " +
+    "third_party\\boringssl-with-bazel\\src\\crypto\\curve25519\\curve25519.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\curve25519\\spake25519.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\dh\\check.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\dh\\dh.c " +
@@ -597,6 +607,7 @@ if (PHP_GRPC != "no") {
     "third_party\\boringssl-with-bazel\\src\\crypto\\dsa\\dsa_asn1.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\ec_extra\\ec_asn1.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\ec_extra\\ec_derive.c " +
+    "third_party\\boringssl-with-bazel\\src\\crypto\\ec_extra\\hash_to_curve.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\ecdh_extra\\ecdh_extra.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\ecdsa_extra\\ecdsa_asn1.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\engine\\engine.c " +
@@ -661,6 +672,8 @@ if (PHP_GRPC != "no") {
     "third_party\\boringssl-with-bazel\\src\\crypto\\thread_none.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\thread_pthread.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\thread_win.c " +
+    "third_party\\boringssl-with-bazel\\src\\crypto\\trust_token\\pmbtoken.c " +
+    "third_party\\boringssl-with-bazel\\src\\crypto\\trust_token\\trust_token.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\x509\\a_digest.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\x509\\a_sign.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\x509\\a_strex.c " +
@@ -779,7 +792,6 @@ if (PHP_GRPC != "no") {
     "third_party\\boringssl-with-bazel\\src\\ssl\\tls13_server.cc " +
     "third_party\\boringssl-with-bazel\\src\\ssl\\tls_method.cc " +
     "third_party\\boringssl-with-bazel\\src\\ssl\\tls_record.cc " +
-    "third_party\\boringssl-with-bazel\\src\\third_party\\fiat\\curve25519.c " +
     "third_party\\upb\\upb\\decode.c " +
     "third_party\\upb\\upb\\encode.c " +
     "third_party\\upb\\upb\\msg.c " +
@@ -880,6 +892,8 @@ if (PHP_GRPC != "no") {
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\filter\\network\\http_connection_manager\\v2");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\listener");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\listener\\v2");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\trace");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\trace\\v2");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\service");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\service\\discovery");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\service\\discovery\\v2");
@@ -1015,11 +1029,10 @@ if (PHP_GRPC != "no") {
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\rsa_extra");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\siphash");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\stack");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\trust_token");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\x509");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\x509v3");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\ssl");
-  FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\third_party");
-  FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\third_party\\fiat");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\upb");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\upb\\upb");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\zlib");
index aa0e1ab..261e76f 100644 (file)
@@ -52,12 +52,12 @@ Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
 
 HTTP2 requires that reserved headers, ones starting with ":" appear before all other headers. Additionally implementations should send **Timeout** immediately after the reserved headers and they should send the **Call-Definition** headers before sending **Custom-Metadata**.
 
-Some gRPC implementations may allow the **Path** format shown above
-to be overridden, but this functionality is strongly discouraged.
-gRPC does not go out of its way to break users that are using this kind
-of override, but we do not actively support it, and some functionality
-(e.g., service config support) will not work when the path is not of
-the form shown above.
+**Path** is case-sensitive. Some gRPC implementations may allow the **Path**
+format shown above to be overridden, but this functionality is strongly
+discouraged. gRPC does not go out of its way to break users that are using this
+kind of override, but we do not actively support it, and some functionality
+(e.g., service config support) will not work when the path is not of the form
+shown above.
 
 If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements.
 
index 4f40481..786825f 100644 (file)
@@ -52,10 +52,12 @@ Mac systems with Homebrew:
 brew install gflags
 ```
 
-Once the prerequisites are satisfied, you can build the command line tool with
-the command:
+Once the prerequisites are satisfied, you can build with cmake:
 
 ```
+$ mkdir -p cmake/build
+$ cd cmake/build
+$ cmake -DgRPC_BUILD_TESTS=ON ../..
 $ make grpc_cli
 ```
 
index 15e35ae..7f0c382 100644 (file)
@@ -76,8 +76,8 @@ of _compression levels_ (such as "low", "medium", "high").
 Levels map to concrete algorithms and/or their settings (such as "low" mapping
 to "gzip -3" and "high" mapping to "gzip -9") automatically depending on what a
 peer is known to support. A server is always aware of what its clients support,
-as clients disclose it in their Message-Accept-Encoding header as part of their
-initial call. A client doesn't a priori (presently) know which algorithms a
+as clients disclose it in the Message-Accept-Encoding header as part of the
+RPC. A client doesn't a priori (presently) know which algorithms a
 server supports. This issue can be addressed with an initial negotiation of
 capabilities or an automatic retry mechanism. These features will be implemented
 in the future. Currently however, compression levels are only supported at the
index 382ccbf..35ea308 100644 (file)
@@ -28,4 +28,5 @@
 - 1.26 'g' stands for ['gon'](https://github.com/grpc/grpc/tree/v1.26.x)
 - 1.27 'g' stands for ['guantao'](https://github.com/grpc/grpc/tree/v1.27.x)
 - 1.28 'g' stands for ['galactic'](https://github.com/grpc/grpc/tree/v1.28.x)
-- 1.29 'g' stands for ['gringotts'](https://github.com/grpc/grpc/tree/master)
+- 1.29 'g' stands for ['gringotts'](https://github.com/grpc/grpc/tree/v1.29.x)
+- 1.30 'g' stands for ['gradius'](https://github.com/grpc/grpc/tree/v1.30.x)
index 4d0271e..ad461e7 100644 (file)
@@ -16,11 +16,11 @@ The above two channel arguments should be sufficient for most users, but the fol
 * **GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS**
   * This channel argument if set to 1 (0 : false; 1 : true), allows keepalive pings to be sent even if there are no calls in flight. 
 * **GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA**
-  * This channel argument controls the maximum number of pings that can be sent when there is no other data (data frame or header frame) to be sent. GRPC Core will not continue sending pings if we run over the limit. Setting it to 0 allows sending pings without sending data.
+  * This channel argument controls the maximum number of pings that can be sent when there is no data/header/window_update frame to be sent. GRPC Core will not continue sending pings if we run over the limit. Setting it to 0 allows sending pings without such a restriction.
 * **GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS**
-  * If there are no data frames being received on the transport, this channel argument controls the minimum time (in milliseconds) gRPC Core will wait between successive pings.
+  * If there are no data/header/window_update frames being received on the transport, this channel argument controls the minimum time (in milliseconds) gRPC Core will wait between successive pings.
 * **GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS**
-  * If there are no data frames being sent on the transport, this channel argument on the server side controls the minimum time (in milliseconds) that gRPC Core would expect between receiving successive pings. If the time between successive pings is less that than this time, then the ping will be considered a bad ping from the peer. Such a ping counts as a â€˜ping strike’.
+  * If there are no data/header/window_update frames being sent on the transport, this channel argument on the server side controls the minimum time (in milliseconds) that gRPC Core would expect between receiving successive pings. If the time between successive pings is less that than this time, then the ping will be considered a bad ping from the peer. Such a ping counts as a â€˜ping strike’.
 On the client side, this does not have any effect.
 * **GRPC_ARG_HTTP2_MAX_PING_STRIKES**
   * This arg controls the maximum number of bad pings that the server will tolerate before sending an HTTP2 GOAWAY frame and closing the transport. Setting it to 0 allows the server to accept any number of bad pings.
index 49e5ecb..6e4bfab 100644 (file)
@@ -28,13 +28,17 @@ sys.path.insert(0, os.path.join(PYTHON_FOLDER, 'grpcio_testing'))
 # -- Project information -----------------------------------------------------
 
 project = 'gRPC Python'
-copyright = '2018, The gRPC Authors'
+copyright = '2020, The gRPC Authors'
 author = 'The gRPC Authors'
 
 # Import generated grpc_version after the path been modified
 import grpc_version
-version = ".".join(grpc_version.VERSION.split(".")[:3])
+version = '.'.join(grpc_version.VERSION.split('.')[:3])
 release = grpc_version.VERSION
+if 'dev' in grpc_version.VERSION:
+    branch = 'master'
+else:
+    branch = 'v%s.%s.x' % tuple(grpc_version.VERSION.split('.')[:2])
 
 # -- General configuration ---------------------------------------------------
 
@@ -100,3 +104,7 @@ epub_exclude_files = ['search.html']
 # -- Options for todo extension ----------------------------------------------
 
 todo_include_todos = True
+
+# -- Options for substitutions -----------------------------------------------
+
+rst_epilog = '.. |grpc_types_link| replace:: https://github.com/grpc/grpc/blob/%s/include/grpc/impl/codegen/grpc_types.h' % branch
index cae5f4a..a4daa31 100644 (file)
@@ -27,3 +27,24 @@ Glossary
     the returned object doesn't have restrictions (i.e. ``None`` allowed). The
     deserializer is invoked with inbound message bytes on both the server side
     and the client-side.
+
+  wait_for_ready
+    If an RPC is issued but the channel is in the TRANSIENT_FAILURE or SHUTDOWN
+    states, the library cannot transmit the RPC at the moment. By default, the
+    gRPC library will fail such RPCs immediately. This is known as "fail fast."
+    RPCs will not fail as a result of the channel being in other states
+    (CONNECTING, READY, or IDLE).
+
+    When the wait_for_ready option is specified, the library will queue RPCs
+    until the channel is READY. Any submitted RPCs may still fail before the
+    READY state is reached for other reasons, e.g., the client channel has been
+    shut down or the RPC's deadline has been reached.
+
+  channel_arguments
+    A list of key-value pairs to configure the underlying gRPC Core channel or
+    server object. Channel arguments are meant for advanced usages and contain
+    experimental API (some may not labeled as experimental). Full list of
+    available channel arguments and documentation can be found under the
+    "grpc_arg_keys" section of "grpc_types.h" header file (|grpc_types_link|).
+    For example, if you want to disable TCP port reuse, you may construct
+    channel arguments like: ``options = (('grpc.so_reuseport', 0),)``.
index ca56481..c301e7d 100644 (file)
@@ -144,7 +144,7 @@ Unary RPC:
 MockEchoTestServiceStub stub;
 EchoResponse resp;
 resp.set_message("hello world");
-Expect_CALL(stub, Echo(_,_,_)).Times(Atleast(1)).WillOnce(DoAll(SetArgPointee<2>(resp), Return(Status::OK)));
+EXPECT_CALL(stub, Echo(_,_,_)).Times(AtLeast(1)).WillOnce(DoAll(SetArgPointee<2>(resp), Return(Status::OK)));
 FakeClient client(stub);
 client.DoEcho();
 ```
index 999238a..4641438 100644 (file)
@@ -25,6 +25,9 @@ The code for the xDS test client can be at:
 
 Clients should accept these arguments:
 
+*   --fail_on_failed_rpcs=BOOL
+    *   If true, the client should exit with a non-zero return code if any RPCs
+        fail. Default is false.
 *   --num_channels=CHANNELS
     *   The number of channels to create to the server.
 *   --qps=QPS
@@ -88,6 +91,7 @@ Client parameters:
 
 1.  --num_channels=1
 1.  --qps=10
+1.  --fail_on_failed_rpc=true
 
 Load balancer configuration:
 
@@ -106,6 +110,7 @@ Client parameters:
 
 1.  --num_channels=1
 1.  --qps=10
+1.  --fail_on_failed_rpc=true
 
 Load balancer configuration:
 
@@ -220,6 +225,7 @@ Client parameters:
 
 1.  --num_channels=1
 1.  --qps=10
+1.  --fail_on_failed_rpc=true
 
 Load balancer configuration:
 
@@ -268,6 +274,7 @@ Client parameters:
 
 1.  --num_channels=1
 1.  --qps=10
+1.  --fail_on_failed_rpc=true
 
 Load balancer configuration:
 
index 1cb5a40..1d1956d 100644 (file)
@@ -3,4 +3,4 @@
 The files in this folder are the samples used in [gRPC Basics: C++][],
 a detailed tutorial for using gRPC in C++.
 
-[gRPC Basics: C++]:https://grpc.io/docs/tutorials/basic/c.html
+[gRPC Basics: C++]:https://grpc.io/docs/tutorials/basic/cpp
index bd374a8..712df61 100644 (file)
@@ -16,7 +16,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <None Include="route_guide_db.json" CopyToOutputDirectory="PreserveNewest" />
+    <EmbeddedResource Include="route_guide_db.json" />
   </ItemGroup>
 
 </Project>
index 96bd8ca..29cd6b9 100644 (file)
@@ -18,6 +18,7 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Reflection;
 using System.Text;
 using System.Threading.Tasks;
 
@@ -28,7 +29,7 @@ namespace Routeguide
     /// </summary>
     public static class RouteGuideUtil
     {
-        public const string DefaultFeaturesFile = "route_guide_db.json";
+        public const string DefaultFeaturesResourceName = "RouteGuide.route_guide_db.json";
 
         private const double CoordFactor = 1e7;
 
@@ -90,12 +91,12 @@ namespace Routeguide
         }
 
         /// <summary>
-        /// Parses features from a JSON file.
+        /// Parses features from an embedded resource.
         /// </summary>
-        public static List<Feature> ParseFeatures(string filename)
+        public static List<Feature> LoadFeatures()
         {
             var features = new List<Feature>();
-            var jsonFeatures = JsonConvert.DeserializeObject<List<JsonFeature>>(File.ReadAllText(filename));
+            var jsonFeatures = JsonConvert.DeserializeObject<List<JsonFeature>>(ReadFeaturesFromResource());
 
             foreach(var jsonFeature in jsonFeatures)
             {
@@ -108,6 +109,19 @@ namespace Routeguide
             return features;
         }
 
+        private static string ReadFeaturesFromResource()
+        {
+            var stream = typeof(RouteGuideUtil).GetTypeInfo().Assembly.GetManifestResourceStream(DefaultFeaturesResourceName);
+            if (stream == null)
+            {
+                throw new IOException(string.Format("Error loading the embedded resource \"{0}\"", DefaultFeaturesResourceName));
+            }
+            using (var streamReader = new StreamReader(stream))
+            {
+                return streamReader.ReadToEnd();
+            }
+        }
+
 #pragma warning disable 0649  // Suppresses "Field 'x' is never assigned to".
         private class JsonFeature
         {
index 9ce0cbc..accaf0a 100644 (file)
@@ -228,7 +228,7 @@ namespace Routeguide
             client.ListFeatures(400000000, -750000000, 420000000, -730000000).Wait();
 
             // Record a few randomly selected points from the features file.
-            client.RecordRoute(RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile), 10).Wait();
+            client.RecordRoute(RouteGuideUtil.LoadFeatures(), 10).Wait();
 
             // Send and receive some notes.
             client.RouteChat().Wait();
index 4548ddf..a79f8a1 100644 (file)
@@ -27,7 +27,7 @@ namespace Routeguide
         {
             const int Port = 50052;
 
-            var features = RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile);
+            var features = RouteGuideUtil.LoadFeatures();
 
             Server server = new Server
             {
diff --git a/examples/csharp/Xds/Greeter.sln b/examples/csharp/Xds/Greeter.sln
new file mode 100644 (file)
index 0000000..a5ba98d
--- /dev/null
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26228.4
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greeter", "Greeter\Greeter.csproj", "{13B6DFC8-F5F6-4CC2-99DF-57A7CF042033}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreeterClient", "GreeterClient\GreeterClient.csproj", "{B754FB02-D501-4308-8B89-33AB7119C80D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreeterServer", "GreeterServer\GreeterServer.csproj", "{DDBFF994-E076-43AD-B18D-049DFC1B670C}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Any CPU = Debug|Any CPU
+               Release|Any CPU = Release|Any CPU
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {13B6DFC8-F5F6-4CC2-99DF-57A7CF042033}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {13B6DFC8-F5F6-4CC2-99DF-57A7CF042033}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {13B6DFC8-F5F6-4CC2-99DF-57A7CF042033}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {13B6DFC8-F5F6-4CC2-99DF-57A7CF042033}.Release|Any CPU.Build.0 = Release|Any CPU
+               {B754FB02-D501-4308-8B89-33AB7119C80D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {B754FB02-D501-4308-8B89-33AB7119C80D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {B754FB02-D501-4308-8B89-33AB7119C80D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {B754FB02-D501-4308-8B89-33AB7119C80D}.Release|Any CPU.Build.0 = Release|Any CPU
+               {DDBFF994-E076-43AD-B18D-049DFC1B670C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {DDBFF994-E076-43AD-B18D-049DFC1B670C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {DDBFF994-E076-43AD-B18D-049DFC1B670C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {DDBFF994-E076-43AD-B18D-049DFC1B670C}.Release|Any CPU.Build.0 = Release|Any CPU
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/examples/csharp/Xds/Greeter/Greeter.csproj b/examples/csharp/Xds/Greeter/Greeter.csproj
new file mode 100644 (file)
index 0000000..9351cbc
--- /dev/null
@@ -0,0 +1,20 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Google.Protobuf" Version="3.12.2" />
+    <PackageReference Include="Grpc.Core" Version="2.29.0" />
+    <PackageReference Include="Grpc.HealthCheck" Version="2.29.0" />
+    <PackageReference Include="Grpc.Reflection" Version="2.29.0"/>
+    <PackageReference Include="CommandLineParser" Version="2.8.0" />
+    <PackageReference Include="Grpc.Tools" Version="2.29.0" PrivateAssets="All" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Protobuf Include="../../../protos/helloworld.proto" Link="helloworld.proto" />
+  </ItemGroup>
+
+</Project>
diff --git a/examples/csharp/Xds/GreeterClient/GreeterClient.csproj b/examples/csharp/Xds/GreeterClient/GreeterClient.csproj
new file mode 100644 (file)
index 0000000..ac10d85
--- /dev/null
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
+    <OutputType>Exe</OutputType>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\Greeter\Greeter.csproj" />
+  </ItemGroup>
+
+</Project>
diff --git a/examples/csharp/Xds/GreeterClient/Program.cs b/examples/csharp/Xds/GreeterClient/Program.cs
new file mode 100644 (file)
index 0000000..c6820a8
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using Grpc.Core;
+using Helloworld;
+using CommandLine;
+
+namespace GreeterClient
+{
+    class Program
+    {
+        private class Options
+        {
+            [Option("server", Default = "localhost:50051", HelpText = "The address of the server")]
+            public string Server { get; set; }
+        }
+
+        public static void Main(string[] args)
+        {
+            Parser.Default.ParseArguments<Options>(args)
+                   .WithParsed<Options>(options => RunClient(options));
+        }
+
+        private static void RunClient(Options options)
+        {
+            Channel channel = new Channel(options.Server, ChannelCredentials.Insecure);
+
+            var client = new Greeter.GreeterClient(channel);
+            String user = "you";
+
+            var reply = client.SayHello(new HelloRequest { Name = user });
+            Console.WriteLine("Greeter client received: " + reply.Message);
+
+            channel.ShutdownAsync().Wait();
+            Console.WriteLine("Press any key to exit...");
+            Console.ReadKey();
+        }
+    }
+}
diff --git a/examples/csharp/Xds/GreeterServer/GreeterServer.csproj b/examples/csharp/Xds/GreeterServer/GreeterServer.csproj
new file mode 100644 (file)
index 0000000..ac10d85
--- /dev/null
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
+    <OutputType>Exe</OutputType>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\Greeter\Greeter.csproj" />
+  </ItemGroup>
+
+</Project>
diff --git a/examples/csharp/Xds/GreeterServer/Program.cs b/examples/csharp/Xds/GreeterServer/Program.cs
new file mode 100644 (file)
index 0000000..e10b1af
--- /dev/null
@@ -0,0 +1,93 @@
+// Copyright 2020 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.Net;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.HealthCheck;
+using Helloworld;
+using Grpc.Health;
+using Grpc.Health.V1;
+using Grpc.Reflection;
+using Grpc.Reflection.V1Alpha;
+using CommandLine;
+
+namespace GreeterServer
+{
+    class GreeterImpl : Greeter.GreeterBase
+    {
+        private string hostname;
+
+        public GreeterImpl(string hostname)
+        {
+            this.hostname = hostname;
+        }
+
+        // Server side handler of the SayHello RPC
+        public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
+        {
+            return Task.FromResult(new HelloReply { Message = $"Hello {request.Name} from {hostname}!"});
+        }
+    }
+
+    class Program
+    {
+        class Options
+        {
+            [Option("port", Default = 50051, HelpText = "The port to listen on.")]
+            public int Port { get; set; }
+
+            [Option("hostname", Required = false, HelpText = "The name clients will see in responses. If not specified, machine's hostname will obtain automatically.")]
+            public string Hostname { get; set; }
+        }
+
+        public static void Main(string[] args)
+        {
+            Parser.Default.ParseArguments<Options>(args)
+                   .WithParsed<Options>(options => RunServer(options));
+        }
+
+        private static void RunServer(Options options)
+        {
+            var hostName = options.Hostname ?? Dns.GetHostName();
+
+            var serviceDescriptors = new [] {Greeter.Descriptor, Health.Descriptor, ServerReflection.Descriptor};
+            var greeterImpl = new GreeterImpl(hostName);
+            var healthServiceImpl = new HealthServiceImpl();
+            var reflectionImpl = new ReflectionServiceImpl(serviceDescriptors);
+
+            Server server = new Server
+            {
+                Services = { Greeter.BindService(greeterImpl), Health.BindService(healthServiceImpl), ServerReflection.BindService(reflectionImpl) },
+                Ports = { new ServerPort("[::]", options.Port, ServerCredentials.Insecure) }
+            };
+            server.Start();
+
+            // Mark all services as healthy.
+            foreach (var serviceDescriptor in serviceDescriptors)
+            {
+                healthServiceImpl.SetStatus(serviceDescriptor.FullName, HealthCheckResponse.Types.ServingStatus.Serving);
+            }
+            // Mark overall server status as healthy.
+            healthServiceImpl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving);
+
+            Console.WriteLine("Greeter server listening on port " + options.Port);
+            Console.WriteLine("Press any key to stop the server...");
+            Console.ReadKey();
+
+            server.ShutdownAsync().Wait();
+        }
+    }
+}
diff --git a/examples/csharp/Xds/README.md b/examples/csharp/Xds/README.md
new file mode 100644 (file)
index 0000000..ce0aa9f
--- /dev/null
@@ -0,0 +1,99 @@
+gRPC Hostname example (C#)
+========================
+
+BACKGROUND
+-------------
+This is a version of the helloworld example with a server whose response includes its hostname. It also supports health and reflection services. This makes it a good server to test infrastructure, such as XDS load balancing.
+
+PREREQUISITES
+-------------
+
+- The [.NET Core SDK 2.1+](https://www.microsoft.com/net/core)
+
+You can also build the solution `Greeter.sln` using Visual Studio 2019,
+but it's not a requirement.
+
+RUN THE EXAMPLE
+-------------
+
+First, build and run the server, then verify the server is running and
+check the server is behaving as expected (more on that below).
+
+```
+cd GreeterServer
+dotnet run
+```
+
+After configuring your xDS server to track the gRPC server we just started,
+create a bootstrap file as desribed in [gRFC A27](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md):
+
+```
+{
+  xds_servers": [
+    {
+      "server_uri": <string containing URI of xds server>,
+      "channel_creds": [
+        {
+          "type": <string containing channel cred type>,
+          "config": <JSON object containing config for the type>
+        }
+      ]
+    }
+  ],
+  "node": <JSON form of Node proto>
+}
+```
+
+Then point the `GRPC_XDS_BOOTSTRAP` environment variable at the bootstrap file:
+
+```
+export GRPC_XDS_BOOTSTRAP=/etc/xds-bootstrap.json
+```
+
+Finally, run your client:
+
+```
+cd GreeterClient
+dotnet run --server xds-experimental:///my-backend
+```
+
+VERIFYING THE SERVER
+-------------
+
+`grpcurl` can be used to test your server. If you don't have it,
+install [`grpcurl`](https://github.com/fullstorydev/grpcurl/releases). This will allow
+you to manually test the service.
+
+Exercise your server's application-layer service:
+
+```sh
+> grpcurl --plaintext -d '{"name": "you"}' localhost:50051
+{
+  "message": "Hello you from jtatt.muc.corp.google.com!"
+}
+```
+
+Make sure that all of your server's services are available via reflection:
+
+```sh
+> grpcurl --plaintext localhost:50051 list
+grpc.health.v1.Health
+grpc.reflection.v1alpha.ServerReflection
+helloworld.Greeter
+```
+
+Make sure that your services are reporting healthy:
+
+```sh
+> grpcurl --plaintext -d '{"service": "helloworld.Greeter"}' localhost:50051
+grpc.health.v1.Health/Check
+{
+  "status": "SERVING"
+}
+
+> grpcurl --plaintext -d '{"service": ""}' localhost:50051
+grpc.health.v1.Health/Check
+{
+  "status": "SERVING"
+}
+```
index 9d900eb..927f7df 100644 (file)
@@ -7,7 +7,9 @@
   },
   "autoload": {
     "psr-4": {
-      "": "route_guide/"
+      "Routeguide\\": "route_guide/Routeguide/",
+      "GPBMetadata\\": ["GPBMetadata/","route_guide/GPBMetadata/"],
+      "Helloworld\\": "Helloworld/"
     }
   }
 }
index bb94a08..1c7ec2a 100644 (file)
  *
  */
 
-// php:generate protoc --proto_path=./../protos   --php_out=./   --grpc_out=./ --plugin=protoc-gen-grpc=./../../bins/opt/grpc_php_plugin ./../protos/helloworld.proto
+// To generate the necessary proto classes:
+// $ protoc --proto_path=../protos --php_out=. --grpc_out=.
+//   --plugin=protoc-gen-grpc=../../bins/opt/grpc_php_plugin
+//   ../protos/helloworld.proto
 
 require dirname(__FILE__).'/vendor/autoload.php';
 
-@include_once dirname(__FILE__).'/Helloworld/GreeterClient.php';
-@include_once dirname(__FILE__).'/Helloworld/HelloReply.php';
-@include_once dirname(__FILE__).'/Helloworld/HelloRequest.php';
-@include_once dirname(__FILE__).'/GPBMetadata/Helloworld.php';
-
-function greet($name)
+function greet($hostname, $name)
 {
-    $client = new Helloworld\GreeterClient('localhost:50051', [
+    $client = new Helloworld\GreeterClient($hostname, [
         'credentials' => Grpc\ChannelCredentials::createInsecure(),
     ]);
     $request = new Helloworld\HelloRequest();
     $request->setName($name);
-    list($reply, $status) = $client->SayHello($request)->wait();
-    $message = $reply->getMessage();
-
-    return $message;
+    list($response, $status) = $client->SayHello($request)->wait();
+    if ($status->code !== Grpc\STATUS_OK) {
+        echo "ERROR: " . $status->code . ", " . $status->details . PHP_EOL;
+        exit(1);
+    }
+    echo $response->getMessage() . PHP_EOL;
 }
 
 $name = !empty($argv[1]) ? $argv[1] : 'world';
-echo greet($name)."\n";
+$hostname = !empty($argv[2]) ? $argv[2] : 'localhost:50051';
+greet($hostname, $name);
index a0d7b29..4322bbd 100755 (executable)
@@ -13,5 +13,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-protoc --proto_path=./../protos   --php_out=./   --grpc_out=./   --plugin=protoc-gen-grpc=./../../bins/opt/grpc_php_plugin   ./../protos/helloworld.proto
-
+protoc --proto_path=../protos --php_out=. --grpc_out=. --plugin=protoc-gen-grpc=../../bins/opt/grpc_php_plugin ../protos/helloworld.proto
diff --git a/examples/python/data_transmission/BUILD b/examples/python/data_transmission/BUILD
new file mode 100644 (file)
index 0000000..2eefb7a
--- /dev/null
@@ -0,0 +1,49 @@
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+licenses(["notice"])  # 3-clause BSD
+
+load("@grpc_python_dependencies//:requirements.bzl", "requirement")
+
+py_binary(
+    name = "alts_server",
+    srcs = [
+        "alts_server.py",
+        "demo_pb2.py",
+        "demo_pb2_grpc.py",
+        "server.py",
+    ],
+    main = "alts_server.py",
+    python_version = "PY3",
+    srcs_version = "PY2AND3",
+    deps = [
+        "//src/python/grpcio/grpc:grpcio",
+    ],
+)
+
+py_binary(
+    name = "alts_client",
+    srcs = [
+        "alts_client.py",
+        "client.py",
+        "demo_pb2.py",
+        "demo_pb2_grpc.py",
+    ],
+    main = "alts_client.py",
+    python_version = "PY3",
+    srcs_version = "PY2AND3",
+    deps = [
+        "//src/python/grpcio/grpc:grpcio",
+    ],
+)
diff --git a/examples/python/data_transmission/alts_client.py b/examples/python/data_transmission/alts_client.py
new file mode 100644 (file)
index 0000000..eb32866
--- /dev/null
@@ -0,0 +1,39 @@
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""The example of using ALTS credentials to setup gRPC client.
+
+The example would only successfully run in GCP environment."""
+
+import grpc
+
+import demo_pb2_grpc
+from client import (bidirectional_streaming_method, client_streaming_method,
+                    server_streaming_method, simple_method)
+
+SERVER_ADDRESS = "localhost:23333"
+
+
+def main():
+    with grpc.secure_channel(
+            SERVER_ADDRESS,
+            credentials=grpc.alts_channel_credentials()) as channel:
+        stub = demo_pb2_grpc.GRPCDemoStub(channel)
+        simple_method(stub)
+        client_streaming_method(stub)
+        server_streaming_method(stub)
+        bidirectional_streaming_method(stub)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/examples/python/data_transmission/alts_server.py b/examples/python/data_transmission/alts_server.py
new file mode 100644 (file)
index 0000000..4e8747c
--- /dev/null
@@ -0,0 +1,39 @@
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""The example of using ALTS credentials to setup gRPC server in python.
+
+The example would only successfully run in GCP environment."""
+
+from concurrent import futures
+
+import grpc
+
+import demo_pb2_grpc
+from server import DemoServer
+
+SERVER_ADDRESS = 'localhost:23333'
+
+
+def main():
+    svr = grpc.server(futures.ThreadPoolExecutor())
+    demo_pb2_grpc.add_GRPCDemoServicer_to_server(DemoServer(), svr)
+    svr.add_secure_port(SERVER_ADDRESS,
+                        server_credentials=grpc.alts_server_credentials())
+    print("------------------start Python GRPC server with ALTS encryption")
+    svr.start()
+    svr.wait_for_termination()
+
+
+if __name__ == '__main__':
+    main()
index 262e366..cc4a68e 100644 (file)
@@ -19,6 +19,11 @@ import grpc
 import demo_pb2_grpc
 import demo_pb2
 
+__all__ = [
+    'simple_method', 'client_streaming_method', 'server_streaming_method',
+    'bidirectional_streaming_method'
+]
+
 SERVER_ADDRESS = "localhost:23333"
 CLIENT_ID = 1
 
index 0a65928..3c99094 100644 (file)
@@ -20,6 +20,7 @@ import grpc
 import demo_pb2_grpc
 import demo_pb2
 
+__all__ = 'DemoServer'
 SERVER_ADDRESS = 'localhost:23333'
 SERVER_ID = 1
 
index bf7809e..cd9587a 100644 (file)
@@ -3,13 +3,10 @@ gRPC Hostname Example
 
 The hostname example is a Hello World server whose response includes its
 hostname. It also supports health and reflection services. This makes it a good
-server to test infrastructure, like load balancing.
+server to test infrastructure, like load balancing. This example depends on a
+gRPC version of 1.28.1 or newer.
 
-The example requires grpc to already be built. You are strongly encouraged
-to check out a git release tag, since there will already be a build of gRPC
-available.
-
-### Run the example
+### Run the Server
 
 1. Navigate to this directory:
 
@@ -26,14 +23,52 @@ pip install -r requirements.txt
 python server.py
 ```
 
-3. Verify the Server
+### Run the Client
+
+1. Set up xDS configuration.
+
+After configuring your xDS server to track the gRPC server we just started,
+create a bootstrap file as desribed in [gRFC A27](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md):
+
+```
+{
+  xds_servers": [
+    {
+      "server_uri": <string containing URI of xds server>,
+      "channel_creds": [
+        {
+          "type": <string containing channel cred type>,
+          "config": <JSON object containing config for the type>
+        }
+      ]
+    }
+  ],
+  "node": <JSON form of Node proto>
+}
+```
+
+2. Point the `GRPC_XDS_BOOTSTRAP` environment variable at the bootstrap file:
 
-This step is not strictly necessary, but you can use it as a sanity check if
-you'd like. If you don't have it, install
-[`grpcurl`](https://github.com/fullstorydev/grpcurl/releases). This will allow
+```
+export GRPC_XDS_BOOTSTRAP=/etc/xds-bootstrap.json
+```
+
+3. Run the client:
+
+```
+python client.py xds-experimental:///my-backend
+```
+
+### Verifying Configuration with a CLI Tool
+
+Alternatively, `grpcurl` can be used to verify your server. If you don't have it,
+install [`grpcurl`](https://github.com/fullstorydev/grpcurl/releases). This will allow
 you to manually test the service.
 
-Exercise your server's application-layer service:
+Be sure to set up the bootstrap file and `GRPC_XDS_BOOTSTRAP` as in the previous
+section.
+
+1. Verify the server's application-layer service:
 
 ```sh
 > grpcurl --plaintext -d '{"name": "you"}' localhost:50051
@@ -42,7 +77,7 @@ Exercise your server's application-layer service:
 }
 ```
 
-Make sure that all of your server's services are available via reflection:
+2. Verify that all services are available via reflection:
 
 ```sh
 > grpcurl --plaintext localhost:50051 list
@@ -51,7 +86,7 @@ grpc.reflection.v1alpha.ServerReflection
 helloworld.Greeter
 ```
 
-Make sure that your services are reporting healthy:
+3. Verify that all services are reporting healthy:
 
 ```sh
 > grpcurl --plaintext -d '{"service": "helloworld.Greeter"}' localhost:50051
diff --git a/examples/python/xds/client.py b/examples/python/xds/client.py
new file mode 100644 (file)
index 0000000..ee30026
--- /dev/null
@@ -0,0 +1,42 @@
+# Copyright 2020 The gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""The Python implementation of the GRPC helloworld.Greeter client."""
+
+from __future__ import print_function
+import logging
+import argparse
+
+import grpc
+
+import helloworld_pb2
+import helloworld_pb2_grpc
+
+_DESCRIPTION = "Get a greeting from a server."
+
+
+def run(server_address):
+    with grpc.insecure_channel(server_address) as channel:
+        stub = helloworld_pb2_grpc.GreeterStub(channel)
+        response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
+    print("Greeter client received: " + response.message)
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(description=_DESCRIPTION)
+    parser.add_argument("server",
+                        default=None,
+                        help="The address of the server.")
+    args = parser.parse_args()
+    logging.basicConfig()
+    run(args.server)
index a7ac2e7..7ba651e 100644 (file)
@@ -1,4 +1,4 @@
-grpcio>=1.28.0
+grpcio>=1.28.1
 protobuf
 grpcio-reflection
 grpcio-health-checking
index 507d254..33a2e79 100755 (executable)
@@ -26,10 +26,15 @@ require 'grpc'
 require 'helloworld_services_pb'
 
 def main
-  stub = Helloworld::Greeter::Stub.new('localhost:50051', :this_channel_is_insecure)
   user = ARGV.size > 0 ?  ARGV[0] : 'world'
-  message = stub.say_hello(Helloworld::HelloRequest.new(name: user)).message
-  p "Greeting: #{message}"
+  hostname = ARGV.size > 1 ?  ARGV[1] : 'localhost:50051'
+  stub = Helloworld::Greeter::Stub.new(hostname, :this_channel_is_insecure)
+  begin
+    message = stub.say_hello(Helloworld::HelloRequest.new(name: user)).message
+    p "Greeting: #{message}"
+  rescue GRPC::BadStatus => e
+    abort "ERROR: #{e.message}"
+  end
 end
 
 main
index 943a6d2..fbb459d 100644 (file)
@@ -22,7 +22,7 @@
 Pod::Spec.new do |s|
   s.name     = 'gRPC-C++'
   # TODO (mxyan): use version that match gRPC version when pod is stabilized
-  version = '1.29.1'
+  version = '1.30.0'
   s.version  = version
   s.summary  = 'gRPC C++ library'
   s.homepage = 'https://grpc.io'
@@ -261,6 +261,8 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/retry_throttle.h',
                       'src/core/ext/filters/client_channel/server_address.h',
                       'src/core/ext/filters/client_channel/service_config.h',
+                      'src/core/ext/filters/client_channel/service_config_call_data.h',
+                      'src/core/ext/filters/client_channel/service_config_parser.h',
                       'src/core/ext/filters/client_channel/subchannel.h',
                       'src/core/ext/filters/client_channel/subchannel_interface.h',
                       'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
@@ -309,18 +311,24 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h',
                       'src/core/ext/upb-generated/envoy/annotations/resource.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cds.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/eds.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h',
@@ -341,6 +349,7 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h',
                       'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h',
                       'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h',
+                      'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h',
                       'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h',
                       'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h',
                       'src/core/ext/upb-generated/envoy/type/http.upb.h',
@@ -369,6 +378,7 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h',
+                      'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
                       'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
                       'src/core/ext/upb-generated/validate/validate.upb.h',
                       'src/core/lib/avl/avl.h',
@@ -418,16 +428,13 @@ Pod::Spec.new do |s|
                       'src/core/lib/gprpp/global_config_env.h',
                       'src/core/lib/gprpp/global_config_generic.h',
                       'src/core/lib/gprpp/host_port.h',
-                      'src/core/lib/gprpp/inlined_vector.h',
                       'src/core/lib/gprpp/manual_constructor.h',
                       'src/core/lib/gprpp/map.h',
                       'src/core/lib/gprpp/memory.h',
                       'src/core/lib/gprpp/mpscq.h',
-                      'src/core/lib/gprpp/optional.h',
                       'src/core/lib/gprpp/orphanable.h',
                       'src/core/lib/gprpp/ref_counted.h',
                       'src/core/lib/gprpp/ref_counted_ptr.h',
-                      'src/core/lib/gprpp/string_view.h',
                       'src/core/lib/gprpp/sync.h',
                       'src/core/lib/gprpp/thd.h',
                       'src/core/lib/http/format_request.h',
@@ -713,6 +720,8 @@ Pod::Spec.new do |s|
                               'src/core/ext/filters/client_channel/retry_throttle.h',
                               'src/core/ext/filters/client_channel/server_address.h',
                               'src/core/ext/filters/client_channel/service_config.h',
+                              'src/core/ext/filters/client_channel/service_config_call_data.h',
+                              'src/core/ext/filters/client_channel/service_config_parser.h',
                               'src/core/ext/filters/client_channel/subchannel.h',
                               'src/core/ext/filters/client_channel/subchannel_interface.h',
                               'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
@@ -761,18 +770,24 @@ Pod::Spec.new do |s|
                               'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h',
                               'src/core/ext/upb-generated/envoy/annotations/resource.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cds.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/eds.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h',
@@ -793,6 +808,7 @@ Pod::Spec.new do |s|
                               'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h',
                               'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h',
                               'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h',
+                              'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h',
                               'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h',
                               'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h',
                               'src/core/ext/upb-generated/envoy/type/http.upb.h',
@@ -821,6 +837,7 @@ Pod::Spec.new do |s|
                               'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h',
+                              'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
                               'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
                               'src/core/ext/upb-generated/validate/validate.upb.h',
                               'src/core/lib/avl/avl.h',
@@ -870,16 +887,13 @@ Pod::Spec.new do |s|
                               'src/core/lib/gprpp/global_config_env.h',
                               'src/core/lib/gprpp/global_config_generic.h',
                               'src/core/lib/gprpp/host_port.h',
-                              'src/core/lib/gprpp/inlined_vector.h',
                               'src/core/lib/gprpp/manual_constructor.h',
                               'src/core/lib/gprpp/map.h',
                               'src/core/lib/gprpp/memory.h',
                               'src/core/lib/gprpp/mpscq.h',
-                              'src/core/lib/gprpp/optional.h',
                               'src/core/lib/gprpp/orphanable.h',
                               'src/core/lib/gprpp/ref_counted.h',
                               'src/core/lib/gprpp/ref_counted_ptr.h',
-                              'src/core/lib/gprpp/string_view.h',
                               'src/core/lib/gprpp/sync.h',
                               'src/core/lib/gprpp/thd.h',
                               'src/core/lib/http/format_request.h',
index 4682e32..9221943 100644 (file)
@@ -21,7 +21,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-Core'
-  version = '1.29.1'
+  version = '1.30.0'
   s.version  = version
   s.summary  = 'Core cross-platform gRPC library, written in C'
   s.homepage = 'https://grpc.io'
@@ -172,7 +172,7 @@ Pod::Spec.new do |s|
     ss.header_mappings_dir = '.'
     ss.libraries = 'z'
     ss.dependency "#{s.name}/Interface", version
-    ss.dependency 'BoringSSL-GRPC', '0.0.8'
+    ss.dependency 'BoringSSL-GRPC', '0.0.9'
     abseil_version = '1.20200225.0'
     ss.dependency 'abseil/container/inlined_vector', abseil_version
     ss.dependency 'abseil/memory/memory', abseil_version
@@ -276,6 +276,9 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/server_address.h',
                       'src/core/ext/filters/client_channel/service_config.cc',
                       'src/core/ext/filters/client_channel/service_config.h',
+                      'src/core/ext/filters/client_channel/service_config_call_data.h',
+                      'src/core/ext/filters/client_channel/service_config_parser.cc',
+                      'src/core/ext/filters/client_channel/service_config_parser.h',
                       'src/core/ext/filters/client_channel/subchannel.cc',
                       'src/core/ext/filters/client_channel/subchannel.h',
                       'src/core/ext/filters/client_channel/subchannel_interface.h',
@@ -381,6 +384,12 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/envoy/annotations/resource.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cds.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/cds.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c',
@@ -393,10 +402,14 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c',
@@ -405,6 +418,8 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h',
                       'src/core/ext/upb-generated/envoy/api/v2/eds.upb.c',
@@ -445,6 +460,8 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h',
                       'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c',
                       'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h',
+                      'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c',
+                      'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h',
                       'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c',
                       'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h',
                       'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c',
@@ -501,6 +518,8 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c',
                       'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h',
+                      'src/core/ext/upb-generated/udpa/annotations/status.upb.c',
+                      'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
                       'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
                       'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
                       'src/core/ext/upb-generated/validate/validate.upb.c',
@@ -610,17 +629,14 @@ Pod::Spec.new do |s|
                       'src/core/lib/gprpp/global_config_generic.h',
                       'src/core/lib/gprpp/host_port.cc',
                       'src/core/lib/gprpp/host_port.h',
-                      'src/core/lib/gprpp/inlined_vector.h',
                       'src/core/lib/gprpp/manual_constructor.h',
                       'src/core/lib/gprpp/map.h',
                       'src/core/lib/gprpp/memory.h',
                       'src/core/lib/gprpp/mpscq.cc',
                       'src/core/lib/gprpp/mpscq.h',
-                      'src/core/lib/gprpp/optional.h',
                       'src/core/lib/gprpp/orphanable.h',
                       'src/core/lib/gprpp/ref_counted.h',
                       'src/core/lib/gprpp/ref_counted_ptr.h',
-                      'src/core/lib/gprpp/string_view.h',
                       'src/core/lib/gprpp/sync.h',
                       'src/core/lib/gprpp/thd.h',
                       'src/core/lib/gprpp/thd_posix.cc',
@@ -1069,6 +1085,8 @@ Pod::Spec.new do |s|
                               'src/core/ext/filters/client_channel/retry_throttle.h',
                               'src/core/ext/filters/client_channel/server_address.h',
                               'src/core/ext/filters/client_channel/service_config.h',
+                              'src/core/ext/filters/client_channel/service_config_call_data.h',
+                              'src/core/ext/filters/client_channel/service_config_parser.h',
                               'src/core/ext/filters/client_channel/subchannel.h',
                               'src/core/ext/filters/client_channel/subchannel_interface.h',
                               'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
@@ -1117,18 +1135,24 @@ Pod::Spec.new do |s|
                               'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h',
                               'src/core/ext/upb-generated/envoy/annotations/resource.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cds.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/eds.upb.h',
                               'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h',
@@ -1149,6 +1173,7 @@ Pod::Spec.new do |s|
                               'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h',
                               'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h',
                               'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h',
+                              'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h',
                               'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h',
                               'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h',
                               'src/core/ext/upb-generated/envoy/type/http.upb.h',
@@ -1177,6 +1202,7 @@ Pod::Spec.new do |s|
                               'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h',
+                              'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
                               'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
                               'src/core/ext/upb-generated/validate/validate.upb.h',
                               'src/core/lib/avl/avl.h',
@@ -1226,16 +1252,13 @@ Pod::Spec.new do |s|
                               'src/core/lib/gprpp/global_config_env.h',
                               'src/core/lib/gprpp/global_config_generic.h',
                               'src/core/lib/gprpp/host_port.h',
-                              'src/core/lib/gprpp/inlined_vector.h',
                               'src/core/lib/gprpp/manual_constructor.h',
                               'src/core/lib/gprpp/map.h',
                               'src/core/lib/gprpp/memory.h',
                               'src/core/lib/gprpp/mpscq.h',
-                              'src/core/lib/gprpp/optional.h',
                               'src/core/lib/gprpp/orphanable.h',
                               'src/core/lib/gprpp/ref_counted.h',
                               'src/core/lib/gprpp/ref_counted_ptr.h',
-                              'src/core/lib/gprpp/string_view.h',
                               'src/core/lib/gprpp/sync.h',
                               'src/core/lib/gprpp/thd.h',
                               'src/core/lib/http/format_request.h',
@@ -1487,6 +1510,7 @@ Pod::Spec.new do |s|
                       'test/core/end2end/tests/cancel_test_helpers.h',
                       'test/core/end2end/tests/cancel_with_status.cc',
                       'test/core/end2end/tests/channelz.cc',
+                      'test/core/end2end/tests/client_streaming.cc',
                       'test/core/end2end/tests/compressed_payload.cc',
                       'test/core/end2end/tests/connectivity.cc',
                       'test/core/end2end/tests/default_host.cc',
index 3dc0e9b..c444d95 100644 (file)
@@ -21,7 +21,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-ProtoRPC'
-  version = '1.29.1'
+  version = '1.30.0'
   s.version  = version
   s.summary  = 'RPC library for Protocol Buffers, based on gRPC'
   s.homepage = 'https://grpc.io'
index 54ce5ea..8796c9e 100644 (file)
@@ -21,7 +21,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-RxLibrary'
-  version = '1.29.1'
+  version = '1.30.0'
   s.version  = version
   s.summary  = 'Reactive Extensions library for iOS/OSX.'
   s.homepage = 'https://grpc.io'
index 8a594ba..e30c30c 100644 (file)
@@ -20,7 +20,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC'
-  version = '1.29.1'
+  version = '1.30.0'
   s.version  = version
   s.summary  = 'gRPC client library for iOS/OSX'
   s.homepage = 'https://grpc.io'
@@ -66,7 +66,8 @@ Pod::Spec.new do |s|
                       "src/objective-c/GRPCClient/GRPCCall+OAuth2.h",
                       "src/objective-c/GRPCClient/GRPCCall+Tests.h",
                       "src/objective-c/GRPCClient/GRPCCallLegacy.h",
-                      "src/objective-c/GRPCClient/GRPCTypes.h"
+                      "src/objective-c/GRPCClient/GRPCTypes.h",
+                      "src/objective-c/GRPCClient/GRPCTypes.m"
     ss.dependency "gRPC-RxLibrary/Interface", version
 
     ss.ios.deployment_target = '7.0'
index c6faf70..af04b9d 100644 (file)
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
   s.name          = 'grpc'
   s.version       = GRPC::VERSION
   s.authors       = ['gRPC Authors']
-  s.email         = 'temiola@google.com'
+  s.email         = 'grpc-io@googlegroups.com'
   s.homepage      = 'https://github.com/google/grpc/tree/master/src/ruby'
   s.summary       = 'GRPC system in Ruby'
   s.description   = 'Send RPCs from Ruby using GRPC'
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
   s.require_paths = %w( src/ruby/lib src/ruby/bin src/ruby/pb )
   s.platform      = Gem::Platform::RUBY
 
-  s.add_dependency 'google-protobuf', '~> 3.11'
+  s.add_dependency 'google-protobuf', '~> 3.12'
   s.add_dependency 'googleapis-common-protos-types', '~> 1.0'
 
   s.add_development_dependency 'bundler',            '>= 1.9'
@@ -198,6 +198,9 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/filters/client_channel/server_address.h )
   s.files += %w( src/core/ext/filters/client_channel/service_config.cc )
   s.files += %w( src/core/ext/filters/client_channel/service_config.h )
+  s.files += %w( src/core/ext/filters/client_channel/service_config_call_data.h )
+  s.files += %w( src/core/ext/filters/client_channel/service_config_parser.cc )
+  s.files += %w( src/core/ext/filters/client_channel/service_config_parser.h )
   s.files += %w( src/core/ext/filters/client_channel/subchannel.cc )
   s.files += %w( src/core/ext/filters/client_channel/subchannel.h )
   s.files += %w( src/core/ext/filters/client_channel/subchannel_interface.h )
@@ -303,6 +306,12 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/upb-generated/envoy/annotations/resource.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cds.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cds.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c )
@@ -315,10 +324,14 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c )
@@ -327,6 +340,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/eds.upb.c )
@@ -367,6 +382,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h )
   s.files += %w( src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c )
@@ -423,6 +440,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/migrate.upb.h )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h )
+  s.files += %w( src/core/ext/upb-generated/udpa/annotations/status.upb.c )
+  s.files += %w( src/core/ext/upb-generated/udpa/annotations/status.upb.h )
   s.files += %w( src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c )
   s.files += %w( src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h )
   s.files += %w( src/core/ext/upb-generated/validate/validate.upb.c )
@@ -532,17 +551,14 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/gprpp/global_config_generic.h )
   s.files += %w( src/core/lib/gprpp/host_port.cc )
   s.files += %w( src/core/lib/gprpp/host_port.h )
-  s.files += %w( src/core/lib/gprpp/inlined_vector.h )
   s.files += %w( src/core/lib/gprpp/manual_constructor.h )
   s.files += %w( src/core/lib/gprpp/map.h )
   s.files += %w( src/core/lib/gprpp/memory.h )
   s.files += %w( src/core/lib/gprpp/mpscq.cc )
   s.files += %w( src/core/lib/gprpp/mpscq.h )
-  s.files += %w( src/core/lib/gprpp/optional.h )
   s.files += %w( src/core/lib/gprpp/orphanable.h )
   s.files += %w( src/core/lib/gprpp/ref_counted.h )
   s.files += %w( src/core/lib/gprpp/ref_counted_ptr.h )
-  s.files += %w( src/core/lib/gprpp/string_view.h )
   s.files += %w( src/core/lib/gprpp/sync.h )
   s.files += %w( src/core/lib/gprpp/thd.h )
   s.files += %w( src/core/lib/gprpp/thd_posix.cc )
@@ -1172,6 +1188,9 @@ Gem::Specification.new do |s|
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/cpu-intel.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/cpu-ppc64le.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/crypto.c )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519.c )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519_tables.h )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/curve25519/internal.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/curve25519/spake25519.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/dh/check.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/dh/dh.c )
@@ -1182,6 +1201,8 @@ Gem::Specification.new do |s|
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/dsa/dsa_asn1.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_asn1.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_derive.c )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/ec_extra/hash_to_curve.c )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/ec_extra/internal.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/ecdh_extra/ecdh_extra.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/ecdsa_extra/ecdsa_asn1.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/engine/engine.c )
@@ -1257,6 +1278,8 @@ Gem::Specification.new do |s|
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-x86_64-table.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-x86_64.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-x86_64.h )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256.c )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256_table.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/scalar.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple_mul.c )
@@ -1279,6 +1302,9 @@ Gem::Specification.new do |s|
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/ofb.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/polyval.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/ctrdrbg.c )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/fork_detect.c )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/fork_detect.h )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/getrandom_fillin.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/internal.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/rand.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/urandom.c )
@@ -1341,6 +1367,9 @@ Gem::Specification.new do |s|
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/thread_none.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/thread_pthread.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/thread_win.c )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/trust_token/internal.h )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/x509/a_digest.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/x509/a_sign.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/x509/a_strex.c )
@@ -1500,6 +1529,7 @@ Gem::Specification.new do |s|
   s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/stack.h )
   s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/thread.h )
   s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/tls1.h )
+  s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/trust_token.h )
   s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/type_check.h )
   s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/x509.h )
   s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/x509_vfy.h )
@@ -1541,12 +1571,8 @@ Gem::Specification.new do |s|
   s.files += %w( third_party/boringssl-with-bazel/src/ssl/tls13_server.cc )
   s.files += %w( third_party/boringssl-with-bazel/src/ssl/tls_method.cc )
   s.files += %w( third_party/boringssl-with-bazel/src/ssl/tls_record.cc )
-  s.files += %w( third_party/boringssl-with-bazel/src/third_party/fiat/curve25519.c )
   s.files += %w( third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_32.h )
   s.files += %w( third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_64.h )
-  s.files += %w( third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_tables.h )
-  s.files += %w( third_party/boringssl-with-bazel/src/third_party/fiat/internal.h )
-  s.files += %w( third_party/boringssl-with-bazel/src/third_party/fiat/p256.c )
   s.files += %w( third_party/boringssl-with-bazel/src/third_party/fiat/p256_32.h )
   s.files += %w( third_party/boringssl-with-bazel/src/third_party/fiat/p256_64.h )
   s.files += %w( third_party/cares/ares_build.h )
index 933251c..b80efd8 100644 (file)
--- a/grpc.gyp
+++ b/grpc.gyp
         'test/core/end2end/tests/cancel_in_a_vacuum.cc',
         'test/core/end2end/tests/cancel_with_status.cc',
         'test/core/end2end/tests/channelz.cc',
+        'test/core/end2end/tests/client_streaming.cc',
         'test/core/end2end/tests/compressed_payload.cc',
         'test/core/end2end/tests/connectivity.cc',
         'test/core/end2end/tests/default_host.cc',
         'test/core/end2end/tests/cancel_in_a_vacuum.cc',
         'test/core/end2end/tests/cancel_with_status.cc',
         'test/core/end2end/tests/channelz.cc',
+        'test/core/end2end/tests/client_streaming.cc',
         'test/core/end2end/tests/compressed_payload.cc',
         'test/core/end2end/tests/connectivity.cc',
         'test/core/end2end/tests/default_host.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/server_address.cc',
         'src/core/ext/filters/client_channel/service_config.cc',
+        'src/core/ext/filters/client_channel/service_config_parser.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
         'src/core/ext/filters/client_channel/xds/xds_api.cc',
         'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c',
         'src/core/ext/upb-generated/envoy/annotations/resource.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/cds.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/eds.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c',
         'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c',
         'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c',
         'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c',
+        'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c',
         'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c',
         'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c',
         'src/core/ext/upb-generated/envoy/type/http.upb.c',
         'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
         'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c',
         'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c',
+        'src/core/ext/upb-generated/udpa/annotations/status.upb.c',
         'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
         'src/core/ext/upb-generated/validate/validate.upb.c',
         'src/core/lib/avl/avl.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/server_address.cc',
         'src/core/ext/filters/client_channel/service_config.cc',
+        'src/core/ext/filters/client_channel/service_config_parser.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
         'src/core/ext/filters/client_channel/xds/xds_api.cc',
         'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c',
         'src/core/ext/upb-generated/envoy/annotations/resource.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/cds.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/eds.upb.c',
         'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c',
         'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c',
         'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c',
         'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c',
+        'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c',
         'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c',
         'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c',
         'src/core/ext/upb-generated/envoy/type/http.upb.c',
         'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
         'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c',
         'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c',
+        'src/core/ext/upb-generated/udpa/annotations/status.upb.c',
         'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
         'src/core/ext/upb-generated/validate/validate.upb.c',
         'src/core/lib/avl/avl.cc',
         'third_party/boringssl-with-bazel/src/crypto/cpu-intel.c',
         'third_party/boringssl-with-bazel/src/crypto/cpu-ppc64le.c',
         'third_party/boringssl-with-bazel/src/crypto/crypto.c',
+        'third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519.c',
         'third_party/boringssl-with-bazel/src/crypto/curve25519/spake25519.c',
         'third_party/boringssl-with-bazel/src/crypto/dh/check.c',
         'third_party/boringssl-with-bazel/src/crypto/dh/dh.c',
         'third_party/boringssl-with-bazel/src/crypto/dsa/dsa_asn1.c',
         'third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_asn1.c',
         'third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_derive.c',
+        'third_party/boringssl-with-bazel/src/crypto/ec_extra/hash_to_curve.c',
         'third_party/boringssl-with-bazel/src/crypto/ecdh_extra/ecdh_extra.c',
         'third_party/boringssl-with-bazel/src/crypto/ecdsa_extra/ecdsa_asn1.c',
         'third_party/boringssl-with-bazel/src/crypto/engine/engine.c',
         'third_party/boringssl-with-bazel/src/crypto/thread_none.c',
         'third_party/boringssl-with-bazel/src/crypto/thread_pthread.c',
         'third_party/boringssl-with-bazel/src/crypto/thread_win.c',
+        'third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c',
+        'third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token.c',
         'third_party/boringssl-with-bazel/src/crypto/x509/a_digest.c',
         'third_party/boringssl-with-bazel/src/crypto/x509/a_sign.c',
         'third_party/boringssl-with-bazel/src/crypto/x509/a_strex.c',
         'third_party/boringssl-with-bazel/src/ssl/tls13_server.cc',
         'third_party/boringssl-with-bazel/src/ssl/tls_method.cc',
         'third_party/boringssl-with-bazel/src/ssl/tls_record.cc',
-        'third_party/boringssl-with-bazel/src/third_party/fiat/curve25519.c',
       ],
     },
     {
index 053b2da..e508294 100644 (file)
@@ -32,6 +32,7 @@ extern "C" {
 #define GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME "x509_pem_cert_chain"
 #define GRPC_SSL_SESSION_REUSED_PROPERTY "ssl_session_reused"
 #define GRPC_TRANSPORT_SECURITY_LEVEL_PROPERTY_NAME "security_level"
+#define GRPC_PEER_SPIFFE_ID_PROPERTY_NAME "peer_spiffe_id"
 
 /** Environment variable that points to the default SSL roots file. This file
    must be a PEM encoded file with all the roots such as the one that can be
index 9efabc9..0ab4213 100644 (file)
@@ -203,18 +203,19 @@ typedef struct {
 /** Should BDP probing be performed? */
 #define GRPC_ARG_HTTP2_BDP_PROBE "grpc.http2.bdp_probe"
 /** Minimum time between sending successive ping frames without receiving any
-    data frame, Int valued, milliseconds. */
+    data/header/window_update frame, Int valued, milliseconds. */
 #define GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS \
   "grpc.http2.min_time_between_pings_ms"
 /** Minimum allowed time between a server receiving successive ping frames
-   without sending any data frame. Int valued, milliseconds */
+   without sending any data/header/window_update frame. Int valued, milliseconds
+ */
 #define GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS \
   "grpc.http2.min_ping_interval_without_data_ms"
 /** Channel arg to override the http2 :scheme header */
 #define GRPC_ARG_HTTP2_SCHEME "grpc.http2_scheme"
-/** How many pings can we send before needing to send a data frame or header
-    frame? (0 indicates that an infinite number of pings can be sent without
-    sending a data frame or header frame) */
+/** How many pings can we send before needing to send a
+   data/header/window_update frame? (0 indicates that an infinite number of
+   pings can be sent without sending a data frame or header frame) */
 #define GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA \
   "grpc.http2.max_pings_without_data"
 /** How many misbehaving pings the server can bear before sending goaway and
@@ -359,11 +360,6 @@ typedef struct {
  * The default is 15 seconds. */
 #define GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS \
   "grpc.xds_resource_does_not_exist_timeout_ms"
-/* If set, enable xds routing policy.  This boolean argument is currently
- * disabled by default; however, it will be changed to enabled by default
- * once the functionality proves stable.  This arg will eventually
- * be removed completely. */
-#define GRPC_ARG_XDS_ROUTING_ENABLED "grpc.xds_routing_enabled"
 /** If non-zero, grpc server's cronet compression workaround will be enabled */
 #define GRPC_ARG_WORKAROUND_CRONET_COMPRESSION \
   "grpc.workaround.cronet_compression"
@@ -391,6 +387,9 @@ typedef struct {
   "grpc.disable_client_authority_filter"
 /** If set to zero, disables use of http proxies. Enabled by default. */
 #define GRPC_ARG_ENABLE_HTTP_PROXY "grpc.enable_http_proxy"
+/** Channel arg to set http proxy per channel. If set, the channel arg
+ *  value will be prefered over the envrionment variable settings. */
+#define GRPC_ARG_HTTP_PROXY "grpc.http_proxy"
 /** If set to non zero, surfaces the user agent string to the server. User
     agent is surfaced by default. */
 #define GRPC_ARG_SURFACE_USER_AGENT "grpc.surface_user_agent"
index cb3fb79..4f213ff 100644 (file)
@@ -53,6 +53,8 @@
 #define NOMINMAX
 #endif /* NOMINMAX */
 
+#include <windows.h>
+
 #ifndef _WIN32_WINNT
 #error \
     "Please compile grpc with _WIN32_WINNT of at least 0x600 (aka Windows Vista)"
@@ -63,8 +65,6 @@
 #endif /* _WIN32_WINNT < 0x0600 */
 #endif /* defined(_WIN32_WINNT) */
 
-#include <windows.h>
-
 #ifdef GRPC_WIN32_LEAN_AND_MEAN_WAS_NOT_DEFINED
 #undef GRPC_WIN32_LEAN_AND_MEAN_WAS_NOT_DEFINED
 #undef WIN32_LEAN_AND_MEAN
@@ -666,18 +666,22 @@ typedef unsigned __int64 uint64_t;
 #endif /* GPR_ATTRIBUTE_NO_TSAN (1) */
 
 /* GRPC_TSAN_ENABLED will be defined, when compiled with thread sanitizer. */
+#ifndef GRPC_TSAN_SUPPRESSED
 #if defined(__SANITIZE_THREAD__)
 #define GRPC_TSAN_ENABLED
 #elif GPR_HAS_FEATURE(thread_sanitizer)
 #define GRPC_TSAN_ENABLED
 #endif
+#endif
 
 /* GRPC_ASAN_ENABLED will be defined, when compiled with address sanitizer. */
+#ifndef GRPC_ASAN_SUPPRESSED
 #if defined(__SANITIZE_ADDRESS__)
 #define GRPC_ASAN_ENABLED
 #elif GPR_HAS_FEATURE(address_sanitizer)
 #define GRPC_ASAN_ENABLED
 #endif
+#endif
 
 /* GRPC_ALLOW_EXCEPTIONS should be 0 or 1 if exceptions are allowed or not */
 #ifndef GRPC_ALLOW_EXCEPTIONS
index e6d7b90..ba91404 100644 (file)
@@ -421,17 +421,12 @@ Status CallOpSendMessage::SendMessagePtr(const M* message) {
 template <class R>
 class CallOpRecvMessage {
  public:
-  CallOpRecvMessage()
-      : got_message(false),
-        message_(nullptr),
-        allow_not_getting_message_(false) {}
-
   void RecvMessage(R* message) { message_ = message; }
 
   // Do not change status if no message is received.
   void AllowNoMessage() { allow_not_getting_message_ = true; }
 
-  bool got_message;
+  bool got_message = false;
 
  protected:
   void AddOp(grpc_op* ops, size_t* nops) {
@@ -444,7 +439,7 @@ class CallOpRecvMessage {
   }
 
   void FinishOp(bool* status) {
-    if (message_ == nullptr || hijacked_) return;
+    if (message_ == nullptr) return;
     if (recv_buf_.Valid()) {
       if (*status) {
         got_message = *status =
@@ -455,18 +450,24 @@ class CallOpRecvMessage {
         got_message = false;
         recv_buf_.Clear();
       }
-    } else {
-      got_message = false;
-      if (!allow_not_getting_message_) {
-        *status = false;
+    } else if (hijacked_) {
+      if (hijacked_recv_message_failed_) {
+        FinishOpRecvMessageFailureHandler(status);
+      } else {
+        // The op was hijacked and it was successful. There is no further action
+        // to be performed since the message is already in its non-serialized
+        // form.
       }
+    } else {
+      FinishOpRecvMessageFailureHandler(status);
     }
   }
 
   void SetInterceptionHookPoint(
       InterceptorBatchMethodsImpl* interceptor_methods) {
     if (message_ == nullptr) return;
-    interceptor_methods->SetRecvMessage(message_, &got_message);
+    interceptor_methods->SetRecvMessage(message_,
+                                        &hijacked_recv_message_failed_);
   }
 
   void SetFinishInterceptionHookPoint(
@@ -485,10 +486,19 @@ class CallOpRecvMessage {
   }
 
  private:
-  R* message_;
+  // Sets got_message and \a status for a failed recv message op
+  void FinishOpRecvMessageFailureHandler(bool* status) {
+    got_message = false;
+    if (!allow_not_getting_message_) {
+      *status = false;
+    }
+  }
+
+  R* message_ = nullptr;
   ByteBuffer recv_buf_;
-  bool allow_not_getting_message_;
+  bool allow_not_getting_message_ = false;
   bool hijacked_ = false;
+  bool hijacked_recv_message_failed_ = false;
 };
 
 class DeserializeFunc {
@@ -513,9 +523,6 @@ class DeserializeFuncType final : public DeserializeFunc {
 
 class CallOpGenericRecvMessage {
  public:
-  CallOpGenericRecvMessage()
-      : got_message(false), allow_not_getting_message_(false) {}
-
   template <class R>
   void RecvMessage(R* message) {
     // Use an explicit base class pointer to avoid resolution error in the
@@ -528,7 +535,7 @@ class CallOpGenericRecvMessage {
   // Do not change status if no message is received.
   void AllowNoMessage() { allow_not_getting_message_ = true; }
 
-  bool got_message;
+  bool got_message = false;
 
  protected:
   void AddOp(grpc_op* ops, size_t* nops) {
@@ -551,6 +558,14 @@ class CallOpGenericRecvMessage {
         got_message = false;
         recv_buf_.Clear();
       }
+    } else if (hijacked_) {
+      if (hijacked_recv_message_failed_) {
+        FinishOpRecvMessageFailureHandler(status);
+      } else {
+        // The op was hijacked and it was successful. There is no further action
+        // to be performed since the message is already in its non-serialized
+        // form.
+      }
     } else {
       got_message = false;
       if (!allow_not_getting_message_) {
@@ -562,7 +577,8 @@ class CallOpGenericRecvMessage {
   void SetInterceptionHookPoint(
       InterceptorBatchMethodsImpl* interceptor_methods) {
     if (!deserialize_) return;
-    interceptor_methods->SetRecvMessage(message_, &got_message);
+    interceptor_methods->SetRecvMessage(message_,
+                                        &hijacked_recv_message_failed_);
   }
 
   void SetFinishInterceptionHookPoint(
@@ -582,11 +598,20 @@ class CallOpGenericRecvMessage {
   }
 
  private:
-  void* message_;
-  bool hijacked_ = false;
+  // Sets got_message and \a status for a failed recv message op
+  void FinishOpRecvMessageFailureHandler(bool* status) {
+    got_message = false;
+    if (!allow_not_getting_message_) {
+      *status = false;
+    }
+  }
+
+  void* message_ = nullptr;
   std::unique_ptr<DeserializeFunc> deserialize_;
   ByteBuffer recv_buf_;
-  bool allow_not_getting_message_;
+  bool allow_not_getting_message_ = false;
+  bool hijacked_ = false;
+  bool hijacked_recv_message_failed_ = false;
 };
 
 class CallOpClientSendClose {
@@ -828,7 +853,7 @@ class CallOpSet;
 /// the maximum count of ops we'll need in a set. We leverage the
 /// empty base class optimization to slim this class (especially
 /// when there are many unused slots used). To avoid duplicate base classes,
-/// the template parmeter for CallNoOp is varied by argument position.
+/// the template parameter for CallNoOp is varied by argument position.
 template <class Op1, class Op2, class Op3, class Op4, class Op5, class Op6>
 class CallOpSet : public CallOpSetInterface,
                   public Op1,
index 18c7cf3..71c32d7 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef GRPCPP_IMPL_CODEGEN_INTERCEPTOR_H
 #define GRPCPP_IMPL_CODEGEN_INTERCEPTOR_H
 
+#include <memory>
+
 #include <grpc/impl/codegen/grpc_types.h>
 #include <grpcpp/impl/codegen/byte_buffer.h>
 #include <grpcpp/impl/codegen/config.h>
index 01ffe19..c87c803 100644 (file)
@@ -166,9 +166,9 @@ class InterceptorBatchMethodsImpl
     send_trailing_metadata_ = metadata;
   }
 
-  void SetRecvMessage(void* message, bool* got_message) {
+  void SetRecvMessage(void* message, bool* hijacked_recv_message_failed) {
     recv_message_ = message;
-    got_message_ = got_message;
+    hijacked_recv_message_failed_ = hijacked_recv_message_failed;
   }
 
   void SetRecvInitialMetadata(MetadataMap* map) {
@@ -195,7 +195,7 @@ class InterceptorBatchMethodsImpl
   void FailHijackedRecvMessage() override {
     GPR_CODEGEN_ASSERT(hooks_[static_cast<size_t>(
         experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)]);
-    *got_message_ = false;
+    *hijacked_recv_message_failed_ = true;
   }
 
   // Clears all state
@@ -407,7 +407,7 @@ class InterceptorBatchMethodsImpl
   std::multimap<grpc::string, grpc::string>* send_trailing_metadata_ = nullptr;
 
   void* recv_message_ = nullptr;
-  bool* got_message_ = nullptr;
+  bool* hijacked_recv_message_failed_ = nullptr;
 
   MetadataMap* recv_initial_metadata_ = nullptr;
 
index d832268..d29e56e 100644 (file)
 #ifndef GRPCPP_SECURITY_TLS_CREDENTIALS_OPTIONS_H
 #define GRPCPP_SECURITY_TLS_CREDENTIALS_OPTIONS_H
 
-#include <memory>
-#include <vector>
-
 #include <grpc/grpc_security_constants.h>
 #include <grpc/status.h>
 #include <grpc/support/log.h>
 #include <grpcpp/support/config.h>
 
+#include <memory>
+#include <vector>
+
 typedef struct grpc_tls_credential_reload_arg grpc_tls_credential_reload_arg;
 typedef struct grpc_tls_credential_reload_config
     grpc_tls_credential_reload_config;
@@ -278,6 +278,21 @@ class TlsServerAuthorizationCheckConfig {
  * more details. **/
 class TlsCredentialsOptions {
  public:
+  // Constructor for client.
+  explicit TlsCredentialsOptions(
+      grpc_tls_server_verification_option server_verification_option,
+      std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config,
+      std::shared_ptr<TlsCredentialReloadConfig> credential_reload_config,
+      std::shared_ptr<TlsServerAuthorizationCheckConfig>
+          server_authorization_check_config);
+
+  // Constructor for server.
+  explicit TlsCredentialsOptions(
+      grpc_ssl_client_certificate_request_type cert_request_type,
+      std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config,
+      std::shared_ptr<TlsCredentialReloadConfig> credential_reload_config);
+
+  // This constructor will be deprecated.
   TlsCredentialsOptions(
       grpc_ssl_client_certificate_request_type cert_request_type,
       grpc_tls_server_verification_option server_verification_option,
index 294a798..171f1ac 100644 (file)
@@ -107,6 +107,8 @@ class ServerBuilder {
   ///     traffic (via AddListeningPort)
   ///  3. [for async api only] completion queues have been added via
   ///     AddCompletionQueue
+  ///
+  ///  Will return a nullptr on errors.
   virtual std::unique_ptr<grpc::Server> BuildAndStart();
 
   /// Register a service. This call does not take ownership of the service.
index 8572c74..5cbfee4 100644 (file)
@@ -291,6 +291,13 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
 
   grpc_impl::ServerInitializer* initializer();
 
+  // Functions to manage the server shutdown ref count. Things that increase
+  // the ref count are the running state of the server (take a ref at start and
+  // drop it at shutdown) and each running callback RPC.
+  void Ref();
+  void UnrefWithPossibleNotify() /* LOCKS_EXCLUDED(mu_) */;
+  void UnrefAndWaitLocked() /* EXCLUSIVE_LOCKS_REQUIRED(mu_) */;
+
   std::vector<std::shared_ptr<grpc::internal::ExternalConnectionAcceptorImpl>>
       acceptors_;
 
@@ -315,16 +322,6 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
   /// the \a sync_server_cqs)
   std::vector<std::unique_ptr<SyncRequestThreadManager>> sync_req_mgrs_;
 
-  // Outstanding unmatched callback requests, indexed by method.
-  // NOTE: Using a gpr_atm rather than atomic_int because atomic_int isn't
-  //       copyable or movable and thus will cause compilation errors. We
-  //       actually only want to extend the vector before the threaded use
-  //       starts, but this is still a limitation.
-  std::vector<gpr_atm> callback_unmatched_reqs_count_;
-
-  // List of callback requests to start when server actually starts.
-  std::list<CallbackRequestBase*> callback_reqs_to_start_;
-
 #ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL
   // For registering experimental callback generic service; remove when that
   // method longer experimental
@@ -336,25 +333,18 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
   bool started_;
   bool shutdown_;
   bool shutdown_notified_;  // Was notify called on the shutdown_cv_
+  grpc::internal::CondVar shutdown_done_cv_;
+  bool shutdown_done_ = false;
+  std::atomic_int shutdown_refs_outstanding_{1};
 
   grpc::internal::CondVar shutdown_cv_;
 
-  // It is ok (but not required) to nest callback_reqs_mu_ under mu_ .
-  // Incrementing callback_reqs_outstanding_ is ok without a lock but it must be
-  // decremented under the lock in case it is the last request and enables the
-  // server shutdown. The increment is performance-critical since it happens
-  // during periods of increasing load; the decrement happens only when memory
-  // is maxed out, during server shutdown, or (possibly in a future version)
-  // during decreasing load, so it is less performance-critical.
-  grpc::internal::Mutex callback_reqs_mu_;
-  grpc::internal::CondVar callback_reqs_done_cv_;
-  std::atomic<intptr_t> callback_reqs_outstanding_{0};
-
   std::shared_ptr<GlobalCallbacks> global_callbacks_;
 
   std::vector<grpc::string> services_;
-  bool has_async_generic_service_{false};
-  bool has_callback_generic_service_{false};
+  bool has_async_generic_service_ = false;
+  bool has_callback_generic_service_ = false;
+  bool has_callback_methods_ = false;
 
   // Pointer to the wrapped grpc_server.
   grpc_server* server_;
@@ -383,8 +373,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
   // with this server (if any). It is set on the first call to CallbackCQ().
   // It is _not owned_ by the server; ownership belongs with its internal
   // shutdown callback tag (invoked when the CQ is fully shutdown).
-  // It is protected by mu_
-  CompletionQueue* callback_cq_ = nullptr;
+  CompletionQueue* callback_cq_ /* GUARDED_BY(mu_) */ = nullptr;
 
   // List of CQs passed in by user that must be Shutdown only after Server is
   // Shutdown.  Even though this is only used with NDEBUG, instantiate it in all
index 9174d2d..6383fe7 100644 (file)
@@ -13,8 +13,8 @@
  <date>2019-09-24</date>
  <time>16:06:07</time>
  <version>
-  <release>1.29.1</release>
-  <api>1.29.1</api>
+  <release>1.30.0</release>
+  <api>1.30.0</api>
  </version>
  <stability>
   <release>stable</release>
@@ -22,7 +22,7 @@
  </stability>
  <license>Apache 2.0</license>
  <notes>
-- gRPC Core 1.29.1 update
+- gRPC Core 1.30.0 update
  </notes>
  <contents>
   <dir baseinstalldir="/" name="/">
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/server_address.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_call_data.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_parser.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_parser.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_interface.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/annotations/resource.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cds.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cds.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/eds.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/migrate.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/status.upb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/status.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/validate/validate.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/global_config_generic.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/host_port.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/host_port.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/gprpp/inlined_vector.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/manual_constructor.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/map.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/memory.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/mpscq.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/mpscq.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/gprpp/optional.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/orphanable.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/ref_counted.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/ref_counted_ptr.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/gprpp/string_view.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/sync.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/thd.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/thd_posix.cc" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/cpu-intel.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/cpu-ppc64le.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/crypto.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519_tables.h" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/curve25519/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/curve25519/spake25519.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/dh/check.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/dh/dh.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/dsa/dsa_asn1.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_asn1.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_derive.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/ec_extra/hash_to_curve.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/ec_extra/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/ecdh_extra/ecdh_extra.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/ecdsa_extra/ecdsa_asn1.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/engine/engine.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-x86_64-table.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-x86_64.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-x86_64.h" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256_table.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/scalar.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple_mul.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/ofb.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/polyval.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/ctrdrbg.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/fork_detect.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/fork_detect.h" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/getrandom_fillin.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/rand.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/urandom.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/thread_none.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/thread_pthread.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/thread_win.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/trust_token/internal.h" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/x509/a_digest.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/x509/a_sign.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/x509/a_strex.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/include/openssl/stack.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/include/openssl/thread.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/include/openssl/tls1.h" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/include/openssl/trust_token.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/include/openssl/type_check.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/include/openssl/x509.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/include/openssl/x509_vfy.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/ssl/tls13_server.cc" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/ssl/tls_method.cc" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/ssl/tls_record.cc" role="src" />
-    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/third_party/fiat/curve25519.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_32.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_64.h" role="src" />
-    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_tables.h" role="src" />
-    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/third_party/fiat/internal.h" role="src" />
-    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/third_party/fiat/p256.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/third_party/fiat/p256_32.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/third_party/fiat/p256_64.h" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/decode.c" role="src" />
index 4d52beb..10b4755 100644 (file)
@@ -6,7 +6,7 @@ protobuf>=3.5.0.post1
 six>=1.10
 wheel>=0.29
 futures>=2.2.0
-google-auth>=1.0.0
+google-auth>=1.17.2
 oauth2client==4.1.0
 requests>=2.14.2
 urllib3>=1.23
index a1562c7..2379703 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -11,7 +11,6 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-
 """A setup module for the GRPC Python package."""
 from distutils import cygwinccompiler
 from distutils import extension as _extension
@@ -37,23 +36,30 @@ egg_info.manifest_maker.template = 'PYTHON-MANIFEST.in'
 
 PY3 = sys.version_info.major == 3
 PYTHON_STEM = os.path.join('src', 'python', 'grpcio')
-CORE_INCLUDE = ('include', '.',)
+CORE_INCLUDE = (
+    'include',
+    '.',
+)
 ABSL_INCLUDE = (os.path.join('third_party', 'abseil-cpp'),)
-ADDRESS_SORTING_INCLUDE = (os.path.join('third_party', 'address_sorting', 'include'),)
+ADDRESS_SORTING_INCLUDE = (os.path.join('third_party', 'address_sorting',
+                                        'include'),)
 CARES_INCLUDE = (
     os.path.join('third_party', 'cares'),
-    os.path.join('third_party', 'cares', 'cares'),)
+    os.path.join('third_party', 'cares', 'cares'),
+)
 if 'darwin' in sys.platform:
-  CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_darwin'),)
+    CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_darwin'),)
 if 'freebsd' in sys.platform:
-  CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_freebsd'),)
+    CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_freebsd'),)
 if 'linux' in sys.platform:
-  CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_linux'),)
+    CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_linux'),)
 if 'openbsd' in sys.platform:
-  CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_openbsd'),)
-SSL_INCLUDE = (os.path.join('third_party', 'boringssl-with-bazel', 'src', 'include'),)
+    CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_openbsd'),)
+SSL_INCLUDE = (os.path.join('third_party', 'boringssl-with-bazel', 'src',
+                            'include'),)
 UPB_INCLUDE = (os.path.join('third_party', 'upb'),)
-UPB_GRPC_GENERATED_INCLUDE = (os.path.join('src', 'core', 'ext', 'upb-generated'),)
+UPB_GRPC_GENERATED_INCLUDE = (os.path.join('src', 'core', 'ext',
+                                           'upb-generated'),)
 ZLIB_INCLUDE = (os.path.join('third_party', 'zlib'),)
 README = os.path.join(PYTHON_STEM, 'README.rst')
 
@@ -79,7 +85,6 @@ CLASSIFIERS = [
     'Programming Language :: Python :: 2',
     'Programming Language :: Python :: 2.7',
     'Programming Language :: Python :: 3',
-    'Programming Language :: Python :: 3.4',
     'Programming Language :: Python :: 3.5',
     'Programming Language :: Python :: 3.6',
     'Programming Language :: Python :: 3.7',
@@ -94,7 +99,6 @@ CLASSIFIERS = [
 # present, then it will still attempt to use Cython.
 BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False)
 
-
 # Export this variable to use the system installation of openssl. You need to
 # have the header files installed (in /usr/include/openssl) and during
 # runtime, the shared library must be installed
@@ -104,8 +108,7 @@ BUILD_WITH_SYSTEM_OPENSSL = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_OPENSSL',
 # Export this variable to use the system installation of zlib. You need to
 # have the header files installed (in /usr/include/) and during
 # runtime, the shared library must be installed
-BUILD_WITH_SYSTEM_ZLIB = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_ZLIB',
-                                        False)
+BUILD_WITH_SYSTEM_ZLIB = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_ZLIB', False)
 
 # Export this variable to use the system installation of cares. You need to
 # have the header files installed (in /usr/include/) and during
@@ -124,34 +127,36 @@ BUILD_WITH_SYSTEM_CARES = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_CARES',
 #    make HAS_SYSTEM_OPENSSL_ALPN=0
 #
 # TODO(ericgribkoff) Respect the BUILD_WITH_SYSTEM_* flags alongside this option
-USE_PREBUILT_GRPC_CORE = os.environ.get(
-    'GRPC_PYTHON_USE_PREBUILT_GRPC_CORE', False)
-
+USE_PREBUILT_GRPC_CORE = os.environ.get('GRPC_PYTHON_USE_PREBUILT_GRPC_CORE',
+                                        False)
 
 # If this environmental variable is set, GRPC will not try to be compatible with
 # libc versions old than the one it was compiled against.
-DISABLE_LIBC_COMPATIBILITY = os.environ.get('GRPC_PYTHON_DISABLE_LIBC_COMPATIBILITY', False)
+DISABLE_LIBC_COMPATIBILITY = os.environ.get(
+    'GRPC_PYTHON_DISABLE_LIBC_COMPATIBILITY', False)
 
 # Environment variable to determine whether or not to enable coverage analysis
 # in Cython modules.
-ENABLE_CYTHON_TRACING = os.environ.get(
-    'GRPC_PYTHON_ENABLE_CYTHON_TRACING', False)
+ENABLE_CYTHON_TRACING = os.environ.get('GRPC_PYTHON_ENABLE_CYTHON_TRACING',
+                                       False)
 
 # Environment variable specifying whether or not there's interest in setting up
 # documentation building.
 ENABLE_DOCUMENTATION_BUILD = os.environ.get(
     'GRPC_PYTHON_ENABLE_DOCUMENTATION_BUILD', False)
 
+
 def check_linker_need_libatomic():
-  """Test if linker on system needs libatomic."""
-  code_test = (b'#include <atomic>\n' +
-               b'int main() { return std::atomic<int64_t>{}; }')
-  cc_test = subprocess.Popen(['cc', '-x', 'c++', '-std=c++11', '-'],
-                             stdin=PIPE,
-                             stdout=PIPE,
-                             stderr=PIPE)
-  cc_test.communicate(input=code_test)
-  return cc_test.returncode != 0
+    """Test if linker on system needs libatomic."""
+    code_test = (b'#include <atomic>\n' +
+                 b'int main() { return std::atomic<int64_t>{}; }')
+    cc_test = subprocess.Popen(['cc', '-x', 'c++', '-std=c++11', '-'],
+                               stdin=PIPE,
+                               stdout=PIPE,
+                               stderr=PIPE)
+    cc_test.communicate(input=code_test)
+    return cc_test.returncode != 0
+
 
 # There are some situations (like on Windows) where CC, CFLAGS, and LDFLAGS are
 # entirely ignored/dropped/forgotten by distutils and its Cygwin/MinGW support.
@@ -163,40 +168,40 @@ def check_linker_need_libatomic():
 EXTRA_ENV_COMPILE_ARGS = os.environ.get('GRPC_PYTHON_CFLAGS', None)
 EXTRA_ENV_LINK_ARGS = os.environ.get('GRPC_PYTHON_LDFLAGS', None)
 if EXTRA_ENV_COMPILE_ARGS is None:
-  EXTRA_ENV_COMPILE_ARGS = ' -std=c++11'
-  if 'win32' in sys.platform:
-    if sys.version_info < (3, 5):
-      EXTRA_ENV_COMPILE_ARGS += ' -D_hypot=hypot'
-      # We use define flags here and don't directly add to DEFINE_MACROS below to
-      # ensure that the expert user/builder has a way of turning it off (via the
-      # envvars) without adding yet more GRPC-specific envvars.
-      # See https://sourceforge.net/p/mingw-w64/bugs/363/
-      if '32' in platform.architecture()[0]:
-        EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s'
-      else:
-        EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64'
-    else:
-      # We need to statically link the C++ Runtime, only the C runtime is
-      # available dynamically
-      EXTRA_ENV_COMPILE_ARGS += ' /MT'
-  elif "linux" in sys.platform:
-    EXTRA_ENV_COMPILE_ARGS += ' -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
-  elif "darwin" in sys.platform:
-    EXTRA_ENV_COMPILE_ARGS += ' -stdlib=libc++ -fvisibility=hidden -fno-wrapv -fno-exceptions'
+    EXTRA_ENV_COMPILE_ARGS = ' -std=c++11'
+    if 'win32' in sys.platform:
+        if sys.version_info < (3, 5):
+            EXTRA_ENV_COMPILE_ARGS += ' -D_hypot=hypot'
+            # We use define flags here and don't directly add to DEFINE_MACROS below to
+            # ensure that the expert user/builder has a way of turning it off (via the
+            # envvars) without adding yet more GRPC-specific envvars.
+            # See https://sourceforge.net/p/mingw-w64/bugs/363/
+            if '32' in platform.architecture()[0]:
+                EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s'
+            else:
+                EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64'
+        else:
+            # We need to statically link the C++ Runtime, only the C runtime is
+            # available dynamically
+            EXTRA_ENV_COMPILE_ARGS += ' /MT'
+    elif "linux" in sys.platform:
+        EXTRA_ENV_COMPILE_ARGS += ' -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
+    elif "darwin" in sys.platform:
+        EXTRA_ENV_COMPILE_ARGS += ' -stdlib=libc++ -fvisibility=hidden -fno-wrapv -fno-exceptions'
 
 if EXTRA_ENV_LINK_ARGS is None:
-  EXTRA_ENV_LINK_ARGS = ''
-  if "linux" in sys.platform or "darwin" in sys.platform:
-    EXTRA_ENV_LINK_ARGS += ' -lpthread'
-    if check_linker_need_libatomic():
-      EXTRA_ENV_LINK_ARGS += ' -latomic'
-  elif "win32" in sys.platform and sys.version_info < (3, 5):
-    msvcr = cygwinccompiler.get_msvcr()[0]
-    EXTRA_ENV_LINK_ARGS += (
-        ' -static-libgcc -static-libstdc++ -mcrtdll={msvcr}'
-        ' -static -lshlwapi'.format(msvcr=msvcr))
-  if "linux" in sys.platform:
-    EXTRA_ENV_LINK_ARGS += ' -Wl,-wrap,memcpy -static-libgcc'
+    EXTRA_ENV_LINK_ARGS = ''
+    if "linux" in sys.platform or "darwin" in sys.platform:
+        EXTRA_ENV_LINK_ARGS += ' -lpthread'
+        if check_linker_need_libatomic():
+            EXTRA_ENV_LINK_ARGS += ' -latomic'
+    elif "win32" in sys.platform and sys.version_info < (3, 5):
+        msvcr = cygwinccompiler.get_msvcr()[0]
+        EXTRA_ENV_LINK_ARGS += (
+            ' -static-libgcc -static-libstdc++ -mcrtdll={msvcr}'
+            ' -static -lshlwapi'.format(msvcr=msvcr))
+    if "linux" in sys.platform:
+        EXTRA_ENV_LINK_ARGS += ' -Wl,-wrap,memcpy -static-libgcc'
 
 EXTRA_COMPILE_ARGS = shlex.split(EXTRA_ENV_COMPILE_ARGS)
 EXTRA_LINK_ARGS = shlex.split(EXTRA_ENV_LINK_ARGS)
@@ -209,119 +214,135 @@ CYTHON_HELPER_C_FILES = ()
 
 CORE_C_FILES = tuple(grpc_core_dependencies.CORE_SOURCE_FILES)
 if "win32" in sys.platform:
-  CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
+    CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
 
 if BUILD_WITH_SYSTEM_OPENSSL:
-  CORE_C_FILES = filter(lambda x: 'third_party/boringssl' not in x, CORE_C_FILES)
-  CORE_C_FILES = filter(lambda x: 'src/boringssl' not in x, CORE_C_FILES)
-  SSL_INCLUDE = (os.path.join('/usr', 'include', 'openssl'),)
+    CORE_C_FILES = filter(lambda x: 'third_party/boringssl' not in x,
+                          CORE_C_FILES)
+    CORE_C_FILES = filter(lambda x: 'src/boringssl' not in x, CORE_C_FILES)
+    SSL_INCLUDE = (os.path.join('/usr', 'include', 'openssl'),)
 
 if BUILD_WITH_SYSTEM_ZLIB:
-  CORE_C_FILES = filter(lambda x: 'third_party/zlib' not in x, CORE_C_FILES)
-  ZLIB_INCLUDE = (os.path.join('/usr', 'include'),)
+    CORE_C_FILES = filter(lambda x: 'third_party/zlib' not in x, CORE_C_FILES)
+    ZLIB_INCLUDE = (os.path.join('/usr', 'include'),)
 
 if BUILD_WITH_SYSTEM_CARES:
-  CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
-  CARES_INCLUDE = (os.path.join('/usr', 'include'),)
-
-EXTENSION_INCLUDE_DIRECTORIES = (
-    (PYTHON_STEM,) +
-    CORE_INCLUDE +
-    ABSL_INCLUDE +
-    ADDRESS_SORTING_INCLUDE +
-    CARES_INCLUDE +
-    SSL_INCLUDE +
-    UPB_INCLUDE +
-    UPB_GRPC_GENERATED_INCLUDE +
-    ZLIB_INCLUDE)
+    CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
+    CARES_INCLUDE = (os.path.join('/usr', 'include'),)
+
+EXTENSION_INCLUDE_DIRECTORIES = ((PYTHON_STEM,) + CORE_INCLUDE + ABSL_INCLUDE +
+                                 ADDRESS_SORTING_INCLUDE + CARES_INCLUDE +
+                                 SSL_INCLUDE + UPB_INCLUDE +
+                                 UPB_GRPC_GENERATED_INCLUDE + ZLIB_INCLUDE)
 
 EXTENSION_LIBRARIES = ()
 if "linux" in sys.platform:
-  EXTENSION_LIBRARIES += ('rt',)
+    EXTENSION_LIBRARIES += ('rt',)
 if not "win32" in sys.platform:
-  EXTENSION_LIBRARIES += ('m',)
+    EXTENSION_LIBRARIES += ('m',)
 if "win32" in sys.platform:
-  EXTENSION_LIBRARIES += ('advapi32', 'ws2_32', 'dbghelp',)
+    EXTENSION_LIBRARIES += (
+        'advapi32',
+        'ws2_32',
+        'dbghelp',
+    )
 if BUILD_WITH_SYSTEM_OPENSSL:
-  EXTENSION_LIBRARIES += ('ssl', 'crypto',)
+    EXTENSION_LIBRARIES += (
+        'ssl',
+        'crypto',
+    )
 if BUILD_WITH_SYSTEM_ZLIB:
-  EXTENSION_LIBRARIES += ('z',)
+    EXTENSION_LIBRARIES += ('z',)
 if BUILD_WITH_SYSTEM_CARES:
-  EXTENSION_LIBRARIES += ('cares',)
+    EXTENSION_LIBRARIES += ('cares',)
 
 DEFINE_MACROS = (('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600))
 if not DISABLE_LIBC_COMPATIBILITY:
-  DEFINE_MACROS += (('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),)
+    DEFINE_MACROS += (('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),)
 if "win32" in sys.platform:
-  # TODO(zyc): Re-enable c-ares on x64 and x86 windows after fixing the
-  # ares_library_init compilation issue
-  DEFINE_MACROS += (('WIN32_LEAN_AND_MEAN', 1), ('CARES_STATICLIB', 1),
-                    ('GRPC_ARES', 0), ('NTDDI_VERSION', 0x06000000),
-                    ('NOMINMAX', 1),)
-  if '64bit' in platform.architecture()[0]:
-    DEFINE_MACROS += (('MS_WIN64', 1),)
-  elif sys.version_info >= (3, 5):
-    # For some reason, this is needed to get access to inet_pton/inet_ntop
-    # on msvc, but only for 32 bits
-    DEFINE_MACROS += (('NTDDI_VERSION', 0x06000000),)
+    # TODO(zyc): Re-enable c-ares on x64 and x86 windows after fixing the
+    # ares_library_init compilation issue
+    DEFINE_MACROS += (
+        ('WIN32_LEAN_AND_MEAN', 1),
+        ('CARES_STATICLIB', 1),
+        ('GRPC_ARES', 0),
+        ('NTDDI_VERSION', 0x06000000),
+        ('NOMINMAX', 1),
+    )
+    if '64bit' in platform.architecture()[0]:
+        DEFINE_MACROS += (('MS_WIN64', 1),)
+    elif sys.version_info >= (3, 5):
+        # For some reason, this is needed to get access to inet_pton/inet_ntop
+        # on msvc, but only for 32 bits
+        DEFINE_MACROS += (('NTDDI_VERSION', 0x06000000),)
 else:
-  DEFINE_MACROS += (('HAVE_CONFIG_H', 1), ('GRPC_ENABLE_FORK_SUPPORT', 1),)
+    DEFINE_MACROS += (
+        ('HAVE_CONFIG_H', 1),
+        ('GRPC_ENABLE_FORK_SUPPORT', 1),
+    )
 
 LDFLAGS = tuple(EXTRA_LINK_ARGS)
 CFLAGS = tuple(EXTRA_COMPILE_ARGS)
 if "linux" in sys.platform or "darwin" in sys.platform:
-  pymodinit_type = 'PyObject*' if PY3 else 'void'
-  pymodinit = 'extern "C" __attribute__((visibility ("default"))) {}'.format(pymodinit_type)
-  DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),)
-  DEFINE_MACROS += (('GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK', 1),)
+    pymodinit_type = 'PyObject*' if PY3 else 'void'
+    pymodinit = 'extern "C" __attribute__((visibility ("default"))) {}'.format(
+        pymodinit_type)
+    DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),)
+    DEFINE_MACROS += (('GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK', 1),)
 
 # By default, Python3 distutils enforces compatibility of
 # c plugins (.so files) with the OSX version Python3 was built with.
 # For Python3.4, this is OSX 10.6, but we need Thread Local Support (__thread)
 if 'darwin' in sys.platform and PY3:
-  mac_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
-  if mac_target and (pkg_resources.parse_version(mac_target) <
-                     pkg_resources.parse_version('10.7.0')):
-    os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
-    os.environ['_PYTHON_HOST_PLATFORM'] = re.sub(
-        r'macosx-[0-9]+\.[0-9]+-(.+)',
-        r'macosx-10.7-\1',
-        util.get_platform())
+    mac_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
+    if mac_target and (pkg_resources.parse_version(mac_target) <
+                       pkg_resources.parse_version('10.7.0')):
+        os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
+        os.environ['_PYTHON_HOST_PLATFORM'] = re.sub(
+            r'macosx-[0-9]+\.[0-9]+-(.+)', r'macosx-10.7-\1',
+            util.get_platform())
 
 
 def cython_extensions_and_necessity():
-  cython_module_files = [os.path.join(PYTHON_STEM,
-                               name.replace('.', '/') + '.pyx')
-                  for name in CYTHON_EXTENSION_MODULE_NAMES]
-  config = os.environ.get('CONFIG', 'opt')
-  prefix = 'libs/' + config + '/'
-  if USE_PREBUILT_GRPC_CORE:
-    extra_objects = [prefix + 'libares.a',
-                     prefix + 'libboringssl.a',
-                     prefix + 'libgpr.a',
-                     prefix + 'libgrpc.a']
-    core_c_files = []
-  else:
-    core_c_files = list(CORE_C_FILES)
-    extra_objects = []
-  extensions = [
-      _extension.Extension(
-          name=module_name,
-          sources=[module_file] + list(CYTHON_HELPER_C_FILES) + core_c_files,
-          include_dirs=list(EXTENSION_INCLUDE_DIRECTORIES),
-          libraries=list(EXTENSION_LIBRARIES),
-          define_macros=list(DEFINE_MACROS),
-          extra_objects=extra_objects,
-          extra_compile_args=list(CFLAGS),
-          extra_link_args=list(LDFLAGS),
-      ) for (module_name, module_file) in zip(list(CYTHON_EXTENSION_MODULE_NAMES), cython_module_files)
-  ]
-  need_cython = BUILD_WITH_CYTHON
-  if not BUILD_WITH_CYTHON:
-    need_cython = need_cython or not commands.check_and_update_cythonization(extensions)
-  # TODO: the strategy for conditional compiling and exposing the aio Cython
-  # dependencies will be revisited by https://github.com/grpc/grpc/issues/19728
-  return commands.try_cythonize(extensions, linetracing=ENABLE_CYTHON_TRACING, mandatory=BUILD_WITH_CYTHON), need_cython
+    cython_module_files = [
+        os.path.join(PYTHON_STEM,
+                     name.replace('.', '/') + '.pyx')
+        for name in CYTHON_EXTENSION_MODULE_NAMES
+    ]
+    config = os.environ.get('CONFIG', 'opt')
+    prefix = 'libs/' + config + '/'
+    if USE_PREBUILT_GRPC_CORE:
+        extra_objects = [
+            prefix + 'libares.a', prefix + 'libboringssl.a',
+            prefix + 'libgpr.a', prefix + 'libgrpc.a'
+        ]
+        core_c_files = []
+    else:
+        core_c_files = list(CORE_C_FILES)
+        extra_objects = []
+    extensions = [
+        _extension.Extension(
+            name=module_name,
+            sources=[module_file] + list(CYTHON_HELPER_C_FILES) + core_c_files,
+            include_dirs=list(EXTENSION_INCLUDE_DIRECTORIES),
+            libraries=list(EXTENSION_LIBRARIES),
+            define_macros=list(DEFINE_MACROS),
+            extra_objects=extra_objects,
+            extra_compile_args=list(CFLAGS),
+            extra_link_args=list(LDFLAGS),
+        ) for (module_name, module_file
+              ) in zip(list(CYTHON_EXTENSION_MODULE_NAMES), cython_module_files)
+    ]
+    need_cython = BUILD_WITH_CYTHON
+    if not BUILD_WITH_CYTHON:
+        need_cython = need_cython or not commands.check_and_update_cythonization(
+            extensions)
+    # TODO: the strategy for conditional compiling and exposing the aio Cython
+    # dependencies will be revisited by https://github.com/grpc/grpc/issues/19728
+    return commands.try_cythonize(extensions,
+                                  linetracing=ENABLE_CYTHON_TRACING,
+                                  mandatory=BUILD_WITH_CYTHON), need_cython
+
 
 CYTHON_EXTENSION_MODULES, need_cython = cython_extensions_and_necessity()
 
@@ -338,20 +359,20 @@ INSTALL_REQUIRES = (
 SETUP_REQUIRES = INSTALL_REQUIRES + (
     'Sphinx~=1.8.1',
     'six>=1.10',
-  ) if ENABLE_DOCUMENTATION_BUILD else ()
+) if ENABLE_DOCUMENTATION_BUILD else ()
 
 try:
-  import Cython
+    import Cython
 except ImportError:
-  if BUILD_WITH_CYTHON:
-    sys.stderr.write(
-      "You requested a Cython build via GRPC_PYTHON_BUILD_WITH_CYTHON, "
-      "but do not have Cython installed. We won't stop you from using "
-      "other commands, but the extension files will fail to build.\n")
-  elif need_cython:
-    sys.stderr.write(
-        'We could not find Cython. Setup may take 10-20 minutes.\n')
-    SETUP_REQUIRES += ('cython>=0.23',)
+    if BUILD_WITH_CYTHON:
+        sys.stderr.write(
+            "You requested a Cython build via GRPC_PYTHON_BUILD_WITH_CYTHON, "
+            "but do not have Cython installed. We won't stop you from using "
+            "other commands, but the extension files will fail to build.\n")
+    elif need_cython:
+        sys.stderr.write(
+            'We could not find Cython. Setup may take 10-20 minutes.\n')
+        SETUP_REQUIRES += ('cython>=0.23',)
 
 COMMAND_CLASS = {
     'doc': commands.SphinxDocumentation,
@@ -364,9 +385,9 @@ COMMAND_CLASS = {
 # Ensure that package data is copied over before any commands have been run:
 credentials_dir = os.path.join(PYTHON_STEM, 'grpc', '_cython', '_credentials')
 try:
-  os.mkdir(credentials_dir)
+    os.mkdir(credentials_dir)
 except OSError:
-  pass
+    pass
 shutil.copyfile(os.path.join('etc', 'roots.pem'),
                 os.path.join(credentials_dir, 'roots.pem'))
 
@@ -382,20 +403,20 @@ PACKAGE_DATA = {
 PACKAGES = setuptools.find_packages(PYTHON_STEM)
 
 setuptools.setup(
-  name='grpcio',
-  version=grpc_version.VERSION,
-  description='HTTP/2-based RPC framework',
-  author='The gRPC Authors',
-  author_email='grpc-io@googlegroups.com',
-  url='https://grpc.io',
-  license=LICENSE,
-  classifiers=CLASSIFIERS,
-  long_description=open(README).read(),
-  ext_modules=CYTHON_EXTENSION_MODULES,
-  packages=list(PACKAGES),
-  package_dir=PACKAGE_DIRECTORIES,
-  package_data=PACKAGE_DATA,
-  install_requires=INSTALL_REQUIRES,
-  setup_requires=SETUP_REQUIRES,
-  cmdclass=COMMAND_CLASS,
+    name='grpcio',
+    version=grpc_version.VERSION,
+    description='HTTP/2-based RPC framework',
+    author='The gRPC Authors',
+    author_email='grpc-io@googlegroups.com',
+    url='https://grpc.io',
+    license=LICENSE,
+    classifiers=CLASSIFIERS,
+    long_description=open(README).read(),
+    ext_modules=CYTHON_EXTENSION_MODULES,
+    packages=list(PACKAGES),
+    package_dir=PACKAGE_DIRECTORIES,
+    package_data=PACKAGE_DATA,
+    install_requires=INSTALL_REQUIRES,
+    setup_requires=SETUP_REQUIRES,
+    cmdclass=COMMAND_CLASS,
 )
index 2e23a77..e288dd6 100644 (file)
@@ -110,7 +110,9 @@ add_library(grpc-interop
   SHARED
   src/main/cpp/grpc-interop.cc
   ${GRPC_SRC_DIR}/test/cpp/interop/interop_client.h
-  ${GRPC_SRC_DIR}/test/cpp/interop/interop_client.cc)
+  ${GRPC_SRC_DIR}/test/cpp/interop/interop_client.cc
+  ${GRPC_SRC_DIR}/test/core/util/histogram.h
+  ${GRPC_SRC_DIR}/test/core/util/histogram.cc)
 
 target_link_libraries(grpc-interop
   messages_proto_lib
index 46578af..6212040 100644 (file)
@@ -1,4 +1,4 @@
-// generated by generate_boringssl_prefix_header.sh on BoringSSL commit: 1c2769383f027befac5b75b6cedd25daf3bf4dcf
+// generated by generate_boringssl_prefix_header.sh on BoringSSL commit: 3ab047a8e377083a9b38dc908fe1612d5743a021
 
 // Copyright (c) 2018, Google Inc.
 //
@@ -82,6 +82,7 @@
 #define SSL_CTX_flush_sessions BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_flush_sessions)
 #define SSL_CTX_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_free)
 #define SSL_CTX_get0_certificate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_get0_certificate)
+#define SSL_CTX_get0_chain BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_get0_chain)
 #define SSL_CTX_get0_chain_certs BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_get0_chain_certs)
 #define SSL_CTX_get0_param BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_get0_param)
 #define SSL_CTX_get0_privatekey BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_get0_privatekey)
 #define SSL_CTX_set_default_verify_paths BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_default_verify_paths)
 #define SSL_CTX_set_dos_protection_cb BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_dos_protection_cb)
 #define SSL_CTX_set_early_data_enabled BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_early_data_enabled)
-#define SSL_CTX_set_ed25519_enabled BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_ed25519_enabled)
 #define SSL_CTX_set_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_ex_data)
 #define SSL_CTX_set_false_start_allowed_without_alpn BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_false_start_allowed_without_alpn)
 #define SSL_CTX_set_grease_enabled BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_grease_enabled)
 #define SSL_CTX_use_certificate_chain_file BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_use_certificate_chain_file)
 #define SSL_CTX_use_certificate_file BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_use_certificate_file)
 #define SSL_CTX_use_psk_identity_hint BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_use_psk_identity_hint)
+#define SSL_SESSION_copy_without_early_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_SESSION_copy_without_early_data)
 #define SSL_SESSION_early_data_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_SESSION_early_data_capable)
 #define SSL_SESSION_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_SESSION_free)
 #define SSL_SESSION_from_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_SESSION_from_bytes)
 #define SSL_set_psk_client_callback BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_psk_client_callback)
 #define SSL_set_psk_server_callback BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_psk_server_callback)
 #define SSL_set_purpose BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_purpose)
+#define SSL_set_quic_early_data_context BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_quic_early_data_context)
 #define SSL_set_quic_method BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_quic_method)
 #define SSL_set_quic_transport_params BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_quic_transport_params)
 #define SSL_set_quiet_shutdown BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_quiet_shutdown)
 #define SSL_set_token_binding_params BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_token_binding_params)
 #define SSL_set_trust BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_trust)
 #define SSL_set_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_verify)
+#define SSL_set_verify_algorithm_prefs BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_verify_algorithm_prefs)
 #define SSL_set_verify_depth BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_verify_depth)
 #define SSL_set_verify_result BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_verify_result)
 #define SSL_set_wfd BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_wfd)
 #define BIO_write_filename BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BIO_write_filename)
 #define BN_BLINDING_convert BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BN_BLINDING_convert)
 #define BN_BLINDING_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BN_BLINDING_free)
+#define BN_BLINDING_invalidate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BN_BLINDING_invalidate)
 #define BN_BLINDING_invert BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BN_BLINDING_invert)
 #define BN_BLINDING_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BN_BLINDING_new)
 #define BN_CTX_end BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BN_CTX_end)
 #define CRYPTO_cleanup_all_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_cleanup_all_ex_data)
 #define CRYPTO_ctr128_encrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_ctr128_encrypt)
 #define CRYPTO_ctr128_encrypt_ctr32 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_ctr128_encrypt_ctr32)
+#define CRYPTO_fork_detect_ignore_madv_wipeonfork_for_testing BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_fork_detect_ignore_madv_wipeonfork_for_testing)
 #define CRYPTO_free_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_free_ex_data)
 #define CRYPTO_gcm128_aad BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_gcm128_aad)
 #define CRYPTO_gcm128_decrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_gcm128_decrypt)
 #define CRYPTO_get_dynlock_lock_callback BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_get_dynlock_lock_callback)
 #define CRYPTO_get_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_get_ex_data)
 #define CRYPTO_get_ex_new_index BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_get_ex_new_index)
+#define CRYPTO_get_fork_generation BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_get_fork_generation)
 #define CRYPTO_get_lock_name BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_get_lock_name)
 #define CRYPTO_get_locking_callback BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_get_locking_callback)
 #define CRYPTO_get_thread_local BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_get_thread_local)
 #define CRYPTO_ghash_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_ghash_init)
 #define CRYPTO_has_asm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_has_asm)
 #define CRYPTO_hchacha20 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_hchacha20)
+#define CRYPTO_init_sysrand BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_init_sysrand)
 #define CRYPTO_is_confidential_build BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_is_confidential_build)
 #define CRYPTO_library_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_library_init)
 #define CRYPTO_malloc_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_malloc_init)
 #define CRYPTO_poly1305_finish BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_poly1305_finish)
 #define CRYPTO_poly1305_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_poly1305_init)
 #define CRYPTO_poly1305_update BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_poly1305_update)
+#define CRYPTO_pre_sandbox_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_pre_sandbox_init)
 #define CRYPTO_rdrand BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_rdrand)
 #define CRYPTO_rdrand_multiple8_buf BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_rdrand_multiple8_buf)
 #define CRYPTO_refcount_dec_and_test_zero BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_refcount_dec_and_test_zero)
 #define CRYPTO_set_locking_callback BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_set_locking_callback)
 #define CRYPTO_set_thread_local BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_set_thread_local)
 #define CRYPTO_sysrand BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_sysrand)
+#define CRYPTO_sysrand_if_available BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_sysrand_if_available)
 #define CRYPTO_tls1_prf BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_tls1_prf)
 #define CTR_DRBG_clear BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CTR_DRBG_clear)
 #define CTR_DRBG_generate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CTR_DRBG_generate)
 #define DH_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_free)
 #define DH_generate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_generate_key)
 #define DH_generate_parameters_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_generate_parameters_ex)
+#define DH_get0_g BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_get0_g)
 #define DH_get0_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_get0_key)
+#define DH_get0_p BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_get0_p)
 #define DH_get0_pqg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_get0_pqg)
+#define DH_get0_priv_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_get0_priv_key)
+#define DH_get0_pub_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_get0_pub_key)
+#define DH_get0_q BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_get0_q)
 #define DH_get_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_get_ex_data)
 #define DH_get_ex_new_index BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_get_ex_new_index)
 #define DH_marshal_parameters BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_marshal_parameters)
 #define DH_set0_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_set0_key)
 #define DH_set0_pqg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_set0_pqg)
 #define DH_set_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_set_ex_data)
+#define DH_set_length BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_set_length)
 #define DH_size BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_size)
 #define DH_up_ref BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_up_ref)
 #define DHparams_dup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DHparams_dup)
 #define DSA_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_free)
 #define DSA_generate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_generate_key)
 #define DSA_generate_parameters_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_generate_parameters_ex)
+#define DSA_get0_g BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_get0_g)
 #define DSA_get0_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_get0_key)
+#define DSA_get0_p BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_get0_p)
 #define DSA_get0_pqg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_get0_pqg)
+#define DSA_get0_priv_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_get0_priv_key)
+#define DSA_get0_pub_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_get0_pub_key)
+#define DSA_get0_q BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_get0_q)
 #define DSA_get_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_get_ex_data)
 #define DSA_get_ex_new_index BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_get_ex_new_index)
 #define DSA_marshal_parameters BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DSA_marshal_parameters)
 #define ECDSA_SIG_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_SIG_free)
 #define ECDSA_SIG_from_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_SIG_from_bytes)
 #define ECDSA_SIG_get0 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_SIG_get0)
+#define ECDSA_SIG_get0_r BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_SIG_get0_r)
+#define ECDSA_SIG_get0_s BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_SIG_get0_s)
 #define ECDSA_SIG_marshal BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_SIG_marshal)
 #define ECDSA_SIG_max_len BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_SIG_max_len)
 #define ECDSA_SIG_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_SIG_new)
 #define EVP_sha256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha256)
 #define EVP_sha384 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha384)
 #define EVP_sha512 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha512)
+#define EVP_sha512_256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha512_256)
 #define EVP_tls_cbc_copy_mac BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_tls_cbc_copy_mac)
 #define EVP_tls_cbc_digest_record BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_tls_cbc_digest_record)
 #define EVP_tls_cbc_record_digest_supported BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_tls_cbc_record_digest_supported)
 #define PKEY_USAGE_PERIOD_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, PKEY_USAGE_PERIOD_free)
 #define PKEY_USAGE_PERIOD_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, PKEY_USAGE_PERIOD_it)
 #define PKEY_USAGE_PERIOD_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, PKEY_USAGE_PERIOD_new)
+#define PMBTOKEN_PRETOKEN_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, PMBTOKEN_PRETOKEN_free)
 #define POLICYINFO_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, POLICYINFO_free)
 #define POLICYINFO_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, POLICYINFO_it)
 #define POLICYINFO_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, POLICYINFO_new)
 #define RAND_pseudo_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RAND_pseudo_bytes)
 #define RAND_seed BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RAND_seed)
 #define RAND_set_rand_method BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RAND_set_rand_method)
-#define RAND_set_urandom_fd BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RAND_set_urandom_fd)
 #define RAND_status BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RAND_status)
 #define RC4 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RC4)
 #define RC4_set_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RC4_set_key)
 #define RSA_generate_key_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_generate_key_ex)
 #define RSA_generate_key_fips BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_generate_key_fips)
 #define RSA_get0_crt_params BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get0_crt_params)
+#define RSA_get0_d BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get0_d)
+#define RSA_get0_dmp1 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get0_dmp1)
+#define RSA_get0_dmq1 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get0_dmq1)
+#define RSA_get0_e BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get0_e)
 #define RSA_get0_factors BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get0_factors)
+#define RSA_get0_iqmp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get0_iqmp)
 #define RSA_get0_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get0_key)
+#define RSA_get0_n BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get0_n)
+#define RSA_get0_p BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get0_p)
+#define RSA_get0_q BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get0_q)
 #define RSA_get_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get_ex_data)
 #define RSA_get_ex_new_index BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_get_ex_new_index)
 #define RSA_is_opaque BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_is_opaque)
 #define SHA384_Init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA384_Init)
 #define SHA384_Update BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA384_Update)
 #define SHA512 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA512)
+#define SHA512_256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA512_256)
+#define SHA512_256_Final BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA512_256_Final)
+#define SHA512_256_Init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA512_256_Init)
+#define SHA512_256_Update BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA512_256_Update)
 #define SHA512_Final BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA512_Final)
 #define SHA512_Init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA512_Init)
 #define SHA512_Transform BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA512_Transform)
 #define SXNET_get_id_ulong BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SXNET_get_id_ulong)
 #define SXNET_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SXNET_it)
 #define SXNET_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SXNET_new)
+#define TRUST_TOKEN_CLIENT_add_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_CLIENT_add_key)
+#define TRUST_TOKEN_CLIENT_begin_issuance BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_CLIENT_begin_issuance)
+#define TRUST_TOKEN_CLIENT_begin_redemption BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_CLIENT_begin_redemption)
+#define TRUST_TOKEN_CLIENT_finish_issuance BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_CLIENT_finish_issuance)
+#define TRUST_TOKEN_CLIENT_finish_redemption BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_CLIENT_finish_redemption)
+#define TRUST_TOKEN_CLIENT_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_CLIENT_free)
+#define TRUST_TOKEN_CLIENT_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_CLIENT_new)
+#define TRUST_TOKEN_CLIENT_set_srr_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_CLIENT_set_srr_key)
+#define TRUST_TOKEN_ISSUER_add_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_ISSUER_add_key)
+#define TRUST_TOKEN_ISSUER_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_ISSUER_free)
+#define TRUST_TOKEN_ISSUER_issue BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_ISSUER_issue)
+#define TRUST_TOKEN_ISSUER_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_ISSUER_new)
+#define TRUST_TOKEN_ISSUER_redeem BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_ISSUER_redeem)
+#define TRUST_TOKEN_ISSUER_set_metadata_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_ISSUER_set_metadata_key)
+#define TRUST_TOKEN_ISSUER_set_srr_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_ISSUER_set_srr_key)
+#define TRUST_TOKEN_decode_private_metadata BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_decode_private_metadata)
+#define TRUST_TOKEN_experiment_v0 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_experiment_v0)
+#define TRUST_TOKEN_experiment_v1 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_experiment_v1)
+#define TRUST_TOKEN_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_free)
+#define TRUST_TOKEN_generate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_generate_key)
+#define TRUST_TOKEN_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, TRUST_TOKEN_new)
 #define USERNOTICE_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, USERNOTICE_free)
 #define USERNOTICE_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, USERNOTICE_it)
 #define USERNOTICE_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, USERNOTICE_new)
 #define X509_STORE_CTX_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_STORE_CTX_cleanup)
 #define X509_STORE_CTX_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_STORE_CTX_free)
 #define X509_STORE_CTX_get0_cert BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_STORE_CTX_get0_cert)
+#define X509_STORE_CTX_get0_chain BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_STORE_CTX_get0_chain)
 #define X509_STORE_CTX_get0_current_crl BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_STORE_CTX_get0_current_crl)
 #define X509_STORE_CTX_get0_current_issuer BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_STORE_CTX_get0_current_issuer)
 #define X509_STORE_CTX_get0_param BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_STORE_CTX_get0_param)
 #define X509_get_serialNumber BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_get_serialNumber)
 #define X509_get_signature_nid BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_get_signature_nid)
 #define X509_get_subject_name BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_get_subject_name)
+#define X509_getm_notAfter BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_getm_notAfter)
+#define X509_getm_notBefore BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_getm_notBefore)
 #define X509_gmtime_adj BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_gmtime_adj)
 #define X509_issuer_and_serial_cmp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_issuer_and_serial_cmp)
 #define X509_issuer_and_serial_hash BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_issuer_and_serial_hash)
 #define bn_mod_add_words BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mod_add_words)
 #define bn_mod_exp_base_2_consttime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mod_exp_base_2_consttime)
 #define bn_mod_exp_mont_small BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mod_exp_mont_small)
+#define bn_mod_inverse0_prime_mont_small BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mod_inverse0_prime_mont_small)
 #define bn_mod_inverse_consttime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mod_inverse_consttime)
 #define bn_mod_inverse_prime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mod_inverse_prime)
-#define bn_mod_inverse_prime_mont_small BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mod_inverse_prime_mont_small)
 #define bn_mod_inverse_secret_prime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mod_inverse_secret_prime)
 #define bn_mod_lshift1_consttime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mod_lshift1_consttime)
 #define bn_mod_lshift_consttime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mod_lshift_consttime)
 #define d2i_X509_fp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_fp)
 #define dsa_asn1_meth BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, dsa_asn1_meth)
 #define ec_GFp_mont_add BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_add)
-#define ec_GFp_mont_bignum_to_felem BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_bignum_to_felem)
 #define ec_GFp_mont_dbl BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_dbl)
+#define ec_GFp_mont_felem_from_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_felem_from_bytes)
 #define ec_GFp_mont_felem_mul BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_felem_mul)
 #define ec_GFp_mont_felem_sqr BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_felem_sqr)
-#define ec_GFp_mont_felem_to_bignum BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_felem_to_bignum)
+#define ec_GFp_mont_felem_to_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_felem_to_bytes)
 #define ec_GFp_mont_group_finish BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_group_finish)
 #define ec_GFp_mont_group_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_group_init)
 #define ec_GFp_mont_group_set_curve BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_group_set_curve)
+#define ec_GFp_mont_init_precomp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_init_precomp)
 #define ec_GFp_mont_mul BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_mul)
 #define ec_GFp_mont_mul_base BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_mul_base)
-#define ec_GFp_mont_mul_public BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_mul_public)
+#define ec_GFp_mont_mul_batch BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_mul_batch)
+#define ec_GFp_mont_mul_precomp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_mul_precomp)
+#define ec_GFp_mont_mul_public_batch BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_mont_mul_public_batch)
 #define ec_GFp_nistp_recode_scalar_bits BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_nistp_recode_scalar_bits)
-#define ec_GFp_simple_cmp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_cmp)
 #define ec_GFp_simple_cmp_x_coordinate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_cmp_x_coordinate)
+#define ec_GFp_simple_felem_from_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_felem_from_bytes)
+#define ec_GFp_simple_felem_to_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_felem_to_bytes)
 #define ec_GFp_simple_group_finish BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_group_finish)
 #define ec_GFp_simple_group_get_curve BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_group_get_curve)
 #define ec_GFp_simple_group_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_group_init)
 #define ec_GFp_simple_invert BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_invert)
 #define ec_GFp_simple_is_at_infinity BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_is_at_infinity)
 #define ec_GFp_simple_is_on_curve BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_is_on_curve)
-#define ec_GFp_simple_mont_inv_mod_ord_vartime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_mont_inv_mod_ord_vartime)
 #define ec_GFp_simple_point_copy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_point_copy)
 #define ec_GFp_simple_point_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_point_init)
-#define ec_GFp_simple_point_set_affine_coordinates BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_point_set_affine_coordinates)
 #define ec_GFp_simple_point_set_to_infinity BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_point_set_to_infinity)
+#define ec_GFp_simple_points_equal BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_GFp_simple_points_equal)
+#define ec_affine_jacobian_equal BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_affine_jacobian_equal)
+#define ec_affine_select BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_affine_select)
+#define ec_affine_to_jacobian BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_affine_to_jacobian)
 #define ec_asn1_meth BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_asn1_meth)
 #define ec_bignum_to_felem BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_bignum_to_felem)
 #define ec_bignum_to_scalar BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_bignum_to_scalar)
 #define ec_compute_wNAF BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_compute_wNAF)
 #define ec_felem_add BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_felem_add)
 #define ec_felem_equal BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_felem_equal)
+#define ec_felem_from_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_felem_from_bytes)
 #define ec_felem_neg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_felem_neg)
 #define ec_felem_non_zero_mask BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_felem_non_zero_mask)
 #define ec_felem_select BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_felem_select)
 #define ec_felem_sub BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_felem_sub)
 #define ec_felem_to_bignum BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_felem_to_bignum)
+#define ec_felem_to_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_felem_to_bytes)
+#define ec_get_x_coordinate_as_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_get_x_coordinate_as_bytes)
 #define ec_get_x_coordinate_as_scalar BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_get_x_coordinate_as_scalar)
 #define ec_group_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_group_new)
+#define ec_hash_to_curve_p384_xmd_sha512_sswu_draft07 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_hash_to_curve_p384_xmd_sha512_sswu_draft07)
+#define ec_hash_to_curve_p521_xmd_sha512_sswu_draft06 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_hash_to_curve_p521_xmd_sha512_sswu_draft06)
+#define ec_hash_to_scalar_p384_xmd_sha512_draft07 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_hash_to_scalar_p384_xmd_sha512_draft07)
+#define ec_hash_to_scalar_p521_xmd_sha512_draft06 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_hash_to_scalar_p521_xmd_sha512_draft06)
+#define ec_init_precomp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_init_precomp)
+#define ec_jacobian_to_affine BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_jacobian_to_affine)
+#define ec_jacobian_to_affine_batch BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_jacobian_to_affine_batch)
 #define ec_pkey_meth BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_pkey_meth)
-#define ec_point_get_affine_coordinate_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_point_get_affine_coordinate_bytes)
+#define ec_point_from_uncompressed BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_point_from_uncompressed)
 #define ec_point_mul_scalar BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_point_mul_scalar)
 #define ec_point_mul_scalar_base BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_point_mul_scalar_base)
+#define ec_point_mul_scalar_batch BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_point_mul_scalar_batch)
+#define ec_point_mul_scalar_precomp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_point_mul_scalar_precomp)
 #define ec_point_mul_scalar_public BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_point_mul_scalar_public)
+#define ec_point_mul_scalar_public_batch BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_point_mul_scalar_public_batch)
+#define ec_point_select BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_point_select)
+#define ec_point_set_affine_coordinates BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_point_set_affine_coordinates)
+#define ec_point_to_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_point_to_bytes)
+#define ec_precomp_select BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_precomp_select)
 #define ec_random_nonzero_scalar BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_random_nonzero_scalar)
 #define ec_scalar_add BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_add)
 #define ec_scalar_equal_vartime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_equal_vartime)
+#define ec_scalar_from_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_from_bytes)
 #define ec_scalar_from_montgomery BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_from_montgomery)
-#define ec_scalar_inv_montgomery BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_inv_montgomery)
-#define ec_scalar_inv_montgomery_vartime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_inv_montgomery_vartime)
+#define ec_scalar_inv0_montgomery BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_inv0_montgomery)
 #define ec_scalar_is_zero BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_is_zero)
 #define ec_scalar_mul_montgomery BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_mul_montgomery)
+#define ec_scalar_neg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_neg)
+#define ec_scalar_reduce BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_reduce)
+#define ec_scalar_select BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_select)
+#define ec_scalar_sub BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_sub)
+#define ec_scalar_to_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_to_bytes)
 #define ec_scalar_to_montgomery BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_to_montgomery)
-#define ec_simple_scalar_inv_montgomery BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_simple_scalar_inv_montgomery)
+#define ec_scalar_to_montgomery_inv_vartime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_scalar_to_montgomery_inv_vartime)
+#define ec_set_to_safe_point BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_set_to_safe_point)
+#define ec_simple_scalar_inv0_montgomery BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_simple_scalar_inv0_montgomery)
+#define ec_simple_scalar_to_montgomery_inv_vartime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_simple_scalar_to_montgomery_inv_vartime)
 #define ecp_nistz256_avx2_select_w7 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ecp_nistz256_avx2_select_w7)
 #define ecp_nistz256_mul_mont BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ecp_nistz256_mul_mont)
 #define ecp_nistz256_neg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ecp_nistz256_neg)
 #define pkcs7_bundle BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pkcs7_bundle)
 #define pkcs7_parse_header BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pkcs7_parse_header)
 #define pkcs8_pbe_decrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pkcs8_pbe_decrypt)
+#define pmbtoken_exp0_blind BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp0_blind)
+#define pmbtoken_exp0_client_key_from_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp0_client_key_from_bytes)
+#define pmbtoken_exp0_generate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp0_generate_key)
+#define pmbtoken_exp0_issuer_key_from_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp0_issuer_key_from_bytes)
+#define pmbtoken_exp0_read BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp0_read)
+#define pmbtoken_exp0_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp0_sign)
+#define pmbtoken_exp0_unblind BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp0_unblind)
+#define pmbtoken_exp1_blind BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp1_blind)
+#define pmbtoken_exp1_client_key_from_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp1_client_key_from_bytes)
+#define pmbtoken_exp1_generate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp1_generate_key)
+#define pmbtoken_exp1_get_h_for_testing BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp1_get_h_for_testing)
+#define pmbtoken_exp1_issuer_key_from_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp1_issuer_key_from_bytes)
+#define pmbtoken_exp1_read BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp1_read)
+#define pmbtoken_exp1_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp1_sign)
+#define pmbtoken_exp1_unblind BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, pmbtoken_exp1_unblind)
 #define policy_cache_find_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, policy_cache_find_data)
 #define policy_cache_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, policy_cache_free)
 #define policy_cache_set BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, policy_cache_set)
index 1cdf0b3..bd8d056 100644 (file)
@@ -34,10 +34,14 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
   CppGrpcGenerator() {}
   virtual ~CppGrpcGenerator() {}
 
+  uint64_t GetSupportedFeatures() const override {
+    return FEATURE_PROTO3_OPTIONAL;
+  }
+
   virtual bool Generate(const grpc::protobuf::FileDescriptor* file,
                         const grpc::string& parameter,
                         grpc::protobuf::compiler::GeneratorContext* context,
-                        grpc::string* error) const {
+                        grpc::string* error) const override {
     if (file->options().cc_generic_services()) {
       *error =
           "cpp grpc proto compiler plugin does not work with generic "
index 5f13aa6..d4648b4 100644 (file)
@@ -29,10 +29,14 @@ class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
   CSharpGrpcGenerator() {}
   ~CSharpGrpcGenerator() {}
 
+  uint64_t GetSupportedFeatures() const override {
+    return FEATURE_PROTO3_OPTIONAL;
+  }
+
   bool Generate(const grpc::protobuf::FileDescriptor* file,
                 const grpc::string& parameter,
                 grpc::protobuf::compiler::GeneratorContext* context,
-                grpc::string* error) const {
+                grpc::string* error) const override {
     std::vector<std::pair<grpc::string, grpc::string> > options;
     grpc::protobuf::compiler::ParseGeneratorParameter(parameter, &options);
 
index 0d19d8e..7b89a71 100644 (file)
@@ -32,10 +32,14 @@ class NodeGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
   NodeGrpcGenerator() {}
   ~NodeGrpcGenerator() {}
 
+  uint64_t GetSupportedFeatures() const override {
+    return FEATURE_PROTO3_OPTIONAL;
+  }
+
   bool Generate(const grpc::protobuf::FileDescriptor* file,
                 const grpc::string& parameter,
                 grpc::protobuf::compiler::GeneratorContext* context,
-                grpc::string* error) const {
+                grpc::string* error) const override {
     grpc_node_generator::Parameters generator_parameters;
     generator_parameters.minimum_node_version = 4;
 
index a08064a..2738a73 100644 (file)
@@ -71,10 +71,14 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
   virtual ~ObjectiveCGrpcGenerator() {}
 
  public:
+  uint64_t GetSupportedFeatures() const override {
+    return FEATURE_PROTO3_OPTIONAL;
+  }
+
   virtual bool Generate(const grpc::protobuf::FileDescriptor* file,
                         const ::grpc::string& parameter,
                         grpc::protobuf::compiler::GeneratorContext* context,
-                        ::grpc::string* error) const {
+                        ::grpc::string* error) const override {
     if (file->service_count() == 0) {
       // No services.  Do nothing.
       return true;
@@ -127,6 +131,12 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
       }
     }
 
+    // Write out a file header.
+    ::grpc::string file_header =
+        "// Code generated by gRPC proto compiler.  DO NOT EDIT!\n"
+        "// source: " +
+        file->name() + "\n\n";
+
     {
       // Generate .pbrpc.h
 
@@ -187,7 +197,7 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
       }
 
       Write(context, file_name + ".pbrpc.h",
-            PreprocIfNot(kForwardDeclare, imports) + "\n" +
+            file_header + PreprocIfNot(kForwardDeclare, imports) + "\n" +
                 PreprocIfNot(kProtocolOnly, system_imports) + "\n" +
                 class_declarations + "\n" +
                 PreprocIfNot(kForwardDeclare, class_imports) + "\n" +
@@ -228,8 +238,9 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
       }
 
       Write(context, file_name + ".pbrpc.m",
-            PreprocIfNot(kProtocolOnly,
-                         imports + "\n" + class_imports + "\n" + definitions));
+            file_header +
+                PreprocIfNot(kProtocolOnly, imports + "\n" + class_imports +
+                                                "\n" + definitions));
     }
 
     return true;
index ca084cc..ddeb2bc 100644 (file)
@@ -80,7 +80,8 @@ void PrintMethod(const MethodDescriptor* method, Printer* out) {
   if (method->client_streaming()) {
     out->Print(vars,
                " * @param array $$metadata metadata\n"
-               " * @param array $$options call options\n */\n"
+               " * @param array $$options call options\n"
+               " * @return \\$output_type_id$\n */\n"
                "public function $name$($$metadata = [], "
                "$$options = []) {\n");
     out->Indent();
@@ -98,7 +99,8 @@ void PrintMethod(const MethodDescriptor* method, Printer* out) {
     out->Print(vars,
                " * @param \\$input_type_id$ $$argument input argument\n"
                " * @param array $$metadata metadata\n"
-               " * @param array $$options call options\n */\n"
+               " * @param array $$options call options\n"
+               " * @return \\$output_type_id$\n */\n"
                "public function $name$(\\$input_type_id$ $$argument,\n"
                "  $$metadata = [], $$options = []) {\n");
     out->Indent();
index d01cbf8..d16cd08 100644 (file)
@@ -33,10 +33,14 @@ class PHPGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
   PHPGrpcGenerator() {}
   ~PHPGrpcGenerator() {}
 
+  uint64_t GetSupportedFeatures() const override {
+    return FEATURE_PROTO3_OPTIONAL;
+  }
+
   bool Generate(const grpc::protobuf::FileDescriptor* file,
                 const grpc::string& parameter,
                 grpc::protobuf::compiler::GeneratorContext* context,
-                grpc::string* error) const {
+                grpc::string* error) const override {
     if (file->service_count() == 0) {
       return true;
     }
index 2312c04..ef553de 100644 (file)
@@ -100,7 +100,7 @@ void PrivateGenerator::PrintAllComments(StringVector comments,
     // of the generated code.
     out->Print(
         "\"\"\"Missing associated documentation comment in .proto "
-        "file\"\"\"\n");
+        "file.\"\"\"\n");
     return;
   }
   out->Print("\"\"\"");
@@ -777,7 +777,9 @@ pair<bool, grpc::string> PrivateGenerator::GetGrpcServices() {
     if (generate_in_pb2_grpc) {
       out->Print(
           "# Generated by the gRPC Python protocol compiler plugin. "
-          "DO NOT EDIT!\n");
+          "DO NOT EDIT!\n\"\"\""
+          "Client and server classes corresponding to protobuf-defined "
+          "services.\"\"\"\n");
       if (!PrintPreamble(out.get())) {
         return make_pair(false, "");
       }
@@ -875,6 +877,10 @@ static bool ParseParameters(const grpc::string& parameter,
   return true;
 }
 
+uint64_t PythonGrpcGenerator::GetSupportedFeatures() const {
+  return FEATURE_PROTO3_OPTIONAL;
+}
+
 bool PythonGrpcGenerator::Generate(const FileDescriptor* file,
                                    const grpc::string& parameter,
                                    GeneratorContext* context,
index 6077ac4..c816e3f 100644 (file)
@@ -44,10 +44,12 @@ class PythonGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
   PythonGrpcGenerator(const GeneratorConfiguration& config);
   ~PythonGrpcGenerator();
 
+  uint64_t GetSupportedFeatures() const override;
+
   bool Generate(const grpc::protobuf::FileDescriptor* file,
                 const grpc::string& parameter,
                 grpc::protobuf::compiler::GeneratorContext* context,
-                grpc::string* error) const;
+                grpc::string* error) const override;
 
  private:
   GeneratorConfiguration config_;
index 005e9f0..36f659d 100644 (file)
@@ -119,12 +119,13 @@ inline grpc::string RubyPackage(const grpc::protobuf::FileDescriptor* file) {
 inline grpc::string RubyTypeOf(const grpc::protobuf::Descriptor* descriptor,
                                const grpc::string& package) {
   std::string proto_type = descriptor->full_name();
+  ReplacePrefix(&proto_type, package,
+                "");                    // remove the leading package if present
+  ReplacePrefix(&proto_type, ".", "");  // remove the leading . (no package)
   if (descriptor->file()->options().has_ruby_package()) {
-    proto_type = RubyPackage(descriptor->file()) + "." + descriptor->name();
+    proto_type = RubyPackage(descriptor->file()) + "." + proto_type;
   }
   grpc::string res(proto_type);
-  ReplacePrefix(&res, package, "");  // remove the leading package if present
-  ReplacePrefix(&res, ".", "");      // remove the leading . (no package)
   if (res.find('.') == grpc::string::npos) {
     return res;
   } else {
index a1d2e81..1b5f7ae 100644 (file)
@@ -29,10 +29,14 @@ class RubyGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
   RubyGrpcGenerator() {}
   ~RubyGrpcGenerator() {}
 
+  uint64_t GetSupportedFeatures() const override {
+    return FEATURE_PROTO3_OPTIONAL;
+  }
+
   bool Generate(const grpc::protobuf::FileDescriptor* file,
                 const grpc::string& /*parameter*/,
                 grpc::protobuf::compiler::GeneratorContext* context,
-                grpc::string* /*error*/) const {
+                grpc::string* /*error*/) const override {
     grpc::string code = grpc_ruby_generator::GetServices(file);
     if (code.size() == 0) {
       return true;  // don't generate a file if there are no services
index b36614f..4c60248 100644 (file)
 
 #include "src/core/ext/filters/client_channel/backend_metric.h"
 
-#include "src/core/lib/gprpp/string_view.h"
+#include "absl/strings/string_view.h"
+
 #include "udpa/data/orca/v1/orca_load_report.upb.h"
 
+#include "src/core/lib/gprpp/map.h"
+
 namespace grpc_core {
 
 namespace {
 
 template <typename EntryType>
-std::map<StringView, double, StringLess> ParseMap(
+std::map<absl::string_view, double, StringLess> ParseMap(
     udpa_data_orca_v1_OrcaLoadReport* msg,
     EntryType** (*entry_func)(udpa_data_orca_v1_OrcaLoadReport*, size_t*),
     upb_strview (*key_func)(const EntryType*),
     double (*value_func)(const EntryType*), Arena* arena) {
-  std::map<StringView, double, StringLess> result;
+  std::map<absl::string_view, double, StringLess> result;
   size_t size;
   const auto* const* entries = entry_func(msg, &size);
   for (size_t i = 0; i < size; ++i) {
     upb_strview key_view = key_func(entries[i]);
     char* key = static_cast<char*>(arena->Alloc(key_view.size + 1));
     memcpy(key, key_view.data, key_view.size);
-    result[StringView(key, key_view.size)] = value_func(entries[i]);
+    result[absl::string_view(key, key_view.size)] = value_func(entries[i]);
   }
   return result;
 }
index 5934501..d8af25d 100644 (file)
 
 #include <set>
 
+#include "absl/strings/string_view.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 
+#include "absl/container/inlined_vector.h"
+#include "absl/types/optional.h"
+
 #include "src/core/ext/filters/client_channel/backend_metric.h"
 #include "src/core/ext/filters/client_channel/backup_poller.h"
 #include "src/core/ext/filters/client_channel/global_subchannel_pool.h"
@@ -45,6 +50,7 @@
 #include "src/core/ext/filters/client_channel/resolving_lb_policy.h"
 #include "src/core/ext/filters/client_channel/retry_throttle.h"
 #include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/filters/client_channel/service_config_call_data.h"
 #include "src/core/ext/filters/client_channel/subchannel.h"
 #include "src/core/ext/filters/deadline/deadline_filter.h"
 #include "src/core/lib/backoff/backoff.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/status_util.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/manual_constructor.h"
 #include "src/core/lib/gprpp/map.h"
 #include "src/core/lib/gprpp/sync.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/polling_entity.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
@@ -126,6 +131,7 @@ class ChannelData {
   size_t per_rpc_retry_buffer_size() const {
     return per_rpc_retry_buffer_size_;
   }
+  grpc_channel_stack* owning_stack() const { return owning_stack_; }
 
   // Note: Does NOT return a new ref.
   grpc_error* disconnect_error() const {
@@ -149,6 +155,7 @@ class ChannelData {
   RefCountedPtr<ServiceConfig> service_config() const {
     return service_config_;
   }
+  WorkSerializer* work_serializer() const { return work_serializer_.get(); }
 
   RefCountedPtr<ConnectedSubchannel> GetConnectedSubchannelInDataPlane(
       SubchannelInterface* subchannel) const;
@@ -159,11 +166,15 @@ class ChannelData {
                                       grpc_connectivity_state* state,
                                       grpc_closure* on_complete,
                                       grpc_closure* watcher_timer_init) {
-    MutexLock lock(&external_watchers_mu_);
-    // Will be deleted when the watch is complete.
-    GPR_ASSERT(external_watchers_[on_complete] == nullptr);
-    external_watchers_[on_complete] = new ExternalConnectivityWatcher(
+    auto* watcher = new ExternalConnectivityWatcher(
         this, pollent, state, on_complete, watcher_timer_init);
+    {
+      MutexLock lock(&external_watchers_mu_);
+      // Will be deleted when the watch is complete.
+      GPR_ASSERT(external_watchers_[on_complete] == nullptr);
+      external_watchers_[on_complete] = watcher;
+    }
+    watcher->Start();
   }
 
   void RemoveExternalConnectivityWatcher(grpc_closure* on_complete,
@@ -204,13 +215,15 @@ class ChannelData {
 
     ~ExternalConnectivityWatcher();
 
+    void Start();
+
     void Notify(grpc_connectivity_state state) override;
 
     void Cancel();
 
    private:
-    static void AddWatcherLocked(void* arg, grpc_error* ignored);
-    static void RemoveWatcherLocked(void* arg, grpc_error* ignored);
+    void AddWatcherLocked();
+    void RemoveWatcherLocked();
 
     ChannelData* chand_;
     grpc_polling_entity pollent_;
@@ -218,8 +231,6 @@ class ChannelData {
     grpc_connectivity_state* state_;
     grpc_closure* on_complete_;
     grpc_closure* watcher_timer_init_;
-    grpc_closure add_closure_;
-    grpc_closure remove_closure_;
     Atomic<bool> done_{false};
   };
 
@@ -245,9 +256,9 @@ class ChannelData {
 
   grpc_error* DoPingLocked(grpc_transport_op* op);
 
-  static void StartTransportOpLocked(void* arg, grpc_error* ignored);
+  void StartTransportOpLocked(grpc_transport_op* op);
 
-  static void TryToConnectLocked(void* arg, grpc_error* error_ignored);
+  void TryToConnectLocked();
 
   void ProcessLbPolicy(
       const Resolver::Result& resolver_result,
@@ -280,9 +291,9 @@ class ChannelData {
   RefCountedPtr<ServiceConfig> service_config_;
 
   //
-  // Fields used in the control plane.  Guarded by combiner.
+  // Fields used in the control plane.  Guarded by work_serializer.
   //
-  Combiner* combiner_;
+  std::shared_ptr<WorkSerializer> work_serializer_;
   grpc_pollset_set* interested_parties_;
   RefCountedPtr<SubchannelPoolInterface> subchannel_pool_;
   OrphanablePtr<ResolvingLoadBalancingPolicy> resolving_lb_policy_;
@@ -294,17 +305,17 @@ class ChannelData {
   std::map<Subchannel*, int> subchannel_refcount_map_;
   // The set of SubchannelWrappers that currently exist.
   // No need to hold a ref, since the map is updated in the control-plane
-  // combiner when the SubchannelWrappers are created and destroyed.
+  // work_serializer when the SubchannelWrappers are created and destroyed.
   std::set<SubchannelWrapper*> subchannel_wrappers_;
   // Pending ConnectedSubchannel updates for each SubchannelWrapper.
-  // Updates are queued here in the control plane combiner and then applied
-  // in the data plane mutex when the picker is updated.
-  std::map<RefCountedPtr<SubchannelWrapper>, RefCountedPtr<ConnectedSubchannel>,
-           RefCountedPtrLess<SubchannelWrapper>>
+  // Updates are queued here in the control plane work_serializer and then
+  // applied in the data plane mutex when the picker is updated.
+  std::map<RefCountedPtr<SubchannelWrapper>, RefCountedPtr<ConnectedSubchannel>>
       pending_subchannel_updates_;
 
   //
-  // Fields accessed from both data plane mutex and control plane combiner.
+  // Fields accessed from both data plane mutex and control plane
+  // work_serializer.
   //
   Atomic<grpc_error*> disconnect_error_;
 
@@ -364,7 +375,7 @@ class CallData {
     Metadata(CallData* calld, grpc_metadata_batch* batch)
         : calld_(calld), batch_(batch) {}
 
-    void Add(StringView key, StringView value) override {
+    void Add(absl::string_view key, absl::string_view value) override {
       grpc_linked_mdelem* linked_mdelem = static_cast<grpc_linked_mdelem*>(
           calld_->arena_->Alloc(sizeof(grpc_linked_mdelem)));
       linked_mdelem->md = grpc_mdelem_from_slices(
@@ -399,7 +410,7 @@ class CallData {
           reinterpret_cast<grpc_linked_mdelem*>(handle);
       return reinterpret_cast<intptr_t>(linked_mdelem->next);
     }
-    std::pair<StringView, StringView> IteratorHandleGet(
+    std::pair<absl::string_view, absl::string_view> IteratorHandleGet(
         intptr_t handle) const override {
       grpc_linked_mdelem* linked_mdelem =
           reinterpret_cast<grpc_linked_mdelem*>(handle);
@@ -431,6 +442,12 @@ class CallData {
       return calld_->backend_metric_data_;
     }
 
+    absl::string_view ExperimentalGetCallAttribute(const char* key) override {
+      auto it = calld_->call_attributes_.find(key);
+      if (it == calld_->call_attributes_.end()) return absl::string_view();
+      return it->second;
+    }
+
    private:
     CallData* calld_;
   };
@@ -750,8 +767,8 @@ class CallData {
   grpc_call_context_element* call_context_;
 
   RefCountedPtr<ServerRetryThrottleData> retry_throttle_data_;
-  ServiceConfig::CallData service_config_call_data_;
   const ClientChannelMethodParsedConfig* method_params_ = nullptr;
+  std::map<const char*, absl::string_view> call_attributes_;
 
   RefCountedPtr<SubchannelCall> subchannel_call_;
 
@@ -820,7 +837,7 @@ class CallData {
   // Note: We inline the cache for the first 3 send_message ops and use
   // dynamic allocation after that.  This number was essentially picked
   // at random; it could be changed in the future to tune performance.
-  InlinedVector<ByteStreamCache*, 3> send_messages_;
+  absl::InlinedVector<ByteStreamCache*, 3> send_messages_;
   // send_trailing_metadata
   bool seen_send_trailing_metadata_ = false;
   grpc_linked_mdelem* send_trailing_metadata_storage_ = nullptr;
@@ -838,7 +855,7 @@ class CallData {
 // Note that no synchronization is needed here, because even if the
 // underlying subchannel is shared between channels, this wrapper will only
 // be used within one channel, so it will always be synchronized by the
-// control plane combiner.
+// control plane work_serializer.
 class ChannelData::SubchannelWrapper : public SubchannelInterface {
  public:
   SubchannelWrapper(ChannelData* chand, Subchannel* subchannel,
@@ -907,7 +924,7 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
         initial_state,
         grpc_core::UniquePtr<char>(
             gpr_strdup(health_check_service_name_.get())),
-        OrphanablePtr<Subchannel::ConnectivityStateWatcherInterface>(
+        RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface>(
             watcher_wrapper));
   }
 
@@ -957,14 +974,14 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
           replacement->last_seen_state(),
           grpc_core::UniquePtr<char>(
               gpr_strdup(health_check_service_name.get())),
-          OrphanablePtr<Subchannel::ConnectivityStateWatcherInterface>(
+          RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface>(
               replacement));
     }
     // Save the new health check service name.
     health_check_service_name_ = std::move(health_check_service_name);
   }
 
-  // Caller must be holding the control-plane combiner.
+  // Caller must be holding the control-plane work_serializer.
   ConnectedSubchannel* connected_subchannel() const {
     return connected_subchannel_.get();
   }
@@ -1004,23 +1021,27 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
           parent_(std::move(parent)),
           last_seen_state_(initial_state) {}
 
-    ~WatcherWrapper() { parent_.reset(DEBUG_LOCATION, "WatcherWrapper"); }
-
-    void Orphan() override { Unref(); }
+    ~WatcherWrapper() {
+      auto* parent = parent_.release();  // ref owned by lambda
+      parent->chand_->work_serializer_->Run(
+          [parent]() { parent->Unref(DEBUG_LOCATION, "WatcherWrapper"); },
+          DEBUG_LOCATION);
+    }
 
-    void OnConnectivityStateChange(
-        grpc_connectivity_state new_state,
-        RefCountedPtr<ConnectedSubchannel> connected_subchannel) override {
+    void OnConnectivityStateChange() override {
       if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
         gpr_log(GPR_INFO,
                 "chand=%p: connectivity change for subchannel wrapper %p "
-                "subchannel %p (connected_subchannel=%p state=%s); "
-                "hopping into combiner",
-                parent_->chand_, parent_.get(), parent_->subchannel_,
-                connected_subchannel.get(), ConnectivityStateName(new_state));
+                "subchannel %p; hopping into work_serializer",
+                parent_->chand_, parent_.get(), parent_->subchannel_);
       }
-      // Will delete itself.
-      new Updater(Ref(), new_state, std::move(connected_subchannel));
+      Ref().release();  // ref owned by lambda
+      parent_->chand_->work_serializer_->Run(
+          [this]() {
+            ApplyUpdateInControlPlaneWorkSerializer();
+            Unref();
+          },
+          DEBUG_LOCATION);
     }
 
     grpc_pollset_set* interested_parties() override {
@@ -1040,50 +1061,25 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
     grpc_connectivity_state last_seen_state() const { return last_seen_state_; }
 
    private:
-    class Updater {
-     public:
-      Updater(RefCountedPtr<WatcherWrapper> parent,
-              grpc_connectivity_state new_state,
-              RefCountedPtr<ConnectedSubchannel> connected_subchannel)
-          : parent_(std::move(parent)),
-            state_(new_state),
-            connected_subchannel_(std::move(connected_subchannel)) {
-        parent_->parent_->chand_->combiner_->Run(
-            GRPC_CLOSURE_INIT(&closure_, ApplyUpdateInControlPlaneCombiner,
-                              this, nullptr),
-            GRPC_ERROR_NONE);
+    void ApplyUpdateInControlPlaneWorkSerializer() {
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
+        gpr_log(GPR_INFO,
+                "chand=%p: processing connectivity change in work serializer "
+                "for subchannel wrapper %p subchannel %p "
+                "watcher=%p",
+                parent_->chand_, parent_.get(), parent_->subchannel_,
+                watcher_.get());
       }
-
-     private:
-      static void ApplyUpdateInControlPlaneCombiner(void* arg,
-                                                    grpc_error* /*error*/) {
-        Updater* self = static_cast<Updater*>(arg);
-        if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
-          gpr_log(GPR_INFO,
-                  "chand=%p: processing connectivity change in combiner "
-                  "for subchannel wrapper %p subchannel %p "
-                  "(connected_subchannel=%p state=%s): watcher=%p",
-                  self->parent_->parent_->chand_, self->parent_->parent_.get(),
-                  self->parent_->parent_->subchannel_,
-                  self->connected_subchannel_.get(),
-                  ConnectivityStateName(self->state_),
-                  self->parent_->watcher_.get());
-        }
-        // Ignore update if the parent WatcherWrapper has been replaced
-        // since this callback was scheduled.
-        if (self->parent_->watcher_ == nullptr) return;
-        self->parent_->last_seen_state_ = self->state_;
-        self->parent_->parent_->MaybeUpdateConnectedSubchannel(
-            std::move(self->connected_subchannel_));
-        self->parent_->watcher_->OnConnectivityStateChange(self->state_);
-        delete self;
+      ConnectivityStateChange state_change = PopConnectivityStateChange();
+      // Ignore update if the parent WatcherWrapper has been replaced
+      // since this callback was scheduled.
+      if (watcher_ != nullptr) {
+        last_seen_state_ = state_change.state;
+        parent_->MaybeUpdateConnectedSubchannel(
+            std::move(state_change.connected_subchannel));
+        watcher_->OnConnectivityStateChange(state_change.state);
       }
-
-      RefCountedPtr<WatcherWrapper> parent_;
-      grpc_connectivity_state state_;
-      RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
-      grpc_closure closure_;
-    };
+    }
 
     std::unique_ptr<SubchannelInterface::ConnectivityStateWatcherInterface>
         watcher_;
@@ -1122,7 +1118,7 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
   // CancelConnectivityStateWatch() with its watcher, we know the
   // corresponding WrapperWatcher to cancel on the underlying subchannel.
   std::map<ConnectivityStateWatcherInterface*, WatcherWrapper*> watcher_map_;
-  // To be accessed only in the control plane combiner.
+  // To be accessed only in the control plane work_serializer.
   RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
   // To be accessed only in the data plane mutex.
   RefCountedPtr<ConnectedSubchannel> connected_subchannel_in_data_plane_;
@@ -1145,9 +1141,6 @@ ChannelData::ExternalConnectivityWatcher::ExternalConnectivityWatcher(
   grpc_polling_entity_add_to_pollset_set(&pollent_,
                                          chand_->interested_parties_);
   GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ExternalConnectivityWatcher");
-  chand_->combiner_->Run(
-      GRPC_CLOSURE_INIT(&add_closure_, AddWatcherLocked, this, nullptr),
-      GRPC_ERROR_NONE);
 }
 
 ChannelData::ExternalConnectivityWatcher::~ExternalConnectivityWatcher() {
@@ -1157,6 +1150,11 @@ ChannelData::ExternalConnectivityWatcher::~ExternalConnectivityWatcher() {
                            "ExternalConnectivityWatcher");
 }
 
+void ChannelData::ExternalConnectivityWatcher::Start() {
+  chand_->work_serializer_->Run([this]() { AddWatcherLocked(); },
+                                DEBUG_LOCATION);
+}
+
 void ChannelData::ExternalConnectivityWatcher::Notify(
     grpc_connectivity_state state) {
   bool done = false;
@@ -1169,13 +1167,12 @@ void ChannelData::ExternalConnectivityWatcher::Notify(
   // Report new state to the user.
   *state_ = state;
   ExecCtx::Run(DEBUG_LOCATION, on_complete_, GRPC_ERROR_NONE);
-  // Hop back into the combiner to clean up.
+  // Hop back into the work_serializer to clean up.
   // Not needed in state SHUTDOWN, because the tracker will
   // automatically remove all watchers in that case.
   if (state != GRPC_CHANNEL_SHUTDOWN) {
-    chand_->combiner_->Run(
-        GRPC_CLOSURE_INIT(&remove_closure_, RemoveWatcherLocked, this, nullptr),
-        GRPC_ERROR_NONE);
+    chand_->work_serializer_->Run([this]() { RemoveWatcherLocked(); },
+                                  DEBUG_LOCATION);
   }
 }
 
@@ -1186,28 +1183,20 @@ void ChannelData::ExternalConnectivityWatcher::Cancel() {
     return;  // Already done.
   }
   ExecCtx::Run(DEBUG_LOCATION, on_complete_, GRPC_ERROR_CANCELLED);
-  // Hop back into the combiner to clean up.
-  chand_->combiner_->Run(
-      GRPC_CLOSURE_INIT(&remove_closure_, RemoveWatcherLocked, this, nullptr),
-      GRPC_ERROR_NONE);
+  // Hop back into the work_serializer to clean up.
+  chand_->work_serializer_->Run([this]() { RemoveWatcherLocked(); },
+                                DEBUG_LOCATION);
 }
 
-void ChannelData::ExternalConnectivityWatcher::AddWatcherLocked(
-    void* arg, grpc_error* /*ignored*/) {
-  ExternalConnectivityWatcher* self =
-      static_cast<ExternalConnectivityWatcher*>(arg);
-  Closure::Run(DEBUG_LOCATION, self->watcher_timer_init_, GRPC_ERROR_NONE);
+void ChannelData::ExternalConnectivityWatcher::AddWatcherLocked() {
+  Closure::Run(DEBUG_LOCATION, watcher_timer_init_, GRPC_ERROR_NONE);
   // Add new watcher.
-  self->chand_->state_tracker_.AddWatcher(
-      self->initial_state_,
-      OrphanablePtr<ConnectivityStateWatcherInterface>(self));
+  chand_->state_tracker_.AddWatcher(
+      initial_state_, OrphanablePtr<ConnectivityStateWatcherInterface>(this));
 }
 
-void ChannelData::ExternalConnectivityWatcher::RemoveWatcherLocked(
-    void* arg, grpc_error* /*ignored*/) {
-  ExternalConnectivityWatcher* self =
-      static_cast<ExternalConnectivityWatcher*>(arg);
-  self->chand_->state_tracker_.RemoveWatcher(self);
+void ChannelData::ExternalConnectivityWatcher::RemoveWatcherLocked() {
+  chand_->state_tracker_.RemoveWatcher(this);
 }
 
 //
@@ -1223,28 +1212,20 @@ class ChannelData::ConnectivityWatcherAdder {
         initial_state_(initial_state),
         watcher_(std::move(watcher)) {
     GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ConnectivityWatcherAdder");
-    chand_->combiner_->Run(
-        GRPC_CLOSURE_INIT(&closure_,
-                          &ConnectivityWatcherAdder::AddWatcherLocked, this,
-                          nullptr),
-        GRPC_ERROR_NONE);
+    chand_->work_serializer_->Run([this]() { AddWatcherLocked(); },
+                                  DEBUG_LOCATION);
   }
 
  private:
-  static void AddWatcherLocked(void* arg, grpc_error* /*error*/) {
-    ConnectivityWatcherAdder* self =
-        static_cast<ConnectivityWatcherAdder*>(arg);
-    self->chand_->state_tracker_.AddWatcher(self->initial_state_,
-                                            std::move(self->watcher_));
-    GRPC_CHANNEL_STACK_UNREF(self->chand_->owning_stack_,
-                             "ConnectivityWatcherAdder");
-    delete self;
+  void AddWatcherLocked() {
+    chand_->state_tracker_.AddWatcher(initial_state_, std::move(watcher_));
+    GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "ConnectivityWatcherAdder");
+    delete this;
   }
 
   ChannelData* chand_;
   grpc_connectivity_state initial_state_;
   OrphanablePtr<AsyncConnectivityStateWatcherInterface> watcher_;
-  grpc_closure closure_;
 };
 
 //
@@ -1257,26 +1238,20 @@ class ChannelData::ConnectivityWatcherRemover {
                              AsyncConnectivityStateWatcherInterface* watcher)
       : chand_(chand), watcher_(watcher) {
     GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ConnectivityWatcherRemover");
-    chand_->combiner_->Run(
-        GRPC_CLOSURE_INIT(&closure_,
-                          &ConnectivityWatcherRemover::RemoveWatcherLocked,
-                          this, nullptr),
-        GRPC_ERROR_NONE);
+    chand_->work_serializer_->Run([this]() { RemoveWatcherLocked(); },
+                                  DEBUG_LOCATION);
   }
 
  private:
-  static void RemoveWatcherLocked(void* arg, grpc_error* /*error*/) {
-    ConnectivityWatcherRemover* self =
-        static_cast<ConnectivityWatcherRemover*>(arg);
-    self->chand_->state_tracker_.RemoveWatcher(self->watcher_);
-    GRPC_CHANNEL_STACK_UNREF(self->chand_->owning_stack_,
+  void RemoveWatcherLocked() {
+    chand_->state_tracker_.RemoveWatcher(watcher_);
+    GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_,
                              "ConnectivityWatcherRemover");
-    delete self;
+    delete this;
   }
 
   ChannelData* chand_;
   AsyncConnectivityStateWatcherInterface* watcher_;
-  grpc_closure closure_;
 };
 
 //
@@ -1340,7 +1315,8 @@ class ChannelData::ClientChannelControlHelper
   // No-op -- we should never get this from ResolvingLoadBalancingPolicy.
   void RequestReresolution() override {}
 
-  void AddTraceEvent(TraceSeverity severity, StringView message) override {
+  void AddTraceEvent(TraceSeverity severity,
+                     absl::string_view message) override {
     if (chand_->channelz_node_ != nullptr) {
       chand_->channelz_node_->AddTraceEvent(
           ConvertSeverityEnum(severity),
@@ -1417,7 +1393,7 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error)
       client_channel_factory_(
           ClientChannelFactory::GetFromChannelArgs(args->channel_args)),
       channelz_node_(GetChannelzNode(args->channel_args)),
-      combiner_(grpc_combiner_create()),
+      work_serializer_(std::make_shared<WorkSerializer>()),
       interested_parties_(grpc_pollset_set_create()),
       subchannel_pool_(GetSubchannelPool(args->channel_args)),
       state_tracker_("client_channel", GRPC_CHANNEL_IDLE),
@@ -1488,7 +1464,6 @@ ChannelData::~ChannelData() {
   // Stop backup polling.
   grpc_client_channel_stop_backup_polling(interested_parties_);
   grpc_pollset_set_destroy(interested_parties_);
-  GRPC_COMBINER_UNREF(combiner_, "client_channel");
   GRPC_ERROR_UNREF(disconnect_error_.Load(MemoryOrder::RELAXED));
   gpr_mu_destroy(&info_mu_);
 }
@@ -1592,7 +1567,7 @@ void ChannelData::UpdateServiceConfigLocked(
 void ChannelData::CreateResolvingLoadBalancingPolicyLocked() {
   // Instantiate resolving LB policy.
   LoadBalancingPolicy::Args lb_args;
-  lb_args.combiner = combiner_;
+  lb_args.work_serializer = work_serializer_;
   lb_args.channel_control_helper =
       absl::make_unique<ClientChannelControlHelper>(this);
   lb_args.args = channel_args_;
@@ -1762,7 +1737,7 @@ bool ChannelData::ProcessResolverResultLocked(
     chand->received_first_resolver_result_ = true;
     RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
     if (parsed_service_config != nullptr) {
-      Optional<internal::ClientChannelGlobalParsedConfig::RetryThrottling>
+      absl::optional<internal::ClientChannelGlobalParsedConfig::RetryThrottling>
           retry_throttle_config = parsed_service_config->retry_throttling();
       if (retry_throttle_config.has_value()) {
         retry_throttle_data =
@@ -1813,22 +1788,18 @@ grpc_error* ChannelData::DoPingLocked(grpc_transport_op* op) {
   return result.error;
 }
 
-void ChannelData::StartTransportOpLocked(void* arg, grpc_error* /*ignored*/) {
-  grpc_transport_op* op = static_cast<grpc_transport_op*>(arg);
-  grpc_channel_element* elem =
-      static_cast<grpc_channel_element*>(op->handler_private.extra_arg);
-  ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
+void ChannelData::StartTransportOpLocked(grpc_transport_op* op) {
   // Connectivity watch.
   if (op->start_connectivity_watch != nullptr) {
-    chand->state_tracker_.AddWatcher(op->start_connectivity_watch_state,
-                                     std::move(op->start_connectivity_watch));
+    state_tracker_.AddWatcher(op->start_connectivity_watch_state,
+                              std::move(op->start_connectivity_watch));
   }
   if (op->stop_connectivity_watch != nullptr) {
-    chand->state_tracker_.RemoveWatcher(op->stop_connectivity_watch);
+    state_tracker_.RemoveWatcher(op->stop_connectivity_watch);
   }
   // Ping.
   if (op->send_ping.on_initiate != nullptr || op->send_ping.on_ack != nullptr) {
-    grpc_error* error = chand->DoPingLocked(op);
+    grpc_error* error = DoPingLocked(op);
     if (error != GRPC_ERROR_NONE) {
       ExecCtx::Run(DEBUG_LOCATION, op->send_ping.on_initiate,
                    GRPC_ERROR_REF(error));
@@ -1840,40 +1811,39 @@ void ChannelData::StartTransportOpLocked(void* arg, grpc_error* /*ignored*/) {
   }
   // Reset backoff.
   if (op->reset_connect_backoff) {
-    if (chand->resolving_lb_policy_ != nullptr) {
-      chand->resolving_lb_policy_->ResetBackoffLocked();
+    if (resolving_lb_policy_ != nullptr) {
+      resolving_lb_policy_->ResetBackoffLocked();
     }
   }
   // Disconnect or enter IDLE.
   if (op->disconnect_with_error != GRPC_ERROR_NONE) {
     if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
-      gpr_log(GPR_INFO, "chand=%p: disconnect_with_error: %s", chand,
+      gpr_log(GPR_INFO, "chand=%p: disconnect_with_error: %s", this,
               grpc_error_string(op->disconnect_with_error));
     }
-    chand->DestroyResolvingLoadBalancingPolicyLocked();
+    DestroyResolvingLoadBalancingPolicyLocked();
     intptr_t value;
     if (grpc_error_get_int(op->disconnect_with_error,
                            GRPC_ERROR_INT_CHANNEL_CONNECTIVITY_STATE, &value) &&
         static_cast<grpc_connectivity_state>(value) == GRPC_CHANNEL_IDLE) {
-      if (chand->disconnect_error() == GRPC_ERROR_NONE) {
+      if (disconnect_error() == GRPC_ERROR_NONE) {
         // Enter IDLE state.
-        chand->UpdateStateAndPickerLocked(GRPC_CHANNEL_IDLE,
-                                          "channel entering IDLE", nullptr);
+        UpdateStateAndPickerLocked(GRPC_CHANNEL_IDLE, "channel entering IDLE",
+                                   nullptr);
       }
       GRPC_ERROR_UNREF(op->disconnect_with_error);
     } else {
       // Disconnect.
-      GPR_ASSERT(chand->disconnect_error_.Load(MemoryOrder::RELAXED) ==
+      GPR_ASSERT(disconnect_error_.Load(MemoryOrder::RELAXED) ==
                  GRPC_ERROR_NONE);
-      chand->disconnect_error_.Store(op->disconnect_with_error,
-                                     MemoryOrder::RELEASE);
-      chand->UpdateStateAndPickerLocked(
+      disconnect_error_.Store(op->disconnect_with_error, MemoryOrder::RELEASE);
+      UpdateStateAndPickerLocked(
           GRPC_CHANNEL_SHUTDOWN, "shutdown from API",
           absl::make_unique<LoadBalancingPolicy::TransientFailurePicker>(
               GRPC_ERROR_REF(op->disconnect_with_error)));
     }
   }
-  GRPC_CHANNEL_STACK_UNREF(chand->owning_stack_, "start_transport_op");
+  GRPC_CHANNEL_STACK_UNREF(owning_stack_, "start_transport_op");
   ExecCtx::Run(DEBUG_LOCATION, op->on_consumed, GRPC_ERROR_NONE);
 }
 
@@ -1885,13 +1855,10 @@ void ChannelData::StartTransportOp(grpc_channel_element* elem,
   if (op->bind_pollset != nullptr) {
     grpc_pollset_set_add_pollset(chand->interested_parties_, op->bind_pollset);
   }
-  // Pop into control plane combiner for remaining ops.
-  op->handler_private.extra_arg = elem;
+  // Pop into control plane work_serializer for remaining ops.
   GRPC_CHANNEL_STACK_REF(chand->owning_stack_, "start_transport_op");
-  chand->combiner_->Run(
-      GRPC_CLOSURE_INIT(&op->handler_private.closure,
-                        ChannelData::StartTransportOpLocked, op, nullptr),
-      GRPC_ERROR_NONE);
+  chand->work_serializer_->Run(
+      [chand, op]() { chand->StartTransportOpLocked(op); }, DEBUG_LOCATION);
 }
 
 void ChannelData::GetChannelInfo(grpc_channel_element* elem,
@@ -1942,14 +1909,13 @@ ChannelData::GetConnectedSubchannelInDataPlane(
   return connected_subchannel->Ref();
 }
 
-void ChannelData::TryToConnectLocked(void* arg, grpc_error* /*error_ignored*/) {
-  auto* chand = static_cast<ChannelData*>(arg);
-  if (chand->resolving_lb_policy_ != nullptr) {
-    chand->resolving_lb_policy_->ExitIdleLocked();
+void ChannelData::TryToConnectLocked() {
+  if (resolving_lb_policy_ != nullptr) {
+    resolving_lb_policy_->ExitIdleLocked();
   } else {
-    chand->CreateResolvingLoadBalancingPolicyLocked();
+    CreateResolvingLoadBalancingPolicyLocked();
   }
-  GRPC_CHANNEL_STACK_UNREF(chand->owning_stack_, "TryToConnect");
+  GRPC_CHANNEL_STACK_UNREF(owning_stack_, "TryToConnect");
 }
 
 grpc_connectivity_state ChannelData::CheckConnectivityState(
@@ -1957,8 +1923,7 @@ grpc_connectivity_state ChannelData::CheckConnectivityState(
   grpc_connectivity_state out = state_tracker_.state();
   if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
     GRPC_CHANNEL_STACK_REF(owning_stack_, "TryToConnect");
-    combiner_->Run(GRPC_CLOSURE_CREATE(TryToConnectLocked, this, nullptr),
-                   GRPC_ERROR_NONE);
+    work_serializer_->Run([this]() { TryToConnectLocked(); }, DEBUG_LOCATION);
   }
   return out;
 }
@@ -3206,10 +3171,9 @@ void CallData::OnComplete(void* arg, grpc_error* error) {
   ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
   CallData* calld = static_cast<CallData*>(elem->call_data);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
-    char* batch_str = grpc_transport_stream_op_batch_string(&batch_data->batch);
     gpr_log(GPR_INFO, "chand=%p calld=%p: got on_complete, error=%s, batch=%s",
-            chand, calld, grpc_error_string(error), batch_str);
-    gpr_free(batch_str);
+            chand, calld, grpc_error_string(error),
+            grpc_transport_stream_op_batch_string(&batch_data->batch).c_str());
   }
   SubchannelCallRetryState* retry_state =
       static_cast<SubchannelCallRetryState*>(
@@ -3282,10 +3246,8 @@ void CallData::AddClosureForSubchannelBatch(
   GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner,
                     batch, grpc_schedule_on_exec_ctx);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
-    char* batch_str = grpc_transport_stream_op_batch_string(batch);
     gpr_log(GPR_INFO, "chand=%p calld=%p: starting subchannel batch: %s", chand,
-            this, batch_str);
-    gpr_free(batch_str);
+            this, grpc_transport_stream_op_batch_string(batch).c_str());
   }
   closures->Add(&batch->handler_private.closure, GRPC_ERROR_NONE,
                 "start_subchannel_batch");
@@ -3798,45 +3760,52 @@ void CallData::ApplyServiceConfigToCallLocked(grpc_call_element* elem) {
     gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call",
             chand, this);
   }
-  // Store a ref to the service_config in service_config_call_data_. Also, save
-  // a pointer to this in the call_context so that all future filters can access
-  // it.
-  service_config_call_data_ =
-      ServiceConfig::CallData(chand->service_config(), path_);
-  if (service_config_call_data_.service_config() != nullptr) {
-    call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value =
-        &service_config_call_data_;
+  auto service_config = chand->service_config();
+  if (service_config != nullptr) {
+    // Create a ServiceConfigCallData for the call.  This stores a ref to the
+    // ServiceConfig and caches the right set of parsed configs to use for
+    // the call.  The MethodConfig will store itself in the call context,
+    // so that it can be accessed by filters in the subchannel, and it
+    // will be cleaned up when the call ends.
+    const auto* method_params_vector =
+        service_config->GetMethodParsedConfigVector(path_);
+    auto* service_config_call_data = arena_->New<ServiceConfigCallData>(
+        std::move(service_config), method_params_vector, call_context_);
+    // Apply our own method params to the call.
     method_params_ = static_cast<ClientChannelMethodParsedConfig*>(
-        service_config_call_data_.GetMethodParsedConfig(
+        service_config_call_data->GetMethodParsedConfig(
             internal::ClientChannelServiceConfigParser::ParserIndex()));
-  }
-  retry_throttle_data_ = chand->retry_throttle_data();
-  if (method_params_ != nullptr) {
-    // If the deadline from the service config is shorter than the one
-    // from the client API, reset the deadline timer.
-    if (chand->deadline_checking_enabled() && method_params_->timeout() != 0) {
-      const grpc_millis per_method_deadline =
-          grpc_cycle_counter_to_millis_round_up(call_start_time_) +
-          method_params_->timeout();
-      if (per_method_deadline < deadline_) {
-        deadline_ = per_method_deadline;
-        grpc_deadline_state_reset(elem, deadline_);
+    if (method_params_ != nullptr) {
+      // If the deadline from the service config is shorter than the one
+      // from the client API, reset the deadline timer.
+      if (chand->deadline_checking_enabled() &&
+          method_params_->timeout() != 0) {
+        const grpc_millis per_method_deadline =
+            grpc_cycle_counter_to_millis_round_up(call_start_time_) +
+            method_params_->timeout();
+        if (per_method_deadline < deadline_) {
+          deadline_ = per_method_deadline;
+          grpc_deadline_state_reset(elem, deadline_);
+        }
       }
-    }
-    // If the service config set wait_for_ready and the application
-    // did not explicitly set it, use the value from the service config.
-    uint32_t* send_initial_metadata_flags =
-        &pending_batches_[0]
-             .batch->payload->send_initial_metadata.send_initial_metadata_flags;
-    if (method_params_->wait_for_ready().has_value() &&
-        !(*send_initial_metadata_flags &
-          GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET)) {
-      if (method_params_->wait_for_ready().value()) {
-        *send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
-      } else {
-        *send_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
+      // If the service config set wait_for_ready and the application
+      // did not explicitly set it, use the value from the service config.
+      uint32_t* send_initial_metadata_flags =
+          &pending_batches_[0]
+               .batch->payload->send_initial_metadata
+               .send_initial_metadata_flags;
+      if (method_params_->wait_for_ready().has_value() &&
+          !(*send_initial_metadata_flags &
+            GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET)) {
+        if (method_params_->wait_for_ready().value()) {
+          *send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
+        } else {
+          *send_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
+        }
       }
     }
+    // Set retry throttle data for call.
+    retry_throttle_data_ = chand->retry_throttle_data();
   }
   // If no retry policy, disable retries.
   // TODO(roth): Remove this when adding support for transparent retries.
@@ -3892,8 +3861,25 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
   // The picker being null means that the channel is currently in IDLE state.
   // The incoming call will make the channel exit IDLE.
   if (chand->picker() == nullptr) {
-    // Bounce into the control plane combiner to exit IDLE.
-    chand->CheckConnectivityState(/*try_to_connect=*/true);
+    GRPC_CHANNEL_STACK_REF(chand->owning_stack(), "PickSubchannelLocked");
+    // Bounce into the control plane work serializer to exit IDLE. Since we are
+    // holding on to the data plane mutex here, we offload it on the ExecCtx so
+    // that we don't deadlock with ourselves.
+    ExecCtx::Run(
+        DEBUG_LOCATION,
+        GRPC_CLOSURE_CREATE(
+            [](void* arg, grpc_error* /*error*/) {
+              auto* chand = static_cast<ChannelData*>(arg);
+              chand->work_serializer()->Run(
+                  [chand]() {
+                    chand->CheckConnectivityState(/*try_to_connect=*/true);
+                    GRPC_CHANNEL_STACK_UNREF(chand->owning_stack(),
+                                             "PickSubchannelLocked");
+                  },
+                  DEBUG_LOCATION);
+            },
+            chand, nullptr),
+        GRPC_ERROR_NONE);
     // Queue the pick, so that it will be attempted once the channel
     // becomes connected.
     AddCallToQueuedPicksLocked(elem);
index 2788d4b..2358415 100644 (file)
@@ -35,6 +35,7 @@
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
 #include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
 #include "src/core/ext/filters/client_channel/retry_throttle.h"
+#include "src/core/ext/filters/client_channel/service_config_parser.h"
 #include "src/core/lib/surface/channel_init.h"
 
 static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
@@ -43,7 +44,7 @@ static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
 }
 
 void grpc_client_channel_init(void) {
-  grpc_core::ServiceConfig::Init();
+  grpc_core::ServiceConfigParser::Init();
   grpc_core::internal::ClientChannelServiceConfigParser::Register();
   grpc_core::LoadBalancingPolicyRegistry::Builder::InitRegistry();
   grpc_core::ResolverRegistry::Builder::InitRegistry();
@@ -65,5 +66,5 @@ void grpc_client_channel_shutdown(void) {
   grpc_core::internal::ServerRetryThrottleMap::Shutdown();
   grpc_core::ResolverRegistry::Builder::ShutdownRegistry();
   grpc_core::LoadBalancingPolicyRegistry::Builder::ShutdownRegistry();
-  grpc_core::ServiceConfig::Shutdown();
+  grpc_core::ServiceConfigParser::Shutdown();
 }
index 5c4aa98..a17d499 100644 (file)
@@ -125,8 +125,7 @@ void HealthCheckClient::StartCallLocked() {
   call_state_->StartCall();
 }
 
-void HealthCheckClient::StartRetryTimer() {
-  MutexLock lock(&mu_);
+void HealthCheckClient::StartRetryTimerLocked() {
   SetHealthStatusLocked(GRPC_CHANNEL_TRANSIENT_FAILURE,
                         "health check call failed; will retry after backoff");
   grpc_millis next_try = retry_backoff_.NextAttemptTime();
@@ -297,14 +296,7 @@ void HealthCheckClient::CallState::StartCall() {
             "checking call on subchannel (%s); will retry",
             health_check_client_.get(), this, grpc_error_string(error));
     GRPC_ERROR_UNREF(error);
-    // Schedule instead of running directly, since we must not be
-    // holding health_check_client_->mu_ when CallEnded() is called.
-    call_->Ref(DEBUG_LOCATION, "call_end_closure").release();
-    ExecCtx::Run(
-        DEBUG_LOCATION,
-        GRPC_CLOSURE_INIT(&batch_.handler_private.closure, CallEndedRetry, this,
-                          grpc_schedule_on_exec_ctx),
-        GRPC_ERROR_NONE);
+    CallEndedLocked(/*retry=*/true);
     return;
   }
   // Initialize payload and batch.
@@ -582,18 +574,11 @@ void HealthCheckClient::CallState::RecvTrailingMetadataReady(
                                                 kErrorMessage);
     retry = false;
   }
-  self->CallEnded(retry);
-}
-
-void HealthCheckClient::CallState::CallEndedRetry(void* arg,
-                                                  grpc_error* /*error*/) {
-  HealthCheckClient::CallState* self =
-      static_cast<HealthCheckClient::CallState*>(arg);
-  self->CallEnded(true /* retry */);
-  self->call_->Unref(DEBUG_LOCATION, "call_end_closure");
+  MutexLock lock(&self->health_check_client_->mu_);
+  self->CallEndedLocked(retry);
 }
 
-void HealthCheckClient::CallState::CallEnded(bool retry) {
+void HealthCheckClient::CallState::CallEndedLocked(bool retry) {
   // If this CallState is still in use, this call ended because of a failure,
   // so we need to stop using it and optionally create a new one.
   // Otherwise, we have deliberately ended this call, and no further action
@@ -606,10 +591,10 @@ void HealthCheckClient::CallState::CallEnded(bool retry) {
         // If the call fails after we've gotten a successful response, reset
         // the backoff and restart the call immediately.
         health_check_client_->retry_backoff_.Reset();
-        health_check_client_->StartCall();
+        health_check_client_->StartCallLocked();
       } else {
         // If the call failed without receiving any messages, retry later.
-        health_check_client_->StartRetryTimer();
+        health_check_client_->StartRetryTimerLocked();
       }
     }
   }
index f8b9ade..e9555b5 100644 (file)
@@ -72,8 +72,8 @@ class HealthCheckClient : public InternallyRefCounted<HealthCheckClient> {
     void StartBatch(grpc_transport_stream_op_batch* batch);
     static void StartBatchInCallCombiner(void* arg, grpc_error* error);
 
-    static void CallEndedRetry(void* arg, grpc_error* error);
-    void CallEnded(bool retry);
+    // Requires holding health_check_client_->mu_.
+    void CallEndedLocked(bool retry);
 
     static void OnComplete(void* arg, grpc_error* error);
     static void RecvInitialMetadataReady(void* arg, grpc_error* error);
@@ -143,7 +143,7 @@ class HealthCheckClient : public InternallyRefCounted<HealthCheckClient> {
   void StartCall();
   void StartCallLocked();  // Requires holding mu_.
 
-  void StartRetryTimer();
+  void StartRetryTimerLocked();  // Requires holding mu_.
   static void OnRetryTimer(void* arg, grpc_error* error);
 
   void SetHealthStatus(grpc_connectivity_state state, const char* reason);
index efd188c..d490054 100644 (file)
@@ -45,17 +45,23 @@ namespace {
  * credentials if present in the 'http_proxy' env var, otherwise leaves it
  * unchanged. It is caller's responsibility to gpr_free user_cred.
  */
-char* GetHttpProxyServer(char** user_cred) {
+char* GetHttpProxyServer(const grpc_channel_args* args, char** user_cred) {
   GPR_ASSERT(user_cred != nullptr);
   grpc_uri* uri = nullptr;
   char* proxy_name = nullptr;
   char** authority_strs = nullptr;
   size_t authority_nstrs;
-  /* Prefer using 'grpc_proxy'. Fallback on 'http_proxy' if it is not set.
-   * Also prefer using 'https_proxy' with fallback on 'http_proxy'. The
-   * fallback behavior can be removed if there's a demand for it.
+  /* We check the following places to determine the HTTP proxy to use, stopping
+   * at the first one that is set:
+   * 1. GRPC_ARG_HTTP_PROXY channel arg
+   * 2. grpc_proxy environment variable
+   * 3. https_proxy environment variable
+   * 4. http_proxy environment variable
+   * If none of the above are set, then no HTTP proxy will be used.
    */
-  char* uri_str = gpr_getenv("grpc_proxy");
+  char* uri_str =
+      gpr_strdup(grpc_channel_args_find_string(args, GRPC_ARG_HTTP_PROXY));
+  if (uri_str == nullptr) uri_str = gpr_getenv("grpc_proxy");
   if (uri_str == nullptr) uri_str = gpr_getenv("https_proxy");
   if (uri_str == nullptr) uri_str = gpr_getenv("http_proxy");
   if (uri_str == nullptr) return nullptr;
@@ -103,7 +109,7 @@ class HttpProxyMapper : public ProxyMapperInterface {
       return false;
     }
     char* user_cred = nullptr;
-    *name_to_resolve = GetHttpProxyServer(&user_cred);
+    *name_to_resolve = GetHttpProxyServer(args, &user_cred);
     if (*name_to_resolve == nullptr) return false;
     char* no_proxy_str = nullptr;
     grpc_uri* uri = grpc_uri_parse(server_uri, false /* suppress_errors */);
@@ -125,8 +131,8 @@ class HttpProxyMapper : public ProxyMapperInterface {
     if (no_proxy_str != nullptr) {
       static const char* NO_PROXY_SEPARATOR = ",";
       bool use_proxy = true;
-      grpc_core::UniquePtr<char> server_host;
-      grpc_core::UniquePtr<char> server_port;
+      std::string server_host;
+      std::string server_port;
       if (!grpc_core::SplitHostPort(
               uri->path[0] == '/' ? uri->path + 1 : uri->path, &server_host,
               &server_port)) {
@@ -136,7 +142,7 @@ class HttpProxyMapper : public ProxyMapperInterface {
                 server_uri);
         gpr_free(no_proxy_str);
       } else {
-        size_t uri_len = strlen(server_host.get());
+        size_t uri_len = server_host.size();
         char** no_proxy_hosts;
         size_t num_no_proxy_hosts;
         gpr_string_split(no_proxy_str, NO_PROXY_SEPARATOR, &no_proxy_hosts,
@@ -146,7 +152,8 @@ class HttpProxyMapper : public ProxyMapperInterface {
           size_t no_proxy_len = strlen(no_proxy_entry);
           if (no_proxy_len <= uri_len &&
               gpr_stricmp(no_proxy_entry,
-                          &(server_host.get()[uri_len - no_proxy_len])) == 0) {
+                          &(server_host.c_str()[uri_len - no_proxy_len])) ==
+                  0) {
             gpr_log(GPR_INFO, "not using proxy for host in no_proxy list '%s'",
                     server_uri);
             use_proxy = false;
index b034db8..6c639ef 100644 (file)
@@ -33,13 +33,12 @@ DebugOnlyTraceFlag grpc_trace_lb_policy_refcount(false, "lb_policy_refcount");
 
 LoadBalancingPolicy::LoadBalancingPolicy(Args args, intptr_t initial_refcount)
     : InternallyRefCounted(&grpc_trace_lb_policy_refcount, initial_refcount),
-      combiner_(GRPC_COMBINER_REF(args.combiner, "lb_policy")),
+      work_serializer_(std::move(args.work_serializer)),
       interested_parties_(grpc_pollset_set_create()),
       channel_control_helper_(std::move(args.channel_control_helper)) {}
 
 LoadBalancingPolicy::~LoadBalancingPolicy() {
   grpc_pollset_set_destroy(interested_parties_);
-  GRPC_COMBINER_UNREF(combiner_, "lb_policy");
 }
 
 void LoadBalancingPolicy::Orphan() {
@@ -99,29 +98,31 @@ LoadBalancingPolicy::PickResult LoadBalancingPolicy::QueuePicker::Pick(
   //    the time this function returns, the pick will already have
   //    been processed, and we'll be trying to re-process the same
   //    pick again, leading to a crash.
-  // 2. We are currently running in the data plane combiner, but we
-  //    need to bounce into the control plane combiner to call
+  // 2. We are currently running in the data plane mutex, but we
+  //    need to bounce into the control plane work_serializer to call
   //    ExitIdleLocked().
   if (!exit_idle_called_) {
     exit_idle_called_ = true;
-    // Ref held by closure.
-    parent_->Ref(DEBUG_LOCATION, "QueuePicker::CallExitIdle").release();
-    parent_->combiner()->Run(
-        GRPC_CLOSURE_CREATE(&CallExitIdle, parent_.get(), nullptr),
-        GRPC_ERROR_NONE);
+    auto* parent = parent_->Ref().release();  // ref held by lambda.
+    ExecCtx::Run(DEBUG_LOCATION,
+                 GRPC_CLOSURE_CREATE(
+                     [](void* arg, grpc_error* /*error*/) {
+                       auto* parent = static_cast<LoadBalancingPolicy*>(arg);
+                       parent->work_serializer()->Run(
+                           [parent]() {
+                             parent->ExitIdleLocked();
+                             parent->Unref();
+                           },
+                           DEBUG_LOCATION);
+                     },
+                     parent, nullptr),
+                 GRPC_ERROR_NONE);
   }
   PickResult result;
   result.type = PickResult::PICK_QUEUE;
   return result;
 }
 
-void LoadBalancingPolicy::QueuePicker::CallExitIdle(void* arg,
-                                                    grpc_error* /*error*/) {
-  LoadBalancingPolicy* parent = static_cast<LoadBalancingPolicy*>(arg);
-  parent->ExitIdleLocked();
-  parent->Unref(DEBUG_LOCATION, "QueuePicker::CallExitIdle");
-}
-
 //
 // LoadBalancingPolicy::TransientFailurePicker
 //
index b3829d7..7a775af 100644 (file)
 #include <functional>
 #include <iterator>
 
+#include "absl/strings/string_view.h"
+
 #include "src/core/ext/filters/client_channel/server_address.h"
 #include "src/core/ext/filters/client_channel/service_config.h"
 #include "src/core/ext/filters/client_channel/subchannel_interface.h"
 #include "src/core/lib/gprpp/map.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/gprpp/string_view.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/polling_entity.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "src/core/lib/transport/connectivity_state.h"
 
 namespace grpc_core {
@@ -72,7 +73,7 @@ extern DebugOnlyTraceFlag grpc_trace_lb_policy_refcount;
 /// LoadBalacingPolicy API.
 ///
 /// Note: All methods with a "Locked" suffix must be called from the
-/// combiner passed to the constructor.
+/// work_serializer passed to the constructor.
 ///
 /// Any I/O done by the LB policy should be done under the pollset_set
 /// returned by \a interested_parties().
@@ -93,11 +94,11 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
     /// Application-specific requests cost metrics.  Metric names are
     /// determined by the application.  Each value is an absolute cost
     /// (e.g. 3487 bytes of storage) associated with the request.
-    std::map<StringView, double, StringLess> request_cost;
+    std::map<absl::string_view, double, StringLess> request_cost;
     /// Application-specific resource utilization metrics.  Metric names
     /// are determined by the application.  Each value is expressed as a
     /// fraction of total resources available.
-    std::map<StringView, double, StringLess> utilization;
+    std::map<absl::string_view, double, StringLess> utilization;
   };
 
   /// Interface for accessing per-call state.
@@ -115,7 +116,17 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
 
     /// Returns the backend metric data returned by the server for the call,
     /// or null if no backend metric data was returned.
+    // TODO(roth): Move this out of CallState, since it should not be
+    // accessible to the picker, only to the recv_trailing_metadata_ready
+    // callback.  It should instead be in its own interface.
     virtual const BackendMetricData* GetBackendMetricData() = 0;
+
+    /// EXPERIMENTAL API.
+    /// Returns the value of the call attribute \a key.
+    /// Keys are static strings, so an attribute can be accessed by an LB
+    /// policy implementation only if it knows about the internal key.
+    /// Returns a null string_view if key not found.
+    virtual absl::string_view ExperimentalGetCallAttribute(const char* key) = 0;
   };
 
   /// Interface for accessing metadata.
@@ -123,12 +134,13 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
   class MetadataInterface {
    public:
     class iterator
-        : public std::iterator<std::input_iterator_tag,
-                               std::pair<StringView, StringView>,  // value_type
-                               std::ptrdiff_t,  // difference_type
-                               std::pair<StringView, StringView>*,  // pointer
-                               std::pair<StringView, StringView>&   // reference
-                               > {
+        : public std::iterator<
+              std::input_iterator_tag,
+              std::pair<absl::string_view, absl::string_view>,  // value_type
+              std::ptrdiff_t,  // difference_type
+              std::pair<absl::string_view, absl::string_view>*,  // pointer
+              std::pair<absl::string_view, absl::string_view>&   // reference
+              > {
      public:
       iterator(const MetadataInterface* md, intptr_t handle)
           : md_(md), handle_(handle) {}
@@ -155,7 +167,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
     /// Implementations must ensure that the key and value remain alive
     /// until the call ends.  If desired, they may be allocated via
     /// CallState::Alloc().
-    virtual void Add(StringView key, StringView value) = 0;
+    virtual void Add(absl::string_view key, absl::string_view value) = 0;
 
     /// Iteration interface.
     virtual iterator begin() const = 0;
@@ -172,7 +184,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
     friend class iterator;
 
     virtual intptr_t IteratorHandleNext(intptr_t handle) const = 0;
-    virtual std::pair<StringView /*key*/, StringView /*value */>
+    virtual std::pair<absl::string_view /*key*/, absl::string_view /*value */>
     IteratorHandleGet(intptr_t handle) const = 0;
   };
 
@@ -184,7 +196,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
     /// call to the chosen backend.
     MetadataInterface* initial_metadata;
     /// An interface for accessing call state.  Can be used to allocate
-    /// data associated with the call in an efficient way.
+    /// memory associated with the call in an efficient way.
     CallState* call_state;
   };
 
@@ -226,6 +238,9 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
     /// does not take ownership, so any data that needs to be used after
     /// returning must be copied.
     /// The call state can be used to obtain backend metric data.
+    // TODO(roth): The arguments to this callback should be moved into a
+    // struct, so that we can later add new fields without breaking
+    // existing implementations.
     std::function<void(grpc_error*, MetadataInterface*, CallState*)>
         recv_trailing_metadata_ready;
   };
@@ -242,7 +257,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
   /// live in the LB policy object itself.
   ///
   /// Currently, pickers are always accessed from within the
-  /// client_channel data plane combiner, so they do not have to be
+  /// client_channel data plane mutex, so they do not have to be
   /// thread-safe.
   class SubchannelPicker {
    public:
@@ -254,9 +269,6 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
 
   /// A proxy object implemented by the client channel and used by the
   /// LB policy to communicate with the channel.
-  // TODO(juanlishen): Consider adding a mid-layer subclass that helps handle
-  // things like swapping in pending policy when it's ready. Currently, we are
-  // duplicating the logic in many subclasses.
   class ChannelControlHelper {
    public:
     ChannelControlHelper() = default;
@@ -276,7 +288,8 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
 
     /// Adds a trace message associated with the channel.
     enum TraceSeverity { TRACE_INFO, TRACE_WARNING, TRACE_ERROR };
-    virtual void AddTraceEvent(TraceSeverity severity, StringView message) = 0;
+    virtual void AddTraceEvent(TraceSeverity severity,
+                               absl::string_view message) = 0;
   };
 
   /// Interface for configuration data used by an LB policy implementation.
@@ -309,12 +322,8 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
 
   /// Args used to instantiate an LB policy.
   struct Args {
-    /// The combiner under which all LB policy calls will be run.
-    /// Policy does NOT take ownership of the reference to the combiner.
-    // TODO(roth): Once we have a C++-like interface for combiners, this
-    // API should change to take a smart pointer that does pass ownership
-    // of a reference.
-    Combiner* combiner = nullptr;
+    /// The work_serializer under which all LB policy calls will be run.
+    std::shared_ptr<WorkSerializer> work_serializer;
     /// Channel control helper.
     /// Note: LB policies MUST NOT call any method on the helper from
     /// their constructor.
@@ -352,7 +361,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
 
   grpc_pollset_set* interested_parties() const { return interested_parties_; }
 
-  // Note: This must be invoked while holding the combiner.
+  // Note: This must be invoked while holding the work_serializer.
   void Orphan() override;
 
   // A picker that returns PICK_QUEUE for all picks.
@@ -368,8 +377,6 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
     PickResult Pick(PickArgs args) override;
 
    private:
-    static void CallExitIdle(void* arg, grpc_error* error);
-
     RefCountedPtr<LoadBalancingPolicy> parent_;
     bool exit_idle_called_ = false;
   };
@@ -387,7 +394,9 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
   };
 
  protected:
-  Combiner* combiner() const { return combiner_; }
+  std::shared_ptr<WorkSerializer> work_serializer() const {
+    return work_serializer_;
+  }
 
   // Note: LB policies MUST NOT call any method on the helper from their
   // constructor.
@@ -399,8 +408,8 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
   virtual void ShutdownLocked() = 0;
 
  private:
-  /// Combiner under which LB policy actions take place.
-  Combiner* combiner_;
+  /// Work Serializer under which LB policy actions take place.
+  std::shared_ptr<WorkSerializer> work_serializer_;
   /// Owned pointer to interested parties in load balancing decisions.
   grpc_pollset_set* interested_parties_;
   /// Channel control helper.
index 1ed5a69..8d8003d 100644 (file)
@@ -49,7 +49,8 @@ class ChildPolicyHandler::Helper
                    std::unique_ptr<SubchannelPicker> picker) override {
     if (parent_->shutting_down_) return;
     // If this request is from the pending child policy, ignore it until
-    // it reports READY, at which point we swap it into place.
+    // it reports something other than CONNECTING, at which point we swap it
+    // into place.
     if (CalledByPendingChild()) {
       if (GRPC_TRACE_FLAG_ENABLED(*(parent_->tracer_))) {
         gpr_log(GPR_INFO,
@@ -57,7 +58,7 @@ class ChildPolicyHandler::Helper
                 "reports state=%s",
                 parent_.get(), this, child_, ConnectivityStateName(state));
       }
-      if (state != GRPC_CHANNEL_READY) return;
+      if (state == GRPC_CHANNEL_CONNECTING) return;
       grpc_pollset_set_del_pollset_set(
           parent_->child_policy_->interested_parties(),
           parent_->interested_parties());
@@ -86,7 +87,8 @@ class ChildPolicyHandler::Helper
     parent_->channel_control_helper()->RequestReresolution();
   }
 
-  void AddTraceEvent(TraceSeverity severity, StringView message) override {
+  void AddTraceEvent(TraceSeverity severity,
+                     absl::string_view message) override {
     if (parent_->shutting_down_) return;
     if (!CalledByPendingChild() && !CalledByCurrentChild()) return;
     parent_->channel_control_helper()->AddTraceEvent(severity, message);
@@ -201,6 +203,10 @@ void ChildPolicyHandler::UpdateLocked(UpdateArgs args) {
     // Cases 1, 2b, and 3b: create a new child policy.
     // If child_policy_ is null, we set it (case 1), else we set
     // pending_child_policy_ (cases 2b and 3b).
+    // TODO(roth): In cases 2b and 3b, we should start a timer here, so
+    // that there's an upper bound on the amount of time it takes us to
+    // switch to the new policy, even if the new policy stays in
+    // CONNECTING for a very long period of time.
     if (GRPC_TRACE_FLAG_ENABLED(*tracer_)) {
       gpr_log(GPR_INFO,
               "[child_policy_handler %p] creating new %schild policy %s", this,
@@ -251,7 +257,7 @@ OrphanablePtr<LoadBalancingPolicy> ChildPolicyHandler::CreateChildPolicy(
     const char* child_policy_name, const grpc_channel_args& args) {
   Helper* helper = new Helper(Ref(DEBUG_LOCATION, "Helper"));
   LoadBalancingPolicy::Args lb_policy_args;
-  lb_policy_args.combiner = combiner();
+  lb_policy_args.work_serializer = work_serializer();
   lb_policy_args.channel_control_helper =
       std::unique_ptr<ChannelControlHelper>(helper);
   lb_policy_args.args = &args;
index da72451..d242357 100644 (file)
 #include <limits.h>
 #include <string.h>
 
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/byte_buffer_reader.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
@@ -91,7 +95,6 @@
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/timer.h"
@@ -179,11 +182,11 @@ class GrpcLb : public LoadBalancingPolicy {
     static void OnBalancerMessageReceived(void* arg, grpc_error* error);
     static void OnBalancerStatusReceived(void* arg, grpc_error* error);
 
-    static void MaybeSendClientLoadReportLocked(void* arg, grpc_error* error);
-    static void ClientLoadReportDoneLocked(void* arg, grpc_error* error);
-    static void OnInitialRequestSentLocked(void* arg, grpc_error* error);
-    static void OnBalancerMessageReceivedLocked(void* arg, grpc_error* error);
-    static void OnBalancerStatusReceivedLocked(void* arg, grpc_error* error);
+    void MaybeSendClientLoadReportLocked(grpc_error* error);
+    void ClientLoadReportDoneLocked(grpc_error* error);
+    void OnInitialRequestSentLocked();
+    void OnBalancerMessageReceivedLocked();
+    void OnBalancerStatusReceivedLocked(grpc_error* error);
 
     // The owning LB policy.
     RefCountedPtr<LoadBalancingPolicy> grpclb_policy_;
@@ -234,7 +237,7 @@ class GrpcLb : public LoadBalancingPolicy {
     const std::vector<GrpcLbServer>& serverlist() const { return serverlist_; }
 
     // Returns a text representation suitable for logging.
-    grpc_core::UniquePtr<char> AsText() const;
+    std::string AsText() const;
 
     // Extracts all non-drop entries into a ServerAddressList.
     ServerAddressList GetServerAddressList(
@@ -248,16 +251,16 @@ class GrpcLb : public LoadBalancingPolicy {
     // should not be dropped.
     //
     // Note: This is called from the picker, so it will be invoked in
-    // the channel's data plane combiner, NOT the control plane
-    // combiner.  It should not be accessed by any other part of the LB
+    // the channel's data plane mutex, NOT the control plane
+    // work_serializer.  It should not be accessed by any other part of the LB
     // policy.
     const char* ShouldDrop();
 
    private:
     std::vector<GrpcLbServer> serverlist_;
 
-    // Guarded by the channel's data plane combiner, NOT the control
-    // plane combiner.  It should not be accessed by anything but the
+    // Guarded by the channel's data plane mutex, NOT the control
+    // plane work_serializer.  It should not be accessed by anything but the
     // picker via the ShouldDrop() method.
     size_t drop_index_ = 0;
   };
@@ -296,7 +299,8 @@ class GrpcLb : public LoadBalancingPolicy {
     void UpdateState(grpc_connectivity_state state,
                      std::unique_ptr<SubchannelPicker> picker) override;
     void RequestReresolution() override;
-    void AddTraceEvent(TraceSeverity severity, StringView message) override;
+    void AddTraceEvent(TraceSeverity severity,
+                       absl::string_view message) override;
 
    private:
     RefCountedPtr<GrpcLb> parent_;
@@ -305,7 +309,7 @@ class GrpcLb : public LoadBalancingPolicy {
   class StateWatcher : public AsyncConnectivityStateWatcherInterface {
    public:
     explicit StateWatcher(RefCountedPtr<GrpcLb> parent)
-        : AsyncConnectivityStateWatcherInterface(parent->combiner()),
+        : AsyncConnectivityStateWatcherInterface(parent->work_serializer()),
           parent_(std::move(parent)) {}
 
     ~StateWatcher() { parent_.reset(DEBUG_LOCATION, "StateWatcher"); }
@@ -340,18 +344,19 @@ class GrpcLb : public LoadBalancingPolicy {
   // Helper functions used in UpdateLocked().
   void ProcessAddressesAndChannelArgsLocked(const ServerAddressList& addresses,
                                             const grpc_channel_args& args);
+
   void CancelBalancerChannelConnectivityWatchLocked();
 
   // Methods for dealing with fallback state.
   void MaybeEnterFallbackModeAfterStartup();
   static void OnFallbackTimer(void* arg, grpc_error* error);
-  static void OnFallbackTimerLocked(void* arg, grpc_error* error);
+  void OnFallbackTimerLocked(grpc_error* error);
 
   // Methods for dealing with the balancer call.
   void StartBalancerCallLocked();
   void StartBalancerCallRetryTimerLocked();
   static void OnBalancerCallRetryTimer(void* arg, grpc_error* error);
-  static void OnBalancerCallRetryTimerLocked(void* arg, grpc_error* error);
+  void OnBalancerCallRetryTimerLocked(grpc_error* error);
 
   // Methods for dealing with the child policy.
   grpc_channel_args* CreateChildPolicyArgsLocked(
@@ -442,28 +447,22 @@ void ParseServer(const GrpcLbServer& server, grpc_resolved_address* addr) {
   }
 }
 
-grpc_core::UniquePtr<char> GrpcLb::Serverlist::AsText() const {
-  gpr_strvec entries;
-  gpr_strvec_init(&entries);
+std::string GrpcLb::Serverlist::AsText() const {
+  std::vector<std::string> entries;
   for (size_t i = 0; i < serverlist_.size(); ++i) {
     const GrpcLbServer& server = serverlist_[i];
-    char* ipport;
+    std::string ipport;
     if (server.drop) {
-      ipport = gpr_strdup("(drop)");
+      ipport = "(drop)";
     } else {
       grpc_resolved_address addr;
       ParseServer(server, &addr);
-      grpc_sockaddr_to_string(&ipport, &addr, false);
+      ipport = grpc_sockaddr_to_string(&addr, false);
     }
-    char* entry;
-    gpr_asprintf(&entry, "  %" PRIuPTR ": %s token=%s\n", i, ipport,
-                 server.load_balance_token);
-    gpr_free(ipport);
-    gpr_strvec_add(&entries, entry);
+    entries.push_back(absl::StrFormat("  %" PRIuPTR ": %s token=%s\n", i,
+                                      ipport, server.load_balance_token));
   }
-  grpc_core::UniquePtr<char> result(gpr_strvec_flatten(&entries, nullptr));
-  gpr_strvec_destroy(&entries);
-  return result;
+  return absl::StrJoin(entries, "");
 }
 
 // vtables for channel args for LB token and client stats.
@@ -555,7 +554,7 @@ ServerAddressList GrpcLb::Serverlist::GetServerAddressList(
       lb_token[0] = '\0';
     }
     // Add address.
-    InlinedVector<grpc_arg, 2> args_to_add;
+    absl::InlinedVector<grpc_arg, 2> args_to_add;
     args_to_add.emplace_back(grpc_channel_arg_pointer_create(
         const_cast<char*>(GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN), lb_token,
         &lb_token_arg_vtable));
@@ -626,7 +625,7 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) {
       // how to interpret it.
       args.initial_metadata->Add(
           kGrpcLbClientStatsMetadataKey,
-          StringView(reinterpret_cast<const char*>(client_stats), 0));
+          absl::string_view(reinterpret_cast<const char*>(client_stats), 0));
       // Update calls-started.
       client_stats->AddCallStarted();
     }
@@ -719,7 +718,8 @@ void GrpcLb::Helper::RequestReresolution() {
   }
 }
 
-void GrpcLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
+void GrpcLb::Helper::AddTraceEvent(TraceSeverity severity,
+                                   absl::string_view message) {
   if (parent_->shutting_down_) return;
   parent_->channel_control_helper()->AddTraceEvent(severity, message);
 }
@@ -739,6 +739,15 @@ GrpcLb::BalancerCallState::BalancerCallState(
   // the polling entities from client_channel.
   GPR_ASSERT(grpclb_policy()->server_name_ != nullptr);
   GPR_ASSERT(grpclb_policy()->server_name_[0] != '\0');
+  // Closure Initialization
+  GRPC_CLOSURE_INIT(&lb_on_initial_request_sent_, OnInitialRequestSent, this,
+                    grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&lb_on_balancer_message_received_,
+                    OnBalancerMessageReceived, this, grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&lb_on_balancer_status_received_, OnBalancerStatusReceived,
+                    this, grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&client_load_report_closure_, MaybeSendClientLoadReport,
+                    this, grpc_schedule_on_exec_ctx);
   const grpc_millis deadline =
       grpclb_policy()->lb_call_timeout_ms_ == 0
           ? GRPC_MILLIS_INF_FUTURE
@@ -815,8 +824,6 @@ void GrpcLb::BalancerCallState::StartQuery() {
   // with the callback.
   auto self = Ref(DEBUG_LOCATION, "on_initial_request_sent");
   self.release();
-  GRPC_CLOSURE_INIT(&lb_on_initial_request_sent_, OnInitialRequestSent, this,
-                    grpc_schedule_on_exec_ctx);
   call_error = grpc_call_start_batch_and_execute(
       lb_call_, ops, (size_t)(op - ops), &lb_on_initial_request_sent_);
   GPR_ASSERT(GRPC_CALL_OK == call_error);
@@ -839,8 +846,6 @@ void GrpcLb::BalancerCallState::StartQuery() {
   // with the callback.
   self = Ref(DEBUG_LOCATION, "on_message_received");
   self.release();
-  GRPC_CLOSURE_INIT(&lb_on_balancer_message_received_,
-                    OnBalancerMessageReceived, this, grpc_schedule_on_exec_ctx);
   call_error = grpc_call_start_batch_and_execute(
       lb_call_, ops, (size_t)(op - ops), &lb_on_balancer_message_received_);
   GPR_ASSERT(GRPC_CALL_OK == call_error);
@@ -857,8 +862,6 @@ void GrpcLb::BalancerCallState::StartQuery() {
   // This callback signals the end of the LB call, so it relies on the initial
   // ref instead of a new ref. When it's invoked, it's the initial ref that is
   // unreffed.
-  GRPC_CLOSURE_INIT(&lb_on_balancer_status_received_, OnBalancerStatusReceived,
-                    this, grpc_schedule_on_exec_ctx);
   call_error = grpc_call_start_batch_and_execute(
       lb_call_, ops, (size_t)(op - ops), &lb_on_balancer_status_received_);
   GPR_ASSERT(GRPC_CALL_OK == call_error);
@@ -877,28 +880,27 @@ void GrpcLb::BalancerCallState::ScheduleNextClientLoadReportLocked() {
 void GrpcLb::BalancerCallState::MaybeSendClientLoadReport(void* arg,
                                                           grpc_error* error) {
   BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  lb_calld->grpclb_policy()->combiner()->Run(
-      GRPC_CLOSURE_INIT(&lb_calld->client_load_report_closure_,
-                        MaybeSendClientLoadReportLocked, lb_calld, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  lb_calld->grpclb_policy()->work_serializer()->Run(
+      [lb_calld, error]() { lb_calld->MaybeSendClientLoadReportLocked(error); },
+      DEBUG_LOCATION);
 }
 
 void GrpcLb::BalancerCallState::MaybeSendClientLoadReportLocked(
-    void* arg, grpc_error* error) {
-  BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  GrpcLb* grpclb_policy = lb_calld->grpclb_policy();
-  lb_calld->client_load_report_timer_callback_pending_ = false;
-  if (error != GRPC_ERROR_NONE || lb_calld != grpclb_policy->lb_calld_.get()) {
-    lb_calld->Unref(DEBUG_LOCATION, "client_load_report");
+    grpc_error* error) {
+  client_load_report_timer_callback_pending_ = false;
+  if (error != GRPC_ERROR_NONE || this != grpclb_policy()->lb_calld_.get()) {
+    Unref(DEBUG_LOCATION, "client_load_report");
+    GRPC_ERROR_UNREF(error);
     return;
   }
   // If we've already sent the initial request, then we can go ahead and send
   // the load report. Otherwise, we need to wait until the initial request has
   // been sent to send this (see OnInitialRequestSentLocked()).
-  if (lb_calld->send_message_payload_ == nullptr) {
-    lb_calld->SendClientLoadReportLocked();
+  if (send_message_payload_ == nullptr) {
+    SendClientLoadReportLocked();
   } else {
-    lb_calld->client_load_report_is_due_ = true;
+    client_load_report_is_due_ = true;
   }
 }
 
@@ -957,140 +959,125 @@ void GrpcLb::BalancerCallState::SendClientLoadReportLocked() {
 void GrpcLb::BalancerCallState::ClientLoadReportDone(void* arg,
                                                      grpc_error* error) {
   BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  lb_calld->grpclb_policy()->combiner()->Run(
-      GRPC_CLOSURE_INIT(&lb_calld->client_load_report_closure_,
-                        ClientLoadReportDoneLocked, lb_calld, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  lb_calld->grpclb_policy()->work_serializer()->Run(
+      [lb_calld, error]() { lb_calld->ClientLoadReportDoneLocked(error); },
+      DEBUG_LOCATION);
 }
 
-void GrpcLb::BalancerCallState::ClientLoadReportDoneLocked(void* arg,
-                                                           grpc_error* error) {
-  BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  GrpcLb* grpclb_policy = lb_calld->grpclb_policy();
-  grpc_byte_buffer_destroy(lb_calld->send_message_payload_);
-  lb_calld->send_message_payload_ = nullptr;
-  if (error != GRPC_ERROR_NONE || lb_calld != grpclb_policy->lb_calld_.get()) {
-    lb_calld->Unref(DEBUG_LOCATION, "client_load_report");
+void GrpcLb::BalancerCallState::ClientLoadReportDoneLocked(grpc_error* error) {
+  grpc_byte_buffer_destroy(send_message_payload_);
+  send_message_payload_ = nullptr;
+  if (error != GRPC_ERROR_NONE || this != grpclb_policy()->lb_calld_.get()) {
+    Unref(DEBUG_LOCATION, "client_load_report");
+    GRPC_ERROR_UNREF(error);
     return;
   }
-  lb_calld->ScheduleNextClientLoadReportLocked();
+  ScheduleNextClientLoadReportLocked();
 }
 
 void GrpcLb::BalancerCallState::OnInitialRequestSent(void* arg,
-                                                     grpc_error* error) {
+                                                     grpc_error* /*error*/) {
   BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  lb_calld->grpclb_policy()->combiner()->Run(
-      GRPC_CLOSURE_INIT(&lb_calld->lb_on_initial_request_sent_,
-                        OnInitialRequestSentLocked, lb_calld, nullptr),
-      GRPC_ERROR_REF(error));
+  lb_calld->grpclb_policy()->work_serializer()->Run(
+      [lb_calld]() { lb_calld->OnInitialRequestSentLocked(); }, DEBUG_LOCATION);
 }
 
-void GrpcLb::BalancerCallState::OnInitialRequestSentLocked(
-    void* arg, grpc_error* /*error*/) {
-  BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  grpc_byte_buffer_destroy(lb_calld->send_message_payload_);
-  lb_calld->send_message_payload_ = nullptr;
+void GrpcLb::BalancerCallState::OnInitialRequestSentLocked() {
+  grpc_byte_buffer_destroy(send_message_payload_);
+  send_message_payload_ = nullptr;
   // If we attempted to send a client load report before the initial request was
   // sent (and this lb_calld is still in use), send the load report now.
-  if (lb_calld->client_load_report_is_due_ &&
-      lb_calld == lb_calld->grpclb_policy()->lb_calld_.get()) {
-    lb_calld->SendClientLoadReportLocked();
-    lb_calld->client_load_report_is_due_ = false;
+  if (client_load_report_is_due_ && this == grpclb_policy()->lb_calld_.get()) {
+    SendClientLoadReportLocked();
+    client_load_report_is_due_ = false;
   }
-  lb_calld->Unref(DEBUG_LOCATION, "on_initial_request_sent");
+  Unref(DEBUG_LOCATION, "on_initial_request_sent");
 }
 
-void GrpcLb::BalancerCallState::OnBalancerMessageReceived(void* arg,
-                                                          grpc_error* error) {
+void GrpcLb::BalancerCallState::OnBalancerMessageReceived(
+    void* arg, grpc_error* /*error*/) {
   BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  lb_calld->grpclb_policy()->combiner()->Run(
-      GRPC_CLOSURE_INIT(&lb_calld->lb_on_balancer_message_received_,
-                        OnBalancerMessageReceivedLocked, lb_calld, nullptr),
-      GRPC_ERROR_REF(error));
+  lb_calld->grpclb_policy()->work_serializer()->Run(
+      [lb_calld]() { lb_calld->OnBalancerMessageReceivedLocked(); },
+      DEBUG_LOCATION);
 }
 
-void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
-    void* arg, grpc_error* /*error*/) {
-  BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  GrpcLb* grpclb_policy = lb_calld->grpclb_policy();
+void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked() {
   // Null payload means the LB call was cancelled.
-  if (lb_calld != grpclb_policy->lb_calld_.get() ||
-      lb_calld->recv_message_payload_ == nullptr) {
-    lb_calld->Unref(DEBUG_LOCATION, "on_message_received");
+  if (this != grpclb_policy()->lb_calld_.get() ||
+      recv_message_payload_ == nullptr) {
+    Unref(DEBUG_LOCATION, "on_message_received");
     return;
   }
   grpc_byte_buffer_reader bbr;
-  grpc_byte_buffer_reader_init(&bbr, lb_calld->recv_message_payload_);
+  grpc_byte_buffer_reader_init(&bbr, recv_message_payload_);
   grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
   grpc_byte_buffer_reader_destroy(&bbr);
-  grpc_byte_buffer_destroy(lb_calld->recv_message_payload_);
-  lb_calld->recv_message_payload_ = nullptr;
+  grpc_byte_buffer_destroy(recv_message_payload_);
+  recv_message_payload_ = nullptr;
   GrpcLbResponse response;
   upb::Arena arena;
   if (!GrpcLbResponseParse(response_slice, arena.ptr(), &response) ||
-      (response.type == response.INITIAL && lb_calld->seen_initial_response_)) {
+      (response.type == response.INITIAL && seen_initial_response_)) {
     char* response_slice_str =
         grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX);
     gpr_log(GPR_ERROR,
             "[grpclb %p] lb_calld=%p: Invalid LB response received: '%s'. "
             "Ignoring.",
-            grpclb_policy, lb_calld, response_slice_str);
+            grpclb_policy(), this, response_slice_str);
     gpr_free(response_slice_str);
   } else {
     switch (response.type) {
       case response.INITIAL: {
         if (response.client_stats_report_interval != 0) {
-          lb_calld->client_stats_report_interval_ =
+          client_stats_report_interval_ =
               GPR_MAX(GPR_MS_PER_SEC, response.client_stats_report_interval);
           if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
             gpr_log(GPR_INFO,
                     "[grpclb %p] lb_calld=%p: Received initial LB response "
                     "message; client load reporting interval = %" PRId64
                     " milliseconds",
-                    grpclb_policy, lb_calld,
-                    lb_calld->client_stats_report_interval_);
+                    grpclb_policy(), this, client_stats_report_interval_);
           }
         } else if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
           gpr_log(GPR_INFO,
                   "[grpclb %p] lb_calld=%p: Received initial LB response "
                   "message; client load reporting NOT enabled",
-                  grpclb_policy, lb_calld);
+                  grpclb_policy(), this);
         }
-        lb_calld->seen_initial_response_ = true;
+        seen_initial_response_ = true;
         break;
       }
       case response.SERVERLIST: {
-        GPR_ASSERT(lb_calld->lb_call_ != nullptr);
+        GPR_ASSERT(lb_call_ != nullptr);
         auto serverlist_wrapper =
             MakeRefCounted<Serverlist>(std::move(response.serverlist));
         if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
-          grpc_core::UniquePtr<char> serverlist_text =
-              serverlist_wrapper->AsText();
           gpr_log(GPR_INFO,
                   "[grpclb %p] lb_calld=%p: Serverlist with %" PRIuPTR
                   " servers received:\n%s",
-                  grpclb_policy, lb_calld,
+                  grpclb_policy(), this,
                   serverlist_wrapper->serverlist().size(),
-                  serverlist_text.get());
+                  serverlist_wrapper->AsText().c_str());
         }
-        lb_calld->seen_serverlist_ = true;
+        seen_serverlist_ = true;
         // Start sending client load report only after we start using the
         // serverlist returned from the current LB call.
-        if (lb_calld->client_stats_report_interval_ > 0 &&
-            lb_calld->client_stats_ == nullptr) {
-          lb_calld->client_stats_ = MakeRefCounted<GrpcLbClientStats>();
+        if (client_stats_report_interval_ > 0 && client_stats_ == nullptr) {
+          client_stats_ = MakeRefCounted<GrpcLbClientStats>();
           // Ref held by callback.
-          lb_calld->Ref(DEBUG_LOCATION, "client_load_report").release();
-          lb_calld->ScheduleNextClientLoadReportLocked();
+          Ref(DEBUG_LOCATION, "client_load_report").release();
+          ScheduleNextClientLoadReportLocked();
         }
         // Check if the serverlist differs from the previous one.
-        if (grpclb_policy->serverlist_ != nullptr &&
-            *grpclb_policy->serverlist_ == *serverlist_wrapper) {
+        if (grpclb_policy()->serverlist_ != nullptr &&
+            *grpclb_policy()->serverlist_ == *serverlist_wrapper) {
           if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
             gpr_log(GPR_INFO,
                     "[grpclb %p] lb_calld=%p: Incoming server list identical "
                     "to current, ignoring.",
-                    grpclb_policy, lb_calld);
+                    grpclb_policy(), this);
           }
         } else {  // New serverlist.
           // Dispose of the fallback.
@@ -1112,130 +1099,124 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
           // the grpclb implementation at this point, since we're deprecating
           // it in favor of the xds policy.  We will implement this the
           // right way in the xds policy instead.
-          if (grpclb_policy->fallback_mode_) {
+          if (grpclb_policy()->fallback_mode_) {
             gpr_log(GPR_INFO,
                     "[grpclb %p] Received response from balancer; exiting "
                     "fallback mode",
-                    grpclb_policy);
-            grpclb_policy->fallback_mode_ = false;
+                    grpclb_policy());
+            grpclb_policy()->fallback_mode_ = false;
           }
-          if (grpclb_policy->fallback_at_startup_checks_pending_) {
-            grpclb_policy->fallback_at_startup_checks_pending_ = false;
-            grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_);
-            grpclb_policy->CancelBalancerChannelConnectivityWatchLocked();
+          if (grpclb_policy()->fallback_at_startup_checks_pending_) {
+            grpclb_policy()->fallback_at_startup_checks_pending_ = false;
+            grpc_timer_cancel(&grpclb_policy()->lb_fallback_timer_);
+            grpclb_policy()->CancelBalancerChannelConnectivityWatchLocked();
           }
           // Update the serverlist in the GrpcLb instance. This serverlist
           // instance will be destroyed either upon the next update or when the
           // GrpcLb instance is destroyed.
-          grpclb_policy->serverlist_ = std::move(serverlist_wrapper);
-          grpclb_policy->CreateOrUpdateChildPolicyLocked();
+          grpclb_policy()->serverlist_ = std::move(serverlist_wrapper);
+          grpclb_policy()->CreateOrUpdateChildPolicyLocked();
         }
         break;
       }
       case response.FALLBACK: {
-        if (!grpclb_policy->fallback_mode_) {
+        if (!grpclb_policy()->fallback_mode_) {
           gpr_log(GPR_INFO,
                   "[grpclb %p] Entering fallback mode as requested by balancer",
-                  grpclb_policy);
-          if (grpclb_policy->fallback_at_startup_checks_pending_) {
-            grpclb_policy->fallback_at_startup_checks_pending_ = false;
-            grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_);
-            grpclb_policy->CancelBalancerChannelConnectivityWatchLocked();
+                  grpclb_policy());
+          if (grpclb_policy()->fallback_at_startup_checks_pending_) {
+            grpclb_policy()->fallback_at_startup_checks_pending_ = false;
+            grpc_timer_cancel(&grpclb_policy()->lb_fallback_timer_);
+            grpclb_policy()->CancelBalancerChannelConnectivityWatchLocked();
           }
-          grpclb_policy->fallback_mode_ = true;
-          grpclb_policy->CreateOrUpdateChildPolicyLocked();
+          grpclb_policy()->fallback_mode_ = true;
+          grpclb_policy()->CreateOrUpdateChildPolicyLocked();
           // Reset serverlist, so that if the balancer exits fallback
           // mode by sending the same serverlist we were previously
           // using, we don't incorrectly ignore it as a duplicate.
-          grpclb_policy->serverlist_.reset();
+          grpclb_policy()->serverlist_.reset();
         }
         break;
       }
     }
   }
   grpc_slice_unref_internal(response_slice);
-  if (!grpclb_policy->shutting_down_) {
+  if (!grpclb_policy()->shutting_down_) {
     // Keep listening for serverlist updates.
     grpc_op op;
     memset(&op, 0, sizeof(op));
     op.op = GRPC_OP_RECV_MESSAGE;
-    op.data.recv_message.recv_message = &lb_calld->recv_message_payload_;
+    op.data.recv_message.recv_message = &recv_message_payload_;
     op.flags = 0;
     op.reserved = nullptr;
     // Reuse the "OnBalancerMessageReceivedLocked" ref taken in StartQuery().
-    GRPC_CLOSURE_INIT(&lb_calld->lb_on_balancer_message_received_,
-                      GrpcLb::BalancerCallState::OnBalancerMessageReceived,
-                      lb_calld, grpc_schedule_on_exec_ctx);
     const grpc_call_error call_error = grpc_call_start_batch_and_execute(
-        lb_calld->lb_call_, &op, 1,
-        &lb_calld->lb_on_balancer_message_received_);
+        lb_call_, &op, 1, &lb_on_balancer_message_received_);
     GPR_ASSERT(GRPC_CALL_OK == call_error);
   } else {
-    lb_calld->Unref(DEBUG_LOCATION, "on_message_received+grpclb_shutdown");
+    Unref(DEBUG_LOCATION, "on_message_received+grpclb_shutdown");
   }
 }
 
 void GrpcLb::BalancerCallState::OnBalancerStatusReceived(void* arg,
                                                          grpc_error* error) {
   BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  lb_calld->grpclb_policy()->combiner()->Run(
-      GRPC_CLOSURE_INIT(&lb_calld->lb_on_balancer_status_received_,
-                        OnBalancerStatusReceivedLocked, lb_calld, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // owned by lambda
+  lb_calld->grpclb_policy()->work_serializer()->Run(
+      [lb_calld, error]() { lb_calld->OnBalancerStatusReceivedLocked(error); },
+      DEBUG_LOCATION);
 }
 
 void GrpcLb::BalancerCallState::OnBalancerStatusReceivedLocked(
-    void* arg, grpc_error* error) {
-  BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
-  GrpcLb* grpclb_policy = lb_calld->grpclb_policy();
-  GPR_ASSERT(lb_calld->lb_call_ != nullptr);
+    grpc_error* error) {
+  GPR_ASSERT(lb_call_ != nullptr);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
-    char* status_details =
-        grpc_slice_to_c_string(lb_calld->lb_call_status_details_);
+    char* status_details = grpc_slice_to_c_string(lb_call_status_details_);
     gpr_log(GPR_INFO,
             "[grpclb %p] lb_calld=%p: Status from LB server received. "
             "Status = %d, details = '%s', (lb_call: %p), error '%s'",
-            grpclb_policy, lb_calld, lb_calld->lb_call_status_, status_details,
-            lb_calld->lb_call_, grpc_error_string(error));
+            grpclb_policy(), this, lb_call_status_, status_details, lb_call_,
+            grpc_error_string(error));
     gpr_free(status_details);
   }
+  GRPC_ERROR_UNREF(error);
   // If this lb_calld is still in use, this call ended because of a failure so
   // we want to retry connecting. Otherwise, we have deliberately ended this
   // call and no further action is required.
-  if (lb_calld == grpclb_policy->lb_calld_.get()) {
+  if (this == grpclb_policy()->lb_calld_.get()) {
     // If the fallback-at-startup checks are pending, go into fallback mode
     // immediately.  This short-circuits the timeout for the fallback-at-startup
     // case.
-    if (grpclb_policy->fallback_at_startup_checks_pending_) {
-      GPR_ASSERT(!lb_calld->seen_serverlist_);
+    if (grpclb_policy()->fallback_at_startup_checks_pending_) {
+      GPR_ASSERT(!seen_serverlist_);
       gpr_log(GPR_INFO,
               "[grpclb %p] Balancer call finished without receiving "
               "serverlist; entering fallback mode",
-              grpclb_policy);
-      grpclb_policy->fallback_at_startup_checks_pending_ = false;
-      grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_);
-      grpclb_policy->CancelBalancerChannelConnectivityWatchLocked();
-      grpclb_policy->fallback_mode_ = true;
-      grpclb_policy->CreateOrUpdateChildPolicyLocked();
+              grpclb_policy());
+      grpclb_policy()->fallback_at_startup_checks_pending_ = false;
+      grpc_timer_cancel(&grpclb_policy()->lb_fallback_timer_);
+      grpclb_policy()->CancelBalancerChannelConnectivityWatchLocked();
+      grpclb_policy()->fallback_mode_ = true;
+      grpclb_policy()->CreateOrUpdateChildPolicyLocked();
     } else {
       // This handles the fallback-after-startup case.
-      grpclb_policy->MaybeEnterFallbackModeAfterStartup();
+      grpclb_policy()->MaybeEnterFallbackModeAfterStartup();
     }
-    grpclb_policy->lb_calld_.reset();
-    GPR_ASSERT(!grpclb_policy->shutting_down_);
-    grpclb_policy->channel_control_helper()->RequestReresolution();
-    if (lb_calld->seen_initial_response_) {
+    grpclb_policy()->lb_calld_.reset();
+    GPR_ASSERT(!grpclb_policy()->shutting_down_);
+    grpclb_policy()->channel_control_helper()->RequestReresolution();
+    if (seen_initial_response_) {
       // If we lose connection to the LB server, reset the backoff and restart
       // the LB call immediately.
-      grpclb_policy->lb_call_backoff_.Reset();
-      grpclb_policy->StartBalancerCallLocked();
+      grpclb_policy()->lb_call_backoff_.Reset();
+      grpclb_policy()->StartBalancerCallLocked();
     } else {
       // If this LB call fails establishing any connection to the LB server,
       // retry later.
-      grpclb_policy->StartBalancerCallRetryTimerLocked();
+      grpclb_policy()->StartBalancerCallRetryTimerLocked();
     }
   }
-  lb_calld->Unref(DEBUG_LOCATION, "lb_call_ended");
+  Unref(DEBUG_LOCATION, "lb_call_ended");
 }
 
 //
@@ -1290,7 +1271,7 @@ grpc_channel_args* BuildBalancerChannelArgs(
       GRPC_ARG_CHANNELZ_CHANNEL_NODE,
   };
   // Channel args to add.
-  InlinedVector<grpc_arg, 3> args_to_add;
+  absl::InlinedVector<grpc_arg, 3> args_to_add;
   // The fake resolver response generator, which we use to inject
   // address updates into the LB channel.
   args_to_add.emplace_back(
@@ -1332,6 +1313,11 @@ GrpcLb::GrpcLb(Args args)
               .set_jitter(GRPC_GRPCLB_RECONNECT_JITTER)
               .set_max_backoff(GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS *
                                1000)) {
+  // Closure Initialization
+  GRPC_CLOSURE_INIT(&lb_on_fallback_, &GrpcLb::OnFallbackTimer, this,
+                    grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&lb_on_call_retry_, &GrpcLb::OnBalancerCallRetryTimer, this,
+                    grpc_schedule_on_exec_ctx);
   // Record server name.
   const grpc_arg* arg = grpc_channel_args_find(args.args, GRPC_ARG_SERVER_URI);
   const char* server_uri = grpc_channel_arg_get_string(arg);
@@ -1416,8 +1402,6 @@ void GrpcLb::UpdateLocked(UpdateArgs args) {
     // Start timer.
     grpc_millis deadline = ExecCtx::Get()->Now() + fallback_at_startup_timeout_;
     Ref(DEBUG_LOCATION, "on_fallback_timer").release();  // Ref for callback
-    GRPC_CLOSURE_INIT(&lb_on_fallback_, &GrpcLb::OnFallbackTimer, this,
-                      grpc_schedule_on_exec_ctx);
     grpc_timer_init(&lb_fallback_timer_, deadline, &lb_on_fallback_);
     // Start watching the channel's connectivity state.  If the channel
     // goes into state TRANSIENT_FAILURE before the timer fires, we go into
@@ -1529,33 +1513,30 @@ void GrpcLb::StartBalancerCallRetryTimerLocked() {
   // with the callback.
   auto self = Ref(DEBUG_LOCATION, "on_balancer_call_retry_timer");
   self.release();
-  GRPC_CLOSURE_INIT(&lb_on_call_retry_, &GrpcLb::OnBalancerCallRetryTimer, this,
-                    grpc_schedule_on_exec_ctx);
   retry_timer_callback_pending_ = true;
   grpc_timer_init(&lb_call_retry_timer_, next_try, &lb_on_call_retry_);
 }
 
 void GrpcLb::OnBalancerCallRetryTimer(void* arg, grpc_error* error) {
   GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
-  grpclb_policy->combiner()->Run(
-      GRPC_CLOSURE_INIT(&grpclb_policy->lb_on_call_retry_,
-                        &GrpcLb::OnBalancerCallRetryTimerLocked, grpclb_policy,
-                        nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  grpclb_policy->work_serializer()->Run(
+      [grpclb_policy, error]() {
+        grpclb_policy->OnBalancerCallRetryTimerLocked(error);
+      },
+      DEBUG_LOCATION);
 }
 
-void GrpcLb::OnBalancerCallRetryTimerLocked(void* arg, grpc_error* error) {
-  GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
-  grpclb_policy->retry_timer_callback_pending_ = false;
-  if (!grpclb_policy->shutting_down_ && error == GRPC_ERROR_NONE &&
-      grpclb_policy->lb_calld_ == nullptr) {
+void GrpcLb::OnBalancerCallRetryTimerLocked(grpc_error* error) {
+  retry_timer_callback_pending_ = false;
+  if (!shutting_down_ && error == GRPC_ERROR_NONE && lb_calld_ == nullptr) {
     if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
-      gpr_log(GPR_INFO, "[grpclb %p] Restarting call to LB server",
-              grpclb_policy);
+      gpr_log(GPR_INFO, "[grpclb %p] Restarting call to LB server", this);
     }
-    grpclb_policy->StartBalancerCallLocked();
+    StartBalancerCallLocked();
   }
-  grpclb_policy->Unref(DEBUG_LOCATION, "on_balancer_call_retry_timer");
+  Unref(DEBUG_LOCATION, "on_balancer_call_retry_timer");
+  GRPC_ERROR_UNREF(error);
 }
 
 //
@@ -1582,28 +1563,28 @@ void GrpcLb::MaybeEnterFallbackModeAfterStartup() {
 
 void GrpcLb::OnFallbackTimer(void* arg, grpc_error* error) {
   GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
-  grpclb_policy->combiner()->Run(
-      GRPC_CLOSURE_INIT(&grpclb_policy->lb_on_fallback_,
-                        &GrpcLb::OnFallbackTimerLocked, grpclb_policy, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  grpclb_policy->work_serializer()->Run(
+      [grpclb_policy, error]() { grpclb_policy->OnFallbackTimerLocked(error); },
+      DEBUG_LOCATION);
 }
 
-void GrpcLb::OnFallbackTimerLocked(void* arg, grpc_error* error) {
-  GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
+void GrpcLb::OnFallbackTimerLocked(grpc_error* error) {
   // If we receive a serverlist after the timer fires but before this callback
   // actually runs, don't fall back.
-  if (grpclb_policy->fallback_at_startup_checks_pending_ &&
-      !grpclb_policy->shutting_down_ && error == GRPC_ERROR_NONE) {
+  if (fallback_at_startup_checks_pending_ && !shutting_down_ &&
+      error == GRPC_ERROR_NONE) {
     gpr_log(GPR_INFO,
             "[grpclb %p] No response from balancer after fallback timeout; "
             "entering fallback mode",
-            grpclb_policy);
-    grpclb_policy->fallback_at_startup_checks_pending_ = false;
-    grpclb_policy->CancelBalancerChannelConnectivityWatchLocked();
-    grpclb_policy->fallback_mode_ = true;
-    grpclb_policy->CreateOrUpdateChildPolicyLocked();
+            this);
+    fallback_at_startup_checks_pending_ = false;
+    CancelBalancerChannelConnectivityWatchLocked();
+    fallback_mode_ = true;
+    CreateOrUpdateChildPolicyLocked();
   }
-  grpclb_policy->Unref(DEBUG_LOCATION, "on_fallback_timer");
+  Unref(DEBUG_LOCATION, "on_fallback_timer");
+  GRPC_ERROR_UNREF(error);
 }
 
 //
@@ -1612,7 +1593,7 @@ void GrpcLb::OnFallbackTimerLocked(void* arg, grpc_error* error) {
 
 grpc_channel_args* GrpcLb::CreateChildPolicyArgsLocked(
     bool is_backend_from_grpclb_load_balancer) {
-  InlinedVector<grpc_arg, 2> args_to_add;
+  absl::InlinedVector<grpc_arg, 2> args_to_add;
   args_to_add.emplace_back(grpc_channel_arg_integer_create(
       const_cast<char*>(GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER),
       is_backend_from_grpclb_load_balancer));
@@ -1627,7 +1608,7 @@ grpc_channel_args* GrpcLb::CreateChildPolicyArgsLocked(
 OrphanablePtr<LoadBalancingPolicy> GrpcLb::CreateChildPolicyLocked(
     const grpc_channel_args* args) {
   LoadBalancingPolicy::Args lb_policy_args;
-  lb_policy_args.combiner = combiner();
+  lb_policy_args.work_serializer = work_serializer();
   lb_policy_args.args = args;
   lb_policy_args.channel_control_helper = absl::make_unique<Helper>(Ref());
   OrphanablePtr<LoadBalancingPolicy> lb_policy =
index 414f827..ab179d3 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <string.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
@@ -51,11 +53,10 @@ RefCountedPtr<TargetAuthorityTable> CreateTargetAuthorityTable(
       static_cast<TargetAuthorityTable::Entry*>(
           gpr_zalloc(sizeof(*target_authority_entries) * addresses.size()));
   for (size_t i = 0; i < addresses.size(); ++i) {
-    char* addr_str;
-    GPR_ASSERT(
-        grpc_sockaddr_to_string(&addr_str, &addresses[i].address(), true) > 0);
-    target_authority_entries[i].key = grpc_slice_from_copied_string(addr_str);
-    gpr_free(addr_str);
+    std::string addr_str =
+        grpc_sockaddr_to_string(&addresses[i].address(), true);
+    target_authority_entries[i].key =
+        grpc_slice_from_copied_string(addr_str.c_str());
     const char* balancer_name =
         FindGrpclbBalancerNameInChannelArgs(*addresses[i].args());
     target_authority_entries[i].value.reset(gpr_strdup(balancer_name));
@@ -71,8 +72,8 @@ RefCountedPtr<TargetAuthorityTable> CreateTargetAuthorityTable(
 
 grpc_channel_args* ModifyGrpclbBalancerChannelArgs(
     const ServerAddressList& addresses, grpc_channel_args* args) {
-  InlinedVector<const char*, 1> args_to_remove;
-  InlinedVector<grpc_arg, 2> args_to_add;
+  absl::InlinedVector<const char*, 1> args_to_remove;
+  absl::InlinedVector<grpc_arg, 2> args_to_add;
   // Add arg for targets info table.
   RefCountedPtr<TargetAuthorityTable> target_authority_table =
       CreateTargetAuthorityTable(addresses);
index 4b1c004..f6e9440 100644 (file)
@@ -23,7 +23,8 @@
 
 #include <grpc/support/atm.h>
 
-#include "src/core/lib/gprpp/inlined_vector.h"
+#include "absl/container/inlined_vector.h"
+
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/sync.h"
@@ -40,7 +41,7 @@ class GrpcLbClientStats : public RefCounted<GrpcLbClientStats> {
         : token(std::move(token)), count(count) {}
   };
 
-  typedef InlinedVector<DropTokenCount, 10> DroppedCallCounts;
+  typedef absl::InlinedVector<DropTokenCount, 10> DroppedCallCounts;
 
   void AddCallStarted();
   void AddCallFinished(bool finished_with_client_failed_to_send,
index ff69112..19fc45f 100644 (file)
@@ -31,8 +31,8 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 
 namespace grpc_core {
 
@@ -152,7 +152,8 @@ class PriorityLb : public LoadBalancingPolicy {
       void UpdateState(grpc_connectivity_state state,
                        std::unique_ptr<SubchannelPicker> picker) override;
       void RequestReresolution() override;
-      void AddTraceEvent(TraceSeverity severity, StringView message) override;
+      void AddTraceEvent(TraceSeverity severity,
+                         absl::string_view message) override;
 
      private:
       RefCountedPtr<ChildPriority> priority_;
@@ -169,9 +170,9 @@ class PriorityLb : public LoadBalancingPolicy {
     void StartFailoverTimerLocked();
 
     static void OnFailoverTimer(void* arg, grpc_error* error);
-    static void OnFailoverTimerLocked(void* arg, grpc_error* error);
+    void OnFailoverTimerLocked(grpc_error* error);
     static void OnDeactivationTimer(void* arg, grpc_error* error);
-    static void OnDeactivationTimerLocked(void* arg, grpc_error* error);
+    void OnDeactivationTimerLocked(grpc_error* error);
 
     RefCountedPtr<PriorityLb> priority_policy_;
     const std::string name_;
@@ -189,7 +190,6 @@ class PriorityLb : public LoadBalancingPolicy {
     // States of failover.
     grpc_timer failover_timer_;
     grpc_closure on_failover_timer_;
-    grpc_closure on_failover_timer_locked_;
     bool failover_timer_callback_pending_ = false;
   };
 
@@ -492,8 +492,8 @@ PriorityLb::ChildPriority::ChildPriority(
   }
   GRPC_CLOSURE_INIT(&on_failover_timer_, OnFailoverTimer, this,
                     grpc_schedule_on_exec_ctx);
-  GRPC_CLOSURE_INIT(&on_failover_timer_locked_, OnFailoverTimerLocked, this,
-                    nullptr);
+  GRPC_CLOSURE_INIT(&on_deactivation_timer_, OnDeactivationTimer, this,
+                    grpc_schedule_on_exec_ctx);
   // Start the failover timer.
   StartFailoverTimerLocked();
 }
@@ -550,7 +550,7 @@ OrphanablePtr<LoadBalancingPolicy>
 PriorityLb::ChildPriority::CreateChildPolicyLocked(
     const grpc_channel_args* args) {
   LoadBalancingPolicy::Args lb_policy_args;
-  lb_policy_args.combiner = priority_policy_->combiner();
+  lb_policy_args.work_serializer = priority_policy_->work_serializer();
   lb_policy_args.args = args;
   lb_policy_args.channel_control_helper =
       absl::make_unique<Helper>(this->Ref(DEBUG_LOCATION, "Helper"));
@@ -631,26 +631,25 @@ void PriorityLb::ChildPriority::MaybeCancelFailoverTimerLocked() {
 
 void PriorityLb::ChildPriority::OnFailoverTimer(void* arg, grpc_error* error) {
   ChildPriority* self = static_cast<ChildPriority*>(arg);
-  self->priority_policy_->combiner()->Run(&self->on_failover_timer_locked_,
-                                          GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  self->priority_policy_->work_serializer()->Run(
+      [self, error]() { self->OnFailoverTimerLocked(error); }, DEBUG_LOCATION);
 }
 
-void PriorityLb::ChildPriority::OnFailoverTimerLocked(void* arg,
-                                                      grpc_error* error) {
-  ChildPriority* self = static_cast<ChildPriority*>(arg);
-  if (error == GRPC_ERROR_NONE && self->failover_timer_callback_pending_ &&
-      !self->priority_policy_->shutting_down_) {
+void PriorityLb::ChildPriority::OnFailoverTimerLocked(grpc_error* error) {
+  if (error == GRPC_ERROR_NONE && failover_timer_callback_pending_ &&
+      !priority_policy_->shutting_down_) {
     if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) {
       gpr_log(GPR_INFO,
               "[priority_lb %p] child %s (%p): failover timer fired, "
               "reporting TRANSIENT_FAILURE",
-              self->priority_policy_.get(), self->name_.c_str(), self);
+              priority_policy_.get(), name_.c_str(), this);
     }
-    self->failover_timer_callback_pending_ = false;
-    self->OnConnectivityStateUpdateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                          nullptr);
+    failover_timer_callback_pending_ = false;
+    OnConnectivityStateUpdateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, nullptr);
   }
-  self->Unref(DEBUG_LOCATION, "ChildPriority+OnFailoverTimerLocked");
+  Unref(DEBUG_LOCATION, "ChildPriority+OnFailoverTimerLocked");
+  GRPC_ERROR_UNREF(error);
 }
 
 void PriorityLb::ChildPriority::DeactivateLocked() {
@@ -666,8 +665,6 @@ void PriorityLb::ChildPriority::DeactivateLocked() {
   MaybeCancelFailoverTimerLocked();
   // Start a timer to delete the child.
   Ref(DEBUG_LOCATION, "ChildPriority+timer").release();
-  GRPC_CLOSURE_INIT(&on_deactivation_timer_, OnDeactivationTimer, this,
-                    grpc_schedule_on_exec_ctx);
   grpc_timer_init(&deactivation_timer_,
                   ExecCtx::Get()->Now() + kChildRetentionIntervalMs,
                   &on_deactivation_timer_);
@@ -688,27 +685,26 @@ void PriorityLb::ChildPriority::MaybeReactivateLocked() {
 void PriorityLb::ChildPriority::OnDeactivationTimer(void* arg,
                                                     grpc_error* error) {
   ChildPriority* self = static_cast<ChildPriority*>(arg);
-  self->priority_policy_->combiner()->Run(
-      GRPC_CLOSURE_INIT(&self->on_deactivation_timer_,
-                        OnDeactivationTimerLocked, self, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  self->priority_policy_->work_serializer()->Run(
+      [self, error]() { self->OnDeactivationTimerLocked(error); },
+      DEBUG_LOCATION);
 }
 
-void PriorityLb::ChildPriority::OnDeactivationTimerLocked(void* arg,
-                                                          grpc_error* error) {
-  ChildPriority* self = static_cast<ChildPriority*>(arg);
-  if (error == GRPC_ERROR_NONE && self->deactivation_timer_callback_pending_ &&
-      !self->priority_policy_->shutting_down_) {
+void PriorityLb::ChildPriority::OnDeactivationTimerLocked(grpc_error* error) {
+  if (error == GRPC_ERROR_NONE && deactivation_timer_callback_pending_ &&
+      !priority_policy_->shutting_down_) {
     if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) {
       gpr_log(GPR_INFO,
               "[priority_lb %p] child %s (%p): deactivation timer fired, "
               "deleting child",
-              self->priority_policy_.get(), self->name_.c_str(), self);
+              priority_policy_.get(), name_.c_str(), this);
     }
-    self->deactivation_timer_callback_pending_ = false;
-    self->priority_policy_->DeleteChild(self);
+    deactivation_timer_callback_pending_ = false;
+    priority_policy_->DeleteChild(this);
   }
-  self->Unref(DEBUG_LOCATION, "ChildPriority+timer");
+  Unref(DEBUG_LOCATION, "ChildPriority+timer");
+  GRPC_ERROR_UNREF(error);
 }
 
 //
@@ -735,8 +731,8 @@ void PriorityLb::ChildPriority::Helper::UpdateState(
   priority_->OnConnectivityStateUpdateLocked(state, std::move(picker));
 }
 
-void PriorityLb::ChildPriority::Helper::AddTraceEvent(TraceSeverity severity,
-                                                      StringView message) {
+void PriorityLb::ChildPriority::Helper::AddTraceEvent(
+    TraceSeverity severity, absl::string_view message) {
   if (priority_->priority_policy_->shutting_down_) return;
   priority_->priority_policy_->channel_control_helper()->AddTraceEvent(severity,
                                                                        message);
index a5ab488..56b71b6 100644 (file)
@@ -160,7 +160,7 @@ class RoundRobin : public LoadBalancingPolicy {
     RoundRobin* parent_;
 
     size_t last_picked_index_;
-    InlinedVector<RefCountedPtr<SubchannelInterface>, 10> subchannels_;
+    absl::InlinedVector<RefCountedPtr<SubchannelInterface>, 10> subchannels_;
   };
 
   void ShutdownLocked() override;
index 2d89889..93c5deb 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <grpc/support/alloc.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
 #include "src/core/ext/filters/client_channel/server_address.h"
 // TODO(roth): Should not need the include of subchannel.h here, since
@@ -33,7 +35,6 @@
 #include "src/core/ext/filters/client_channel/subchannel_interface.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/debug/trace.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
@@ -62,7 +63,7 @@ class MySubchannelList
 };
 
 */
-// All methods will be called from within the client_channel combiner.
+// All methods will be called from within the client_channel work serializer.
 
 namespace grpc_core {
 
@@ -172,7 +173,7 @@ class SubchannelData {
 template <typename SubchannelListType, typename SubchannelDataType>
 class SubchannelList : public InternallyRefCounted<SubchannelListType> {
  public:
-  typedef InlinedVector<SubchannelDataType, 10> SubchannelVector;
+  typedef absl::InlinedVector<SubchannelDataType, 10> SubchannelVector;
 
   // The number of subchannels in the list.
   size_t num_subchannels() const { return subchannels_.size(); }
@@ -370,7 +371,7 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
                                          GRPC_ARG_SERVICE_CONFIG};
   // Create a subchannel for each address.
   for (size_t i = 0; i < addresses.size(); i++) {
-    InlinedVector<grpc_arg, 3> args_to_add;
+    absl::InlinedVector<grpc_arg, 3> args_to_add;
     const size_t subchannel_address_arg_index = args_to_add.size();
     args_to_add.emplace_back(
         Subchannel::CreateSubchannelAddressArg(&addresses[i].address()));
index a319c40..96491b6 100644 (file)
@@ -20,6 +20,7 @@
 #include <limits.h>
 #include <string.h>
 
+#include "absl/container/inlined_vector.h"
 #include "absl/strings/str_cat.h"
 
 #include <grpc/grpc.h>
@@ -33,8 +34,8 @@
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 
 namespace grpc_core {
 
@@ -99,9 +100,8 @@ class WeightedTargetLb : public LoadBalancingPolicy {
     // ready state. The first element in the pair represents the end of a
     // range proportional to the child's weight. The start of the range
     // is the previous value in the vector and is 0 for the first element.
-    using PickerList =
-        InlinedVector<std::pair<uint32_t, RefCountedPtr<ChildPickerWrapper>>,
-                      1>;
+    using PickerList = absl::InlinedVector<
+        std::pair<uint32_t, RefCountedPtr<ChildPickerWrapper>>, 1>;
 
     explicit WeightedPicker(PickerList pickers)
         : pickers_(std::move(pickers)) {}
@@ -148,7 +148,8 @@ class WeightedTargetLb : public LoadBalancingPolicy {
       void UpdateState(grpc_connectivity_state state,
                        std::unique_ptr<SubchannelPicker> picker) override;
       void RequestReresolution() override;
-      void AddTraceEvent(TraceSeverity severity, StringView message) override;
+      void AddTraceEvent(TraceSeverity severity,
+                         absl::string_view message) override;
 
      private:
       RefCountedPtr<WeightedChild> weighted_child_;
@@ -163,7 +164,7 @@ class WeightedTargetLb : public LoadBalancingPolicy {
         std::unique_ptr<SubchannelPicker> picker);
 
     static void OnDelayedRemovalTimer(void* arg, grpc_error* error);
-    static void OnDelayedRemovalTimerLocked(void* arg, grpc_error* error);
+    void OnDelayedRemovalTimerLocked(grpc_error* error);
 
     // The owning LB policy.
     RefCountedPtr<WeightedTargetLb> weighted_target_policy_;
@@ -277,20 +278,31 @@ void WeightedTargetLb::UpdateLocked(UpdateArgs args) {
       child->DeactivateLocked();
     }
   }
-  // Add or update the targets in the new config.
-  HierarchicalAddressMap address_map =
-      MakeHierarchicalAddressMap(args.addresses);
+  // Create any children that don't already exist.
+  // Note that we add all children before updating any of them, because
+  // an update may trigger a child to immediately update its
+  // connectivity state (e.g., reporting TRANSIENT_FAILURE immediately when
+  // receiving an empty address list), and we don't want to return an
+  // overall state with incomplete data.
   for (const auto& p : config_->target_map()) {
     const std::string& name = p.first;
-    const WeightedTargetLbConfig::ChildConfig& config = p.second;
     auto it = targets_.find(name);
     if (it == targets_.end()) {
       it = targets_.emplace(std::make_pair(name, nullptr)).first;
       it->second = MakeOrphanable<WeightedChild>(
           Ref(DEBUG_LOCATION, "WeightedChild"), it->first);
     }
-    it->second->UpdateLocked(config, std::move(address_map[name]), args.args);
   }
+  // Update all children.
+  HierarchicalAddressMap address_map =
+      MakeHierarchicalAddressMap(args.addresses);
+  for (const auto& p : config_->target_map()) {
+    const std::string& name = p.first;
+    const WeightedTargetLbConfig::ChildConfig& config = p.second;
+    targets_[name]->UpdateLocked(config, std::move(address_map[name]),
+                                 args.args);
+  }
+  UpdateStateLocked();
 }
 
 void WeightedTargetLb::UpdateStateLocked() {
@@ -392,6 +404,8 @@ WeightedTargetLb::WeightedChild::WeightedChild(
     gpr_log(GPR_INFO, "[weighted_target_lb %p] created WeightedChild %p for %s",
             weighted_target_policy_.get(), this, name_.c_str());
   }
+  GRPC_CLOSURE_INIT(&on_delayed_removal_timer_, OnDelayedRemovalTimer, this,
+                    grpc_schedule_on_exec_ctx);
 }
 
 WeightedTargetLb::WeightedChild::~WeightedChild() {
@@ -430,7 +444,7 @@ OrphanablePtr<LoadBalancingPolicy>
 WeightedTargetLb::WeightedChild::CreateChildPolicyLocked(
     const grpc_channel_args* args) {
   LoadBalancingPolicy::Args lb_policy_args;
-  lb_policy_args.combiner = weighted_target_policy_->combiner();
+  lb_policy_args.work_serializer = weighted_target_policy_->work_serializer();
   lb_policy_args.args = args;
   lb_policy_args.channel_control_helper =
       absl::make_unique<Helper>(this->Ref(DEBUG_LOCATION, "Helper"));
@@ -536,8 +550,6 @@ void WeightedTargetLb::WeightedChild::DeactivateLocked() {
   weight_ = 0;
   // Start a timer to delete the child.
   Ref(DEBUG_LOCATION, "WeightedChild+timer").release();
-  GRPC_CLOSURE_INIT(&on_delayed_removal_timer_, OnDelayedRemovalTimer, this,
-                    grpc_schedule_on_exec_ctx);
   delayed_removal_timer_callback_pending_ = true;
   grpc_timer_init(&delayed_removal_timer_,
                   ExecCtx::Get()->Now() + kChildRetentionIntervalMs,
@@ -547,22 +559,21 @@ void WeightedTargetLb::WeightedChild::DeactivateLocked() {
 void WeightedTargetLb::WeightedChild::OnDelayedRemovalTimer(void* arg,
                                                             grpc_error* error) {
   WeightedChild* self = static_cast<WeightedChild*>(arg);
-  self->weighted_target_policy_->combiner()->Run(
-      GRPC_CLOSURE_INIT(&self->on_delayed_removal_timer_,
-                        OnDelayedRemovalTimerLocked, self, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  self->weighted_target_policy_->work_serializer()->Run(
+      [self, error]() { self->OnDelayedRemovalTimerLocked(error); },
+      DEBUG_LOCATION);
 }
 
 void WeightedTargetLb::WeightedChild::OnDelayedRemovalTimerLocked(
-    void* arg, grpc_error* error) {
-  WeightedChild* self = static_cast<WeightedChild*>(arg);
-  if (error == GRPC_ERROR_NONE &&
-      self->delayed_removal_timer_callback_pending_ && !self->shutdown_ &&
-      self->weight_ == 0) {
-    self->delayed_removal_timer_callback_pending_ = false;
-    self->weighted_target_policy_->targets_.erase(self->name_);
+    grpc_error* error) {
+  if (error == GRPC_ERROR_NONE && delayed_removal_timer_callback_pending_ &&
+      !shutdown_ && weight_ == 0) {
+    delayed_removal_timer_callback_pending_ = false;
+    weighted_target_policy_->targets_.erase(name_);
   }
-  self->Unref(DEBUG_LOCATION, "WeightedChild+timer");
+  Unref(DEBUG_LOCATION, "WeightedChild+timer");
+  GRPC_ERROR_UNREF(error);
 }
 
 //
@@ -590,7 +601,7 @@ void WeightedTargetLb::WeightedChild::Helper::RequestReresolution() {
 }
 
 void WeightedTargetLb::WeightedChild::Helper::AddTraceEvent(
-    TraceSeverity severity, StringView message) {
+    TraceSeverity severity, absl::string_view message) {
   if (weighted_child_->weighted_target_policy_->shutting_down_) return;
   weighted_child_->weighted_target_policy_->channel_control_helper()
       ->AddTraceEvent(severity, message);
@@ -676,14 +687,15 @@ class WeightedTargetLbFactory : public LoadBalancingPolicyFactory {
       error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
           "field:weight error:must be of type number"));
     } else {
-      child_config->weight =
-          gpr_parse_nonnegative_int(it->second.string_value().c_str());
-      if (child_config->weight == -1) {
+      int weight = gpr_parse_nonnegative_int(it->second.string_value().c_str());
+      if (weight == -1) {
         error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
             "field:weight error:unparseable value"));
-      } else if (child_config->weight == 0) {
+      } else if (weight == 0) {
         error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
             "field:weight error:value must be greater than zero"));
+      } else {
+        child_config->weight = weight;
       }
     }
     // Child policy.
index 29f571d..500f1ac 100644 (file)
@@ -18,6 +18,8 @@
 
 #include <string.h>
 
+#include "absl/strings/str_cat.h"
+
 #include "src/core/ext/filters/client_channel/lb_policy.h"
 #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
 #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
@@ -65,6 +67,7 @@ class CdsLb : public LoadBalancingPolicy {
         : parent_(std::move(parent)) {}
     void OnClusterChanged(XdsApi::CdsUpdate cluster_data) override;
     void OnError(grpc_error* error) override;
+    void OnResourceDoesNotExist() override;
 
    private:
     RefCountedPtr<CdsLb> parent_;
@@ -79,7 +82,8 @@ class CdsLb : public LoadBalancingPolicy {
     void UpdateState(grpc_connectivity_state state,
                      std::unique_ptr<SubchannelPicker> picker) override;
     void RequestReresolution() override;
-    void AddTraceEvent(TraceSeverity severity, StringView message) override;
+    void AddTraceEvent(TraceSeverity severity,
+                       absl::string_view message) override;
 
    private:
     RefCountedPtr<CdsLb> parent_;
@@ -89,6 +93,8 @@ class CdsLb : public LoadBalancingPolicy {
 
   void ShutdownLocked() override;
 
+  void MaybeDestroyChildPolicyLocked();
+
   RefCountedPtr<CdsLbConfig> config_;
 
   // Current channel args from the resolver.
@@ -168,7 +174,7 @@ void CdsLb::ClusterWatcher::OnClusterChanged(XdsApi::CdsUpdate cluster_data) {
   // Create child policy if not already present.
   if (parent_->child_policy_ == nullptr) {
     LoadBalancingPolicy::Args args;
-    args.combiner = parent_->combiner();
+    args.work_serializer = parent_->work_serializer();
     args.args = parent_->args_;
     args.channel_control_helper = absl::make_unique<Helper>(parent_->Ref());
     parent_->child_policy_ =
@@ -210,6 +216,21 @@ void CdsLb::ClusterWatcher::OnError(grpc_error* error) {
   }
 }
 
+void CdsLb::ClusterWatcher::OnResourceDoesNotExist() {
+  gpr_log(GPR_ERROR,
+          "[cdslb %p] CDS resource for %s does not exist -- reporting "
+          "TRANSIENT_FAILURE",
+          parent_.get(), parent_->config_->cluster().c_str());
+  parent_->channel_control_helper()->UpdateState(
+      GRPC_CHANNEL_TRANSIENT_FAILURE,
+      absl::make_unique<TransientFailurePicker>(
+          GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+              absl::StrCat("CDS resource \"", parent_->config_->cluster(),
+                           "\" does not exist")
+                  .c_str())));
+  parent_->MaybeDestroyChildPolicyLocked();
+}
+
 //
 // CdsLb::Helper
 //
@@ -222,7 +243,7 @@ RefCountedPtr<SubchannelInterface> CdsLb::Helper::CreateSubchannel(
 
 void CdsLb::Helper::UpdateState(grpc_connectivity_state state,
                                 std::unique_ptr<SubchannelPicker> picker) {
-  if (parent_->shutting_down_) return;
+  if (parent_->shutting_down_ || parent_->child_policy_ == nullptr) return;
   if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
     gpr_log(GPR_INFO, "[cdslb %p] state updated by child: %s", this,
             ConnectivityStateName(state));
@@ -239,7 +260,8 @@ void CdsLb::Helper::RequestReresolution() {
   parent_->channel_control_helper()->RequestReresolution();
 }
 
-void CdsLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
+void CdsLb::Helper::AddTraceEvent(TraceSeverity severity,
+                                  absl::string_view message) {
   if (parent_->shutting_down_) return;
   parent_->channel_control_helper()->AddTraceEvent(severity, message);
 }
@@ -268,24 +290,27 @@ void CdsLb::ShutdownLocked() {
     gpr_log(GPR_INFO, "[cdslb %p] shutting down", this);
   }
   shutting_down_ = true;
-  if (child_policy_ != nullptr) {
-    grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
-                                     interested_parties());
-    child_policy_.reset();
-  }
+  MaybeDestroyChildPolicyLocked();
   if (xds_client_ != nullptr) {
     if (cluster_watcher_ != nullptr) {
       if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
         gpr_log(GPR_INFO, "[cdslb %p] cancelling watch for cluster %s", this,
                 config_->cluster().c_str());
       }
-      xds_client_->CancelClusterDataWatch(
-          StringView(config_->cluster().c_str()), cluster_watcher_);
+      xds_client_->CancelClusterDataWatch(config_->cluster(), cluster_watcher_);
     }
     xds_client_.reset();
   }
 }
 
+void CdsLb::MaybeDestroyChildPolicyLocked() {
+  if (child_policy_ != nullptr) {
+    grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
+                                     interested_parties());
+    child_policy_.reset();
+  }
+}
+
 void CdsLb::ResetBackoffLocked() {
   if (child_policy_ != nullptr) child_policy_->ResetBackoffLocked();
 }
@@ -309,9 +334,9 @@ void CdsLb::UpdateLocked(UpdateArgs args) {
         gpr_log(GPR_INFO, "[cdslb %p] cancelling watch for cluster %s", this,
                 old_config->cluster().c_str());
       }
-      xds_client_->CancelClusterDataWatch(
-          StringView(old_config->cluster().c_str()), cluster_watcher_,
-          /*delay_unsubscription=*/true);
+      xds_client_->CancelClusterDataWatch(old_config->cluster(),
+                                          cluster_watcher_,
+                                          /*delay_unsubscription=*/true);
     }
     if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
       gpr_log(GPR_INFO, "[cdslb %p] starting watch for cluster %s", this,
@@ -319,8 +344,7 @@ void CdsLb::UpdateLocked(UpdateArgs args) {
     }
     auto watcher = absl::make_unique<ClusterWatcher>(Ref());
     cluster_watcher_ = watcher.get();
-    xds_client_->WatchClusterData(StringView(config_->cluster().c_str()),
-                                  std::move(watcher));
+    xds_client_->WatchClusterData(config_->cluster(), std::move(watcher));
   }
 }
 
index 8351d74..c1bbf74 100644 (file)
 #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
 #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
 #include "src/core/ext/filters/client_channel/server_address.h"
+#include "src/core/ext/filters/client_channel/xds/xds_channel_args.h"
 #include "src/core/ext/filters/client_channel/xds/xds_client.h"
 #include "src/core/ext/filters/client_channel/xds/xds_client_stats.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "src/core/lib/uri/uri_parser.h"
 
 #define GRPC_EDS_DEFAULT_FALLBACK_TIMEOUT 10000
@@ -137,7 +138,8 @@ class EdsLb : public LoadBalancingPolicy {
     // This is a no-op, because we get the addresses from the xds
     // client, which is a watch-based API.
     void RequestReresolution() override {}
-    void AddTraceEvent(TraceSeverity severity, StringView message) override;
+    void AddTraceEvent(TraceSeverity severity,
+                       absl::string_view message) override;
 
    private:
     RefCountedPtr<EdsLb> eds_policy_;
@@ -147,6 +149,8 @@ class EdsLb : public LoadBalancingPolicy {
 
   void ShutdownLocked() override;
 
+  void MaybeDestroyChildPolicyLocked();
+
   void UpdatePriorityList(XdsApi::PriorityListUpdate priority_list_update);
   void UpdateChildPolicyLocked();
   OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
@@ -158,7 +162,7 @@ class EdsLb : public LoadBalancingPolicy {
   void MaybeUpdateDropPickerLocked();
 
   // Caller must ensure that config_ is set before calling.
-  const StringView GetEdsResourceName() const {
+  const absl::string_view GetEdsResourceName() const {
     if (xds_client_from_channel_ == nullptr) return server_name_;
     if (!config_->eds_service_name().empty()) {
       return config_->eds_service_name();
@@ -169,7 +173,7 @@ class EdsLb : public LoadBalancingPolicy {
   // Returns a pair containing the cluster and eds_service_name to use
   // for LRS load reporting.
   // Caller must ensure that config_ is set before calling.
-  std::pair<StringView, StringView> GetLrsClusterKey() const {
+  std::pair<absl::string_view, absl::string_view> GetLrsClusterKey() const {
     if (xds_client_from_channel_ == nullptr) return {server_name_, nullptr};
     return {config_->cluster_name(), config_->eds_service_name()};
   }
@@ -262,7 +266,9 @@ RefCountedPtr<SubchannelInterface> EdsLb::Helper::CreateSubchannel(
 
 void EdsLb::Helper::UpdateState(grpc_connectivity_state state,
                                 std::unique_ptr<SubchannelPicker> picker) {
-  if (eds_policy_->shutting_down_) return;
+  if (eds_policy_->shutting_down_ || eds_policy_->child_policy_ == nullptr) {
+    return;
+  }
   if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
     gpr_log(GPR_INFO, "[edslb %p] child policy updated state=%s picker=%p",
             eds_policy_.get(), ConnectivityStateName(state), picker.get());
@@ -275,7 +281,8 @@ void EdsLb::Helper::UpdateState(grpc_connectivity_state state,
   eds_policy_->MaybeUpdateDropPickerLocked();
 }
 
-void EdsLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
+void EdsLb::Helper::AddTraceEvent(TraceSeverity severity,
+                                  absl::string_view message) {
   if (eds_policy_->shutting_down_) return;
   eds_policy_->channel_control_helper()->AddTraceEvent(severity, message);
 }
@@ -339,6 +346,19 @@ class EdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
     }
   }
 
+  void OnResourceDoesNotExist() override {
+    gpr_log(
+        GPR_ERROR,
+        "[edslb %p] EDS resource does not exist -- reporting TRANSIENT_FAILURE",
+        eds_policy_.get());
+    eds_policy_->channel_control_helper()->UpdateState(
+        GRPC_CHANNEL_TRANSIENT_FAILURE,
+        absl::make_unique<TransientFailurePicker>(
+            GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                "EDS resource does not exist")));
+    eds_policy_->MaybeDestroyChildPolicyLocked();
+  }
+
  private:
   RefCountedPtr<EdsLb> eds_policy_;
 };
@@ -383,11 +403,7 @@ void EdsLb::ShutdownLocked() {
   // Drop our ref to the child's picker, in case it's holding a ref to
   // the child.
   child_picker_.reset();
-  if (child_policy_ != nullptr) {
-    grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
-                                     interested_parties());
-    child_policy_.reset();
-  }
+  MaybeDestroyChildPolicyLocked();
   drop_stats_.reset();
   // Cancel the endpoint watch here instead of in our dtor if we are using the
   // xds resolver, because the watcher holds a ref to us and we might not be
@@ -407,6 +423,14 @@ void EdsLb::ShutdownLocked() {
   xds_client_.reset();
 }
 
+void EdsLb::MaybeDestroyChildPolicyLocked() {
+  if (child_policy_ != nullptr) {
+    grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
+                                     interested_parties());
+    child_policy_.reset();
+  }
+}
+
 void EdsLb::UpdateLocked(UpdateArgs args) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
     gpr_log(GPR_INFO, "[edslb %p] Received update", this);
@@ -424,7 +448,7 @@ void EdsLb::UpdateLocked(UpdateArgs args) {
     if (xds_client_from_channel_ == nullptr) {
       grpc_error* error = GRPC_ERROR_NONE;
       xds_client_ = MakeOrphanable<XdsClient>(
-          combiner(), interested_parties(), GetEdsResourceName(),
+          work_serializer(), interested_parties(), GetEdsResourceName(),
           nullptr /* service config watcher */, *args_, &error);
       // TODO(roth): If we decide that we care about EDS-only mode, add
       // proper error handling here.
@@ -701,17 +725,24 @@ grpc_channel_args* EdsLb::CreateChildPolicyArgsLocked(
       grpc_channel_arg_integer_create(
           const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1),
   };
+  absl::InlinedVector<const char*, 1> args_to_remove;
   if (xds_client_from_channel_ == nullptr) {
     args_to_add.emplace_back(xds_client_->MakeChannelArg());
-  }
-  return grpc_channel_args_copy_and_add(args, args_to_add.data(),
-                                        args_to_add.size());
+  } else if (!config_->lrs_load_reporting_server_name().has_value()) {
+    // Remove XdsClient from channel args, so that its presence doesn't
+    // prevent us from sharing subchannels between channels.
+    // If load reporting is enabled, this happens in the LRS policy instead.
+    args_to_remove.push_back(GRPC_ARG_XDS_CLIENT);
+  }
+  return grpc_channel_args_copy_and_add_and_remove(
+      args, args_to_remove.data(), args_to_remove.size(), args_to_add.data(),
+      args_to_add.size());
 }
 
 OrphanablePtr<LoadBalancingPolicy> EdsLb::CreateChildPolicyLocked(
     const grpc_channel_args* args) {
   LoadBalancingPolicy::Args lb_policy_args;
-  lb_policy_args.combiner = combiner();
+  lb_policy_args.work_serializer = work_serializer();
   lb_policy_args.args = args;
   lb_policy_args.channel_control_helper =
       absl::make_unique<Helper>(Ref(DEBUG_LOCATION, "Helper"));
index b91d1b3..0aca12d 100644 (file)
@@ -27,7 +27,7 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/iomgr/combiner.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 
 namespace grpc_core {
 
@@ -123,7 +123,8 @@ class LrsLb : public LoadBalancingPolicy {
     void UpdateState(grpc_connectivity_state state,
                      std::unique_ptr<SubchannelPicker> picker) override;
     void RequestReresolution() override;
-    void AddTraceEvent(TraceSeverity severity, StringView message) override;
+    void AddTraceEvent(TraceSeverity severity,
+                       absl::string_view message) override;
 
    private:
     RefCountedPtr<LrsLb> lrs_policy_;
@@ -176,7 +177,7 @@ LoadBalancingPolicy::PickResult LrsLb::LoadReportingPicker::Pick(
         locality_stats_->Ref(DEBUG_LOCATION, "LocalityStats+call").release();
     result.recv_trailing_metadata_ready =
         // Note: This callback does not run in either the control plane
-        // combiner or in the data plane mutex.
+        // work serializer or in the data plane mutex.
         [locality_stats](grpc_error* error, MetadataInterface* /*metadata*/,
                          CallState* /*call_state*/) {
           const bool call_failed = error != GRPC_ERROR_NONE;
@@ -253,9 +254,11 @@ void LrsLb::UpdateLocked(UpdateArgs args) {
         config_->eds_service_name(), config_->locality_name());
     MaybeUpdatePickerLocked();
   }
+  // Remove XdsClient from channel args, so that its presence doesn't
+  // prevent us from sharing subchannels between channels.
+  grpc_channel_args* new_args = XdsClient::RemoveFromChannelArgs(*args.args);
   // Update child policy.
-  UpdateChildPolicyLocked(std::move(args.addresses), args.args);
-  args.args = nullptr;  // Ownership passed to UpdateChildPolicyLocked().
+  UpdateChildPolicyLocked(std::move(args.addresses), new_args);
 }
 
 void LrsLb::MaybeUpdatePickerLocked() {
@@ -273,7 +276,7 @@ void LrsLb::MaybeUpdatePickerLocked() {
 OrphanablePtr<LoadBalancingPolicy> LrsLb::CreateChildPolicyLocked(
     const grpc_channel_args* args) {
   LoadBalancingPolicy::Args lb_policy_args;
-  lb_policy_args.combiner = combiner();
+  lb_policy_args.work_serializer = work_serializer();
   lb_policy_args.args = args;
   lb_policy_args.channel_control_helper =
       absl::make_unique<Helper>(Ref(DEBUG_LOCATION, "Helper"));
@@ -341,7 +344,8 @@ void LrsLb::Helper::RequestReresolution() {
   lrs_policy_->channel_control_helper()->RequestReresolution();
 }
 
-void LrsLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
+void LrsLb::Helper::AddTraceEvent(TraceSeverity severity,
+                                  absl::string_view message) {
   if (lrs_policy_->shutting_down_) return;
   lrs_policy_->channel_control_helper()->AddTraceEvent(severity, message);
 }
index 8cc5aa7..ea1007c 100644 (file)
@@ -34,8 +34,8 @@
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 
 #define GRPC_XDS_ROUTING_CHILD_RETENTION_INTERVAL_MS (15 * 60 * 1000)
 
@@ -161,7 +161,8 @@ class XdsRoutingLb : public LoadBalancingPolicy {
       void UpdateState(grpc_connectivity_state state,
                        std::unique_ptr<SubchannelPicker> picker) override;
       void RequestReresolution() override;
-      void AddTraceEvent(TraceSeverity severity, StringView message) override;
+      void AddTraceEvent(TraceSeverity severity,
+                         absl::string_view message) override;
 
      private:
       RefCountedPtr<XdsRoutingChild> xds_routing_child_;
@@ -172,7 +173,7 @@ class XdsRoutingLb : public LoadBalancingPolicy {
         const grpc_channel_args* args);
 
     static void OnDelayedRemovalTimer(void* arg, grpc_error* error);
-    static void OnDelayedRemovalTimerLocked(void* arg, grpc_error* error);
+    void OnDelayedRemovalTimerLocked(grpc_error* error);
 
     // The owning LB policy.
     RefCountedPtr<XdsRoutingLb> xds_routing_policy_;
@@ -400,6 +401,8 @@ XdsRoutingLb::XdsRoutingChild::XdsRoutingChild(
     gpr_log(GPR_INFO, "[xds_routing_lb %p] created XdsRoutingChild %p for %s",
             xds_routing_policy_.get(), this, name_.c_str());
   }
+  GRPC_CLOSURE_INIT(&on_delayed_removal_timer_, OnDelayedRemovalTimer, this,
+                    grpc_schedule_on_exec_ctx);
 }
 
 XdsRoutingLb::XdsRoutingChild::~XdsRoutingChild() {
@@ -436,7 +439,7 @@ OrphanablePtr<LoadBalancingPolicy>
 XdsRoutingLb::XdsRoutingChild::CreateChildPolicyLocked(
     const grpc_channel_args* args) {
   LoadBalancingPolicy::Args lb_policy_args;
-  lb_policy_args.combiner = xds_routing_policy_->combiner();
+  lb_policy_args.work_serializer = xds_routing_policy_->work_serializer();
   lb_policy_args.args = args;
   lb_policy_args.channel_control_helper =
       absl::make_unique<Helper>(this->Ref(DEBUG_LOCATION, "Helper"));
@@ -501,8 +504,6 @@ void XdsRoutingLb::XdsRoutingChild::DeactivateLocked() {
   // Set the child weight to 0 so that future picker won't contain this child.
   // Start a timer to delete the child.
   Ref(DEBUG_LOCATION, "XdsRoutingChild+timer").release();
-  GRPC_CLOSURE_INIT(&on_delayed_removal_timer_, OnDelayedRemovalTimer, this,
-                    grpc_schedule_on_exec_ctx);
   grpc_timer_init(
       &delayed_removal_timer_,
       ExecCtx::Get()->Now() + GRPC_XDS_ROUTING_CHILD_RETENTION_INTERVAL_MS,
@@ -513,20 +514,20 @@ void XdsRoutingLb::XdsRoutingChild::DeactivateLocked() {
 void XdsRoutingLb::XdsRoutingChild::OnDelayedRemovalTimer(void* arg,
                                                           grpc_error* error) {
   XdsRoutingChild* self = static_cast<XdsRoutingChild*>(arg);
-  self->xds_routing_policy_->combiner()->Run(
-      GRPC_CLOSURE_INIT(&self->on_delayed_removal_timer_,
-                        OnDelayedRemovalTimerLocked, self, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // Ref owned by the lambda
+  self->xds_routing_policy_->work_serializer()->Run(
+      [self, error]() { self->OnDelayedRemovalTimerLocked(error); },
+      DEBUG_LOCATION);
 }
 
 void XdsRoutingLb::XdsRoutingChild::OnDelayedRemovalTimerLocked(
-    void* arg, grpc_error* error) {
-  XdsRoutingChild* self = static_cast<XdsRoutingChild*>(arg);
-  self->delayed_removal_timer_callback_pending_ = false;
-  if (error == GRPC_ERROR_NONE && !self->shutdown_) {
-    self->xds_routing_policy_->actions_.erase(self->name_);
+    grpc_error* error) {
+  delayed_removal_timer_callback_pending_ = false;
+  if (error == GRPC_ERROR_NONE && !shutdown_) {
+    xds_routing_policy_->actions_.erase(name_);
   }
-  self->Unref(DEBUG_LOCATION, "XdsRoutingChild+timer");
+  Unref(DEBUG_LOCATION, "XdsRoutingChild+timer");
+  GRPC_ERROR_UNREF(error);
 }
 
 //
@@ -579,7 +580,7 @@ void XdsRoutingLb::XdsRoutingChild::Helper::RequestReresolution() {
 }
 
 void XdsRoutingLb::XdsRoutingChild::Helper::AddTraceEvent(
-    TraceSeverity severity, StringView message) {
+    TraceSeverity severity, absl::string_view message) {
   if (xds_routing_child_->xds_routing_policy_->shutting_down_) return;
   xds_routing_child_->xds_routing_policy_->channel_control_helper()
       ->AddTraceEvent(severity, message);
@@ -711,7 +712,7 @@ class XdsRoutingLbFactory : public LoadBalancingPolicyFactory {
           "value should be of type object"));
       return error_list;
     }
-    auto it = json.object_value().find("child_policy");
+    auto it = json.object_value().find("childPolicy");
     if (it == json.object_value().end()) {
       error_list.push_back(
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("did not find childPolicy"));
index 498b158..806d6b3 100644 (file)
@@ -22,8 +22,9 @@
 
 #include <string.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 
 namespace grpc_core {
 
@@ -54,7 +55,8 @@ class RegistryState {
   }
 
  private:
-  InlinedVector<std::unique_ptr<LoadBalancingPolicyFactory>, 10> factories_;
+  absl::InlinedVector<std::unique_ptr<LoadBalancingPolicyFactory>, 10>
+      factories_;
 };
 
 RegistryState* g_state = nullptr;
index a6b7e25..7d18d9b 100644 (file)
@@ -38,7 +38,8 @@ class LocalSubchannelPool final : public SubchannelPoolInterface {
   ~LocalSubchannelPool() override;
 
   // Implements interface methods.
-  // Thread-unsafe. Intended to be invoked within the client_channel combiner.
+  // Thread-unsafe. Intended to be invoked within the client_channel work
+  // serializer.
   Subchannel* RegisterSubchannel(SubchannelKey* key,
                                  Subchannel* constructed) override;
   void UnregisterSubchannel(SubchannelKey* key) override;
index fbfbb44..e9950ac 100644 (file)
@@ -73,8 +73,8 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr,
                               bool log_errors) {
   bool success = false;
   // Split host and port.
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
+  std::string host;
+  std::string port;
   if (!grpc_core::SplitHostPort(hostport, &host, &port)) {
     if (log_errors) {
       gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)", hostport);
@@ -86,21 +86,21 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr,
   addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
   grpc_sockaddr_in* in = reinterpret_cast<grpc_sockaddr_in*>(addr->addr);
   in->sin_family = GRPC_AF_INET;
-  if (grpc_inet_pton(GRPC_AF_INET, host.get(), &in->sin_addr) == 0) {
+  if (grpc_inet_pton(GRPC_AF_INET, host.c_str(), &in->sin_addr) == 0) {
     if (log_errors) {
-      gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host.get());
+      gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host.c_str());
     }
     goto done;
   }
   // Parse port.
-  if (port == nullptr) {
+  if (port.empty()) {
     if (log_errors) gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
     goto done;
   }
   int port_num;
-  if (sscanf(port.get(), "%d", &port_num) != 1 || port_num < 0 ||
+  if (sscanf(port.c_str(), "%d", &port_num) != 1 || port_num < 0 ||
       port_num > 65535) {
-    if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port.get());
+    if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port.c_str());
     goto done;
   }
   in->sin_port = grpc_htons(static_cast<uint16_t>(port_num));
@@ -125,8 +125,8 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
                               bool log_errors) {
   bool success = false;
   // Split host and port.
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
+  std::string host;
+  std::string port;
   if (!grpc_core::SplitHostPort(hostport, &host, &port)) {
     if (log_errors) {
       gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)", hostport);
@@ -140,11 +140,12 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
   in6->sin6_family = GRPC_AF_INET6;
   // Handle the RFC6874 syntax for IPv6 zone identifiers.
   char* host_end =
-      static_cast<char*>(gpr_memrchr(host.get(), '%', strlen(host.get())));
+      static_cast<char*>(gpr_memrchr(host.c_str(), '%', host.size()));
   if (host_end != nullptr) {
-    GPR_ASSERT(host_end >= host.get());
+    GPR_ASSERT(host_end >= host.c_str());
     char host_without_scope[GRPC_INET6_ADDRSTRLEN + 1];
-    size_t host_without_scope_len = static_cast<size_t>(host_end - host.get());
+    size_t host_without_scope_len =
+        static_cast<size_t>(host_end - host.c_str());
     uint32_t sin6_scope_id = 0;
     if (host_without_scope_len > GRPC_INET6_ADDRSTRLEN) {
       if (log_errors) {
@@ -156,7 +157,7 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
       }
       goto done;
     }
-    strncpy(host_without_scope, host.get(), host_without_scope_len);
+    strncpy(host_without_scope, host.c_str(), host_without_scope_len);
     host_without_scope[host_without_scope_len] = '\0';
     if (grpc_inet_pton(GRPC_AF_INET6, host_without_scope, &in6->sin6_addr) ==
         0) {
@@ -165,9 +166,9 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
       }
       goto done;
     }
-    if (gpr_parse_bytes_to_uint32(
-            host_end + 1, strlen(host.get()) - host_without_scope_len - 1,
-            &sin6_scope_id) == 0) {
+    if (gpr_parse_bytes_to_uint32(host_end + 1,
+                                  host.size() - host_without_scope_len - 1,
+                                  &sin6_scope_id) == 0) {
       if ((sin6_scope_id = grpc_if_nametoindex(host_end + 1)) == 0) {
         gpr_log(GPR_ERROR,
                 "Invalid interface name: '%s'. "
@@ -179,22 +180,22 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
     // Handle "sin6_scope_id" being type "u_long". See grpc issue #10027.
     in6->sin6_scope_id = sin6_scope_id;
   } else {
-    if (grpc_inet_pton(GRPC_AF_INET6, host.get(), &in6->sin6_addr) == 0) {
+    if (grpc_inet_pton(GRPC_AF_INET6, host.c_str(), &in6->sin6_addr) == 0) {
       if (log_errors) {
-        gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host.get());
+        gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host.c_str());
       }
       goto done;
     }
   }
   // Parse port.
-  if (port == nullptr) {
+  if (port.empty()) {
     if (log_errors) gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
     goto done;
   }
   int port_num;
-  if (sscanf(port.get(), "%d", &port_num) != 1 || port_num < 0 ||
+  if (sscanf(port.c_str(), "%d", &port_num) != 1 || port_num < 0 ||
       port_num > 65535) {
-    if (log_errors) gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port.get());
+    if (log_errors) gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port.c_str());
     goto done;
   }
   in6->sin6_port = grpc_htons(static_cast<uint16_t>(port_num));
index c322d89..4a76a7d 100644 (file)
@@ -19,7 +19,6 @@
 #include <grpc/support/port_platform.h>
 
 #include "src/core/ext/filters/client_channel/resolver.h"
-#include "src/core/lib/iomgr/combiner.h"
 
 grpc_core::DebugOnlyTraceFlag grpc_trace_resolver_refcount(false,
                                                            "resolver_refcount");
@@ -30,13 +29,11 @@ namespace grpc_core {
 // Resolver
 //
 
-Resolver::Resolver(Combiner* combiner,
+Resolver::Resolver(std::shared_ptr<WorkSerializer> work_serializer,
                    std::unique_ptr<ResultHandler> result_handler)
     : InternallyRefCounted(&grpc_trace_resolver_refcount),
-      result_handler_(std::move(result_handler)),
-      combiner_(GRPC_COMBINER_REF(combiner, "resolver")) {}
-
-Resolver::~Resolver() { GRPC_COMBINER_UNREF(combiner_, "resolver"); }
+      work_serializer_(std::move(work_serializer)),
+      result_handler_(std::move(result_handler)) {}
 
 //
 // Resolver::Result
index ca2b2ea..de941a0 100644 (file)
@@ -27,8 +27,8 @@
 #include "src/core/ext/filters/client_channel/service_config.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 
 extern grpc_core::DebugOnlyTraceFlag grpc_trace_resolver_refcount;
 
@@ -45,7 +45,7 @@ namespace grpc_core {
 /// DNS).
 ///
 /// Note: All methods with a "Locked" suffix must be called from the
-/// combiner passed to the constructor.
+/// work_serializer passed to the constructor.
 class Resolver : public InternallyRefCounted<Resolver> {
  public:
   /// Results returned by the resolver.
@@ -87,7 +87,7 @@ class Resolver : public InternallyRefCounted<Resolver> {
   // Not copyable nor movable.
   Resolver(const Resolver&) = delete;
   Resolver& operator=(const Resolver&) = delete;
-  virtual ~Resolver();
+  virtual ~Resolver() = default;
 
   /// Starts resolving.
   virtual void StartLocked() = 0;
@@ -115,30 +115,28 @@ class Resolver : public InternallyRefCounted<Resolver> {
   /// implementations.  At that point, this method can go away.
   virtual void ResetBackoffLocked() {}
 
-  // Note: This must be invoked while holding the combiner.
+  // Note: This must be invoked while holding the work_serializer.
   void Orphan() override {
     ShutdownLocked();
     Unref();
   }
 
  protected:
-  /// Does NOT take ownership of the reference to \a combiner.
-  // TODO(roth): Once we have a C++-like interface for combiners, this
-  // API should change to take a RefCountedPtr<>, so that we always take
-  // ownership of a new ref.
-  explicit Resolver(Combiner* combiner,
-                    std::unique_ptr<ResultHandler> result_handler);
+  Resolver(std::shared_ptr<WorkSerializer> work_serializer,
+           std::unique_ptr<ResultHandler> result_handler);
 
   /// Shuts down the resolver.
   virtual void ShutdownLocked() = 0;
 
-  Combiner* combiner() const { return combiner_; }
+  std::shared_ptr<WorkSerializer> work_serializer() const {
+    return work_serializer_;
+  }
 
   ResultHandler* result_handler() const { return result_handler_.get(); }
 
  private:
+  std::shared_ptr<WorkSerializer> work_serializer_;
   std::unique_ptr<ResultHandler> result_handler_;
-  Combiner* combiner_;
 };
 
 }  // namespace grpc_core
index e2a05d0..781941b 100644 (file)
@@ -24,6 +24,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/manual_constructor.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/gethostname.h"
 #include "src/core/lib/iomgr/iomgr_custom.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "src/core/lib/json/json.h"
 
 #define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1
@@ -79,8 +81,8 @@ class AresDnsResolver : public Resolver {
 
   static void OnNextResolution(void* arg, grpc_error* error);
   static void OnResolved(void* arg, grpc_error* error);
-  static void OnNextResolutionLocked(void* arg, grpc_error* error);
-  static void OnResolvedLocked(void* arg, grpc_error* error);
+  void OnNextResolutionLocked(grpc_error* error);
+  void OnResolvedLocked(grpc_error* error);
 
   /// DNS server to use (if not system default)
   char* dns_server_;
@@ -92,7 +94,7 @@ class AresDnsResolver : public Resolver {
   bool request_service_config_;
   /// pollset_set to drive the name resolution process
   grpc_pollset_set* interested_parties_;
-  /// closures used by the combiner
+  /// closures used by the work_serializer
   grpc_closure on_next_resolution_;
   grpc_closure on_resolved_;
   /// are we currently resolving?
@@ -123,7 +125,7 @@ class AresDnsResolver : public Resolver {
 };
 
 AresDnsResolver::AresDnsResolver(ResolverArgs args)
-    : Resolver(args.combiner, std::move(args.result_handler)),
+    : Resolver(std::move(args.work_serializer), std::move(args.result_handler)),
       backoff_(
           BackOff::Options()
               .set_initial_backoff(GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS *
@@ -131,6 +133,10 @@ AresDnsResolver::AresDnsResolver(ResolverArgs args)
               .set_multiplier(GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER)
               .set_jitter(GRPC_DNS_RECONNECT_JITTER)
               .set_max_backoff(GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS * 1000)) {
+  // Closure Initialization
+  GRPC_CLOSURE_INIT(&on_next_resolution_, OnNextResolution, this,
+                    grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&on_resolved_, OnResolved, this, grpc_schedule_on_exec_ctx);
   // Get name to resolve from URI path.
   const char* path = args.uri->path;
   if (path[0] == '/') ++path;
@@ -204,26 +210,26 @@ void AresDnsResolver::ShutdownLocked() {
 
 void AresDnsResolver::OnNextResolution(void* arg, grpc_error* error) {
   AresDnsResolver* r = static_cast<AresDnsResolver*>(arg);
-  r->combiner()->Run(GRPC_CLOSURE_INIT(&r->on_next_resolution_,
-                                       OnNextResolutionLocked, r, nullptr),
-                     GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  r->work_serializer()->Run([r, error]() { r->OnNextResolutionLocked(error); },
+                            DEBUG_LOCATION);
 }
 
-void AresDnsResolver::OnNextResolutionLocked(void* arg, grpc_error* error) {
-  AresDnsResolver* r = static_cast<AresDnsResolver*>(arg);
+void AresDnsResolver::OnNextResolutionLocked(grpc_error* error) {
   GRPC_CARES_TRACE_LOG(
       "resolver:%p re-resolution timer fired. error: %s. shutdown_initiated_: "
       "%d",
-      r, grpc_error_string(error), r->shutdown_initiated_);
-  r->have_next_resolution_timer_ = false;
-  if (error == GRPC_ERROR_NONE && !r->shutdown_initiated_) {
-    if (!r->resolving_) {
+      this, grpc_error_string(error), shutdown_initiated_);
+  have_next_resolution_timer_ = false;
+  if (error == GRPC_ERROR_NONE && !shutdown_initiated_) {
+    if (!resolving_) {
       GRPC_CARES_TRACE_LOG(
-          "resolver:%p start resolving due to re-resolution timer", r);
-      r->StartResolvingLocked();
+          "resolver:%p start resolving due to re-resolution timer", this);
+      StartResolvingLocked();
     }
   }
-  r->Unref(DEBUG_LOCATION, "next_resolution_timer");
+  Unref(DEBUG_LOCATION, "next_resolution_timer");
+  GRPC_ERROR_UNREF(error);
 }
 
 bool ValueInJsonArray(const Json::Array& array, const char* value) {
@@ -245,7 +251,7 @@ std::string ChooseServiceConfig(char* service_config_choice_json,
     return "";
   }
   const Json* service_config = nullptr;
-  InlinedVector<grpc_error*, 4> error_list;
+  absl::InlinedVector<grpc_error*, 4> error_list;
   for (const Json& choice : json.array_value()) {
     if (choice.type() != Json::Type::OBJECT) {
       error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
@@ -316,81 +322,79 @@ std::string ChooseServiceConfig(char* service_config_choice_json,
 
 void AresDnsResolver::OnResolved(void* arg, grpc_error* error) {
   AresDnsResolver* r = static_cast<AresDnsResolver*>(arg);
-  r->combiner()->Run(
-      GRPC_CLOSURE_INIT(&r->on_resolved_, OnResolvedLocked, r, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  r->work_serializer()->Run([r, error]() { r->OnResolvedLocked(error); },
+                            DEBUG_LOCATION);
 }
 
-void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
-  AresDnsResolver* r = static_cast<AresDnsResolver*>(arg);
-  GPR_ASSERT(r->resolving_);
-  r->resolving_ = false;
-  gpr_free(r->pending_request_);
-  r->pending_request_ = nullptr;
-  if (r->shutdown_initiated_) {
-    r->Unref(DEBUG_LOCATION, "OnResolvedLocked() shutdown");
+void AresDnsResolver::OnResolvedLocked(grpc_error* error) {
+  GPR_ASSERT(resolving_);
+  resolving_ = false;
+  gpr_free(pending_request_);
+  pending_request_ = nullptr;
+  if (shutdown_initiated_) {
+    Unref(DEBUG_LOCATION, "OnResolvedLocked() shutdown");
+    GRPC_ERROR_UNREF(error);
     return;
   }
-  if (r->addresses_ != nullptr || r->balancer_addresses_ != nullptr) {
+  if (addresses_ != nullptr || balancer_addresses_ != nullptr) {
     Result result;
-    if (r->addresses_ != nullptr) {
-      result.addresses = std::move(*r->addresses_);
+    if (addresses_ != nullptr) {
+      result.addresses = std::move(*addresses_);
     }
-    if (r->service_config_json_ != nullptr) {
+    if (service_config_json_ != nullptr) {
       std::string service_config_string = ChooseServiceConfig(
-          r->service_config_json_, &result.service_config_error);
-      gpr_free(r->service_config_json_);
+          service_config_json_, &result.service_config_error);
+      gpr_free(service_config_json_);
       if (result.service_config_error == GRPC_ERROR_NONE &&
           !service_config_string.empty()) {
         GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s",
-                             r, service_config_string.c_str());
+                             this, service_config_string.c_str());
         result.service_config = ServiceConfig::Create(
             service_config_string, &result.service_config_error);
       }
     }
-    InlinedVector<grpc_arg, 1> new_args;
-    if (r->balancer_addresses_ != nullptr) {
+    absl::InlinedVector<grpc_arg, 1> new_args;
+    if (balancer_addresses_ != nullptr) {
       new_args.push_back(
-          CreateGrpclbBalancerAddressesArg(r->balancer_addresses_.get()));
+          CreateGrpclbBalancerAddressesArg(balancer_addresses_.get()));
     }
-    result.args = grpc_channel_args_copy_and_add(
-        r->channel_args_, new_args.data(), new_args.size());
-    r->result_handler()->ReturnResult(std::move(result));
-    r->addresses_.reset();
-    r->balancer_addresses_.reset();
+    result.args = grpc_channel_args_copy_and_add(channel_args_, new_args.data(),
+                                                 new_args.size());
+    result_handler()->ReturnResult(std::move(result));
+    addresses_.reset();
+    balancer_addresses_.reset();
     // Reset backoff state so that we start from the beginning when the
     // next request gets triggered.
-    r->backoff_.Reset();
+    backoff_.Reset();
   } else {
-    GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed: %s", r,
+    GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed: %s", this,
                          grpc_error_string(error));
-    r->result_handler()->ReturnError(grpc_error_set_int(
+    result_handler()->ReturnError(grpc_error_set_int(
         GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
             "DNS resolution failed", &error, 1),
         GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
     // Set retry timer.
-    grpc_millis next_try = r->backoff_.NextAttemptTime();
+    grpc_millis next_try = backoff_.NextAttemptTime();
     grpc_millis timeout = next_try - ExecCtx::Get()->Now();
     GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed (will retry): %s",
-                         r, grpc_error_string(error));
-    GPR_ASSERT(!r->have_next_resolution_timer_);
-    r->have_next_resolution_timer_ = true;
+                         this, grpc_error_string(error));
+    GPR_ASSERT(!have_next_resolution_timer_);
+    have_next_resolution_timer_ = true;
     // TODO(roth): We currently deal with this ref manually.  Once the
     // new closure API is done, find a way to track this ref with the timer
     // callback as part of the type system.
-    r->Ref(DEBUG_LOCATION, "retry-timer").release();
+    Ref(DEBUG_LOCATION, "retry-timer").release();
     if (timeout > 0) {
       GRPC_CARES_TRACE_LOG("resolver:%p retrying in %" PRId64 " milliseconds",
-                           r, timeout);
+                           this, timeout);
     } else {
-      GRPC_CARES_TRACE_LOG("resolver:%p retrying immediately", r);
+      GRPC_CARES_TRACE_LOG("resolver:%p retrying immediately", this);
     }
-    GRPC_CLOSURE_INIT(&r->on_next_resolution_, OnNextResolution, r,
-                      grpc_schedule_on_exec_ctx);
-    grpc_timer_init(&r->next_resolution_timer_, next_try,
-                    &r->on_next_resolution_);
+    grpc_timer_init(&next_resolution_timer_, next_try, &on_next_resolution_);
   }
-  r->Unref(DEBUG_LOCATION, "dns-resolving");
+  Unref(DEBUG_LOCATION, "dns-resolving");
+  GRPC_ERROR_UNREF(error);
 }
 
 void AresDnsResolver::MaybeStartResolvingLocked() {
@@ -414,8 +418,6 @@ void AresDnsResolver::MaybeStartResolvingLocked() {
       // new closure API is done, find a way to track this ref with the timer
       // callback as part of the type system.
       Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown").release();
-      GRPC_CLOSURE_INIT(&on_next_resolution_, OnNextResolution, this,
-                        grpc_schedule_on_exec_ctx);
       grpc_timer_init(&next_resolution_timer_,
                       ExecCtx::Get()->Now() + ms_until_next_resolution,
                       &on_next_resolution_);
@@ -433,13 +435,12 @@ void AresDnsResolver::StartResolvingLocked() {
   GPR_ASSERT(!resolving_);
   resolving_ = true;
   service_config_json_ = nullptr;
-  GRPC_CLOSURE_INIT(&on_resolved_, OnResolved, this, grpc_schedule_on_exec_ctx);
   pending_request_ = grpc_dns_lookup_ares_locked(
       dns_server_, name_to_resolve_, kDefaultPort, interested_parties_,
       &on_resolved_, &addresses_,
       enable_srv_queries_ ? &balancer_addresses_ : nullptr,
       request_service_config_ ? &service_config_json_ : nullptr,
-      query_timeout_ms_, combiner());
+      query_timeout_ms_, work_serializer());
   last_resolution_timestamp_ = grpc_core::ExecCtx::Get()->Now();
   GRPC_CARES_TRACE_LOG("resolver:%p Started resolving. pending_request_:%p",
                        this, pending_request_);
index 626b725..7e546a3 100644 (file)
@@ -31,7 +31,6 @@
 #include <grpc/support/time.h>
 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/timer.h"
@@ -66,8 +65,8 @@ struct grpc_ares_ev_driver {
   /** refcount of the event driver */
   gpr_refcount refs;
 
-  /** combiner to synchronize c-ares and I/O callbacks on */
-  grpc_core::Combiner* combiner;
+  /** work_serializer to synchronize c-ares and I/O callbacks on */
+  std::shared_ptr<grpc_core::WorkSerializer> work_serializer;
   /** a list of grpc_fd that this event driver is currently using. */
   fd_node* fds;
   /** is this event driver currently working? */
@@ -107,7 +106,6 @@ static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) {
     GRPC_CARES_TRACE_LOG("request:%p destroy ev_driver %p", ev_driver->request,
                          ev_driver);
     GPR_ASSERT(ev_driver->fds == nullptr);
-    GRPC_COMBINER_UNREF(ev_driver->combiner, "free ares event driver");
     ares_destroy(ev_driver->channel);
     grpc_ares_complete_request_locked(ev_driver->request);
     delete ev_driver;
@@ -133,21 +131,22 @@ static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) {
 }
 
 static void on_timeout(void* arg, grpc_error* error);
-static void on_timeout_locked(void* arg, grpc_error* error);
+static void on_timeout_locked(grpc_ares_ev_driver* arg, grpc_error* error);
 
 static void on_ares_backup_poll_alarm(void* arg, grpc_error* error);
-static void on_ares_backup_poll_alarm_locked(void* arg, grpc_error* error);
+static void on_ares_backup_poll_alarm_locked(grpc_ares_ev_driver* arg,
+                                             grpc_error* error);
 
 static void noop_inject_channel_config(ares_channel /*channel*/) {}
 
 void (*grpc_ares_test_only_inject_config)(ares_channel channel) =
     noop_inject_channel_config;
 
-grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
-                                              grpc_pollset_set* pollset_set,
-                                              int query_timeout_ms,
-                                              grpc_core::Combiner* combiner,
-                                              grpc_ares_request* request) {
+grpc_error* grpc_ares_ev_driver_create_locked(
+    grpc_ares_ev_driver** ev_driver, grpc_pollset_set* pollset_set,
+    int query_timeout_ms,
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer,
+    grpc_ares_request* request) {
   *ev_driver = new grpc_ares_ev_driver();
   ares_options opts;
   memset(&opts, 0, sizeof(opts));
@@ -164,7 +163,7 @@ grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
     gpr_free(*ev_driver);
     return err;
   }
-  (*ev_driver)->combiner = GRPC_COMBINER_REF(combiner, "ares event driver");
+  (*ev_driver)->work_serializer = std::move(work_serializer);
   gpr_ref_init(&(*ev_driver)->refs, 1);
   (*ev_driver)->pollset_set = pollset_set;
   (*ev_driver)->fds = nullptr;
@@ -172,7 +171,7 @@ grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
   (*ev_driver)->shutting_down = false;
   (*ev_driver)->request = request;
   (*ev_driver)->polled_fd_factory =
-      grpc_core::NewGrpcPolledFdFactory((*ev_driver)->combiner);
+      grpc_core::NewGrpcPolledFdFactory((*ev_driver)->work_serializer);
   (*ev_driver)
       ->polled_fd_factory->ConfigureAresChannelLocked((*ev_driver)->channel);
   (*ev_driver)->query_timeout_ms = query_timeout_ms;
@@ -234,13 +233,12 @@ static grpc_millis calculate_next_ares_backup_poll_alarm_ms(
 
 static void on_timeout(void* arg, grpc_error* error) {
   grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
-  driver->combiner->Run(GRPC_CLOSURE_INIT(&driver->on_timeout_locked,
-                                          on_timeout_locked, driver, nullptr),
-                        GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  driver->work_serializer->Run(
+      [driver, error]() { on_timeout_locked(driver, error); }, DEBUG_LOCATION);
 }
 
-static void on_timeout_locked(void* arg, grpc_error* error) {
-  grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
+static void on_timeout_locked(grpc_ares_ev_driver* driver, grpc_error* error) {
   GRPC_CARES_TRACE_LOG(
       "request:%p ev_driver=%p on_timeout_locked. driver->shutting_down=%d. "
       "err=%s",
@@ -249,14 +247,15 @@ static void on_timeout_locked(void* arg, grpc_error* error) {
     grpc_ares_ev_driver_shutdown_locked(driver);
   }
   grpc_ares_ev_driver_unref(driver);
+  GRPC_ERROR_UNREF(error);
 }
 
 static void on_ares_backup_poll_alarm(void* arg, grpc_error* error) {
   grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
-  driver->combiner->Run(
-      GRPC_CLOSURE_INIT(&driver->on_ares_backup_poll_alarm_locked,
-                        on_ares_backup_poll_alarm_locked, driver, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);
+  driver->work_serializer->Run(
+      [driver, error]() { on_ares_backup_poll_alarm_locked(driver, error); },
+      DEBUG_LOCATION);
 }
 
 /* In case of non-responsive DNS servers, dropped packets, etc., c-ares has
@@ -267,8 +266,8 @@ static void on_ares_backup_poll_alarm(void* arg, grpc_error* error) {
  *   b) when some time has passed without fd events having happened
  * For the latter, we use this backup poller. Also see
  * https://github.com/grpc/grpc/pull/17688 description for more details. */
-static void on_ares_backup_poll_alarm_locked(void* arg, grpc_error* error) {
-  grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
+static void on_ares_backup_poll_alarm_locked(grpc_ares_ev_driver* driver,
+                                             grpc_error* error) {
   GRPC_CARES_TRACE_LOG(
       "request:%p ev_driver=%p on_ares_backup_poll_alarm_locked. "
       "driver->shutting_down=%d. "
@@ -301,10 +300,10 @@ static void on_ares_backup_poll_alarm_locked(void* arg, grpc_error* error) {
     grpc_ares_notify_on_event_locked(driver);
   }
   grpc_ares_ev_driver_unref(driver);
+  GRPC_ERROR_UNREF(error);
 }
 
-static void on_readable_locked(void* arg, grpc_error* error) {
-  fd_node* fdn = static_cast<fd_node*>(arg);
+static void on_readable_locked(fd_node* fdn, grpc_error* error) {
   GPR_ASSERT(fdn->readable_registered);
   grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
   const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked();
@@ -326,17 +325,17 @@ static void on_readable_locked(void* arg, grpc_error* error) {
   }
   grpc_ares_notify_on_event_locked(ev_driver);
   grpc_ares_ev_driver_unref(ev_driver);
+  GRPC_ERROR_UNREF(error);
 }
 
 static void on_readable(void* arg, grpc_error* error) {
   fd_node* fdn = static_cast<fd_node*>(arg);
-  fdn->ev_driver->combiner->Run(
-      GRPC_CLOSURE_INIT(&fdn->read_closure, on_readable_locked, fdn, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error); /* ref owned by lambda */
+  fdn->ev_driver->work_serializer->Run(
+      [fdn, error]() { on_readable_locked(fdn, error); }, DEBUG_LOCATION);
 }
 
-static void on_writable_locked(void* arg, grpc_error* error) {
-  fd_node* fdn = static_cast<fd_node*>(arg);
+static void on_writable_locked(fd_node* fdn, grpc_error* error) {
   GPR_ASSERT(fdn->writable_registered);
   grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
   const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked();
@@ -356,13 +355,14 @@ static void on_writable_locked(void* arg, grpc_error* error) {
   }
   grpc_ares_notify_on_event_locked(ev_driver);
   grpc_ares_ev_driver_unref(ev_driver);
+  GRPC_ERROR_UNREF(error);
 }
 
 static void on_writable(void* arg, grpc_error* error) {
   fd_node* fdn = static_cast<fd_node*>(arg);
-  fdn->ev_driver->combiner->Run(
-      GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_locked, fdn, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error); /* ref owned by lambda */
+  fdn->ev_driver->work_serializer->Run(
+      [fdn, error]() { on_writable_locked(fdn, error); }, DEBUG_LOCATION);
 }
 
 ares_channel* grpc_ares_ev_driver_get_channel_locked(
@@ -387,7 +387,7 @@ static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) {
           fdn = static_cast<fd_node*>(gpr_malloc(sizeof(fd_node)));
           fdn->grpc_polled_fd =
               ev_driver->polled_fd_factory->NewGrpcPolledFdLocked(
-                  socks[i], ev_driver->pollset_set, ev_driver->combiner);
+                  socks[i], ev_driver->pollset_set, ev_driver->work_serializer);
           GRPC_CARES_TRACE_LOG("request:%p new fd: %s", ev_driver->request,
                                fdn->grpc_polled_fd->GetName());
           fdn->ev_driver = ev_driver;
index 1a5a3f6..cedf0c3 100644 (file)
@@ -40,11 +40,11 @@ ares_channel* grpc_ares_ev_driver_get_channel_locked(
 
 /* Creates a new grpc_ares_ev_driver. Returns GRPC_ERROR_NONE if \a ev_driver is
    created successfully. */
-grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
-                                              grpc_pollset_set* pollset_set,
-                                              int query_timeout_ms,
-                                              grpc_core::Combiner* combiner,
-                                              grpc_ares_request* request);
+grpc_error* grpc_ares_ev_driver_create_locked(
+    grpc_ares_ev_driver** ev_driver, grpc_pollset_set* pollset_set,
+    int query_timeout_ms,
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer,
+    grpc_ares_request* request);
 
 /* Called back when all DNS lookups have completed. */
 void grpc_ares_ev_driver_on_queries_complete_locked(
@@ -90,12 +90,13 @@ class GrpcPolledFdFactory {
   /* Creates a new wrapped fd for the current platform */
   virtual GrpcPolledFd* NewGrpcPolledFdLocked(
       ares_socket_t as, grpc_pollset_set* driver_pollset_set,
-      Combiner* combiner) = 0;
+      std::shared_ptr<grpc_core::WorkSerializer> work_serializer) = 0;
   /* Optionally configures the ares channel after creation */
   virtual void ConfigureAresChannelLocked(ares_channel channel) = 0;
 };
 
-std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(Combiner* combiner);
+std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer);
 
 }  // namespace grpc_core
 
index 37bb903..3d293ee 100644 (file)
@@ -31,7 +31,7 @@
 #include <grpc/support/time.h>
 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/iomgr/combiner.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 
 namespace grpc_core {
 
@@ -41,19 +41,16 @@ void ares_uv_poll_close_cb(uv_handle_t* handle) { delete handle; }
 
 class GrpcPolledFdLibuv : public GrpcPolledFd {
  public:
-  GrpcPolledFdLibuv(ares_socket_t as, Combiner* combiner)
-      : as_(as), combiner_(combiner) {
+  GrpcPolledFdLibuv(ares_socket_t as,
+                    std::shared_ptr<WorkSerializer> work_serializer)
+      : as_(as), work_serializer_(std::move(work_serializer)) {
     gpr_asprintf(&name_, "c-ares socket: %" PRIdPTR, (intptr_t)as);
     handle_ = new uv_poll_t();
     uv_poll_init_socket(uv_default_loop(), handle_, as);
     handle_->data = this;
-    GRPC_COMBINER_REF(combiner_, "libuv ares event driver");
   }
 
-  ~GrpcPolledFdLibuv() {
-    gpr_free(name_);
-    GRPC_COMBINER_UNREF(combiner_, "libuv ares event driver");
-  }
+  ~GrpcPolledFdLibuv() { gpr_free(name_); }
 
   void RegisterForOnReadableLocked(grpc_closure* read_closure) override {
     GPR_ASSERT(read_closure_ == nullptr);
@@ -109,7 +106,7 @@ class GrpcPolledFdLibuv : public GrpcPolledFd {
   grpc_closure* read_closure_ = nullptr;
   grpc_closure* write_closure_ = nullptr;
   int poll_events_ = 0;
-  Combiner* combiner_;
+  std::shared_ptr<WorkSerializer> work_serializer_;
 };
 
 struct AresUvPollCbArg {
@@ -121,14 +118,14 @@ struct AresUvPollCbArg {
   int events;
 };
 
-static void ares_uv_poll_cb_locked(void* arg, grpc_error* error) {
-  std::unique_ptr<AresUvPollCbArg> arg_struct(
-      reinterpret_cast<AresUvPollCbArg*>(arg));
+static void ares_uv_poll_cb_locked(AresUvPollCbArg* arg) {
+  std::unique_ptr<AresUvPollCbArg> arg_struct(arg);
   uv_poll_t* handle = arg_struct->handle;
   int status = arg_struct->status;
   int events = arg_struct->events;
   GrpcPolledFdLibuv* polled_fd =
       reinterpret_cast<GrpcPolledFdLibuv*>(handle->data);
+  grpc_error* error = GRPC_ERROR_NONE;
   if (status < 0) {
     error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("cares polling error");
     error =
@@ -155,24 +152,23 @@ void ares_uv_poll_cb(uv_poll_t* handle, int status, int events) {
   GrpcPolledFdLibuv* polled_fd =
       reinterpret_cast<GrpcPolledFdLibuv*>(handle->data);
   AresUvPollCbArg* arg = new AresUvPollCbArg(handle, status, events);
-  polled_fd->combiner_->Run(
-      GRPC_CLOSURE_CREATE(ares_uv_poll_cb_locked, arg, nullptr),
-      GRPC_ERROR_NONE);
+  polled_fd->work_serializer_->Run([arg]() { ares_uv_poll_cb_locked(arg); },
+                                   DEBUG_LOCATION);
 }
 
 class GrpcPolledFdFactoryLibuv : public GrpcPolledFdFactory {
  public:
-  GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
-                                      grpc_pollset_set* driver_pollset_set,
-                                      Combiner* combiner) override {
-    return new GrpcPolledFdLibuv(as, combiner);
+  GrpcPolledFd* NewGrpcPolledFdLocked(
+      ares_socket_t as, grpc_pollset_set* driver_pollset_set,
+      std::shared_ptr<WorkSerializer> work_serializer) override {
+    return new GrpcPolledFdLibuv(as, std::move(work_serializer));
   }
 
   void ConfigureAresChannelLocked(ares_channel channel) override {}
 };
 
 std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(
-    Combiner* combiner) {
+    std::shared_ptr<WorkSerializer> work_serializer) {
   return absl::make_unique<GrpcPolledFdFactoryLibuv>();
 }
 
index 0b571a2..a6ff49b 100644 (file)
@@ -88,9 +88,9 @@ class GrpcPolledFdPosix : public GrpcPolledFd {
 
 class GrpcPolledFdFactoryPosix : public GrpcPolledFdFactory {
  public:
-  GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
-                                      grpc_pollset_set* driver_pollset_set,
-                                      Combiner* /*combiner*/) override {
+  GrpcPolledFd* NewGrpcPolledFdLocked(
+      ares_socket_t as, grpc_pollset_set* driver_pollset_set,
+      std::shared_ptr<WorkSerializer> /*work_serializer*/) override {
     return new GrpcPolledFdPosix(as, driver_pollset_set);
   }
 
@@ -98,7 +98,7 @@ class GrpcPolledFdFactoryPosix : public GrpcPolledFdFactory {
 };
 
 std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(
-    Combiner* /*combiner*/) {
+    std::shared_ptr<WorkSerializer> work_serializer) { /* NOLINT */
   return absl::make_unique<GrpcPolledFdFactoryPosix>();
 }
 
index 0742c97..1b5bfb0 100644 (file)
 #include <string.h>
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/memory.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/iocp_windows.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/sockaddr_windows.h"
 #include "src/core/lib/iomgr/socket_windows.h"
 #include "src/core/lib/iomgr/tcp_windows.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "src/core/lib/slice/slice_internal.h"
 
 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
@@ -97,28 +97,31 @@ class GrpcPolledFdWindows {
     WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY,
   };
 
-  GrpcPolledFdWindows(ares_socket_t as, Combiner* combiner, int address_family,
-                      int socket_type)
-      : read_buf_(grpc_empty_slice()),
+  GrpcPolledFdWindows(ares_socket_t as,
+                      std::shared_ptr<WorkSerializer> work_serializer,
+                      int address_family, int socket_type)
+      : work_serializer_(std::move(work_serializer)),
+        read_buf_(grpc_empty_slice()),
         write_buf_(grpc_empty_slice()),
         tcp_write_state_(WRITE_IDLE),
         gotten_into_driver_list_(false),
         address_family_(address_family),
         socket_type_(socket_type) {
     gpr_asprintf(&name_, "c-ares socket: %" PRIdPTR, as);
+    // Closure Initialization
+    GRPC_CLOSURE_INIT(&outer_read_closure_,
+                      &GrpcPolledFdWindows::OnIocpReadable, this,
+                      grpc_schedule_on_exec_ctx);
+    GRPC_CLOSURE_INIT(&outer_write_closure_,
+                      &GrpcPolledFdWindows::OnIocpWriteable, this,
+                      grpc_schedule_on_exec_ctx);
+    GRPC_CLOSURE_INIT(&on_tcp_connect_locked_,
+                      &GrpcPolledFdWindows::OnTcpConnect, this,
+                      grpc_schedule_on_exec_ctx);
     winsocket_ = grpc_winsocket_create(as, name_);
-    combiner_ = GRPC_COMBINER_REF(combiner, name_);
-    GRPC_CLOSURE_INIT(&continue_register_for_on_readable_locked_,
-                      &GrpcPolledFdWindows::ContinueRegisterForOnReadableLocked,
-                      this, nullptr);
-    GRPC_CLOSURE_INIT(
-        &continue_register_for_on_writeable_locked_,
-        &GrpcPolledFdWindows::ContinueRegisterForOnWriteableLocked, this,
-        nullptr);
   }
 
   ~GrpcPolledFdWindows() {
-    GRPC_COMBINER_UNREF(combiner_, name_);
     grpc_slice_unref_internal(read_buf_);
     grpc_slice_unref_internal(write_buf_);
     GPR_ASSERT(read_closure_ == nullptr);
@@ -145,23 +148,15 @@ class GrpcPolledFdWindows {
     GPR_ASSERT(!read_buf_has_data_);
     read_buf_ = GRPC_SLICE_MALLOC(4192);
     if (connect_done_) {
-      combiner_->Run(&continue_register_for_on_readable_locked_,
-                     GRPC_ERROR_NONE);
+      work_serializer_->Run([this]() { ContinueRegisterForOnReadableLocked(); },
+                            DEBUG_LOCATION);
     } else {
-      GPR_ASSERT(pending_continue_register_for_on_readable_locked_ == nullptr);
-      pending_continue_register_for_on_readable_locked_ =
-          &continue_register_for_on_readable_locked_;
+      GPR_ASSERT(pending_continue_register_for_on_readable_locked_ == false);
+      pending_continue_register_for_on_readable_locked_ = true;
     }
   }
 
-  static void ContinueRegisterForOnReadableLocked(void* arg,
-                                                  grpc_error* unused_error) {
-    GrpcPolledFdWindows* grpc_polled_fd =
-        static_cast<GrpcPolledFdWindows*>(arg);
-    grpc_polled_fd->InnerContinueRegisterForOnReadableLocked(GRPC_ERROR_NONE);
-  }
-
-  void InnerContinueRegisterForOnReadableLocked(grpc_error* unused_error) {
+  void ContinueRegisterForOnReadableLocked() {
     GRPC_CARES_TRACE_LOG(
         "fd:|%s| InnerContinueRegisterForOnReadableLocked "
         "wsa_connect_error_:%d",
@@ -194,10 +189,7 @@ class GrpcPolledFdWindows {
         return;
       }
     }
-    grpc_socket_notify_on_read(
-        winsocket_, GRPC_CLOSURE_INIT(&outer_read_closure_,
-                                      &GrpcPolledFdWindows::OnIocpReadable,
-                                      this, grpc_schedule_on_exec_ctx));
+    grpc_socket_notify_on_read(winsocket_, &outer_read_closure_);
   }
 
   void RegisterForOnWriteableLocked(grpc_closure* write_closure) {
@@ -213,23 +205,15 @@ class GrpcPolledFdWindows {
     GPR_ASSERT(write_closure_ == nullptr);
     write_closure_ = write_closure;
     if (connect_done_) {
-      combiner_->Run(&continue_register_for_on_writeable_locked_,
-                     GRPC_ERROR_NONE);
+      work_serializer_->Run(
+          [this]() { ContinueRegisterForOnWriteableLocked(); }, DEBUG_LOCATION);
     } else {
-      GPR_ASSERT(pending_continue_register_for_on_writeable_locked_ == nullptr);
-      pending_continue_register_for_on_writeable_locked_ =
-          &continue_register_for_on_writeable_locked_;
+      GPR_ASSERT(pending_continue_register_for_on_writeable_locked_ == false);
+      pending_continue_register_for_on_writeable_locked_ = true;
     }
   }
 
-  static void ContinueRegisterForOnWriteableLocked(void* arg,
-                                                   grpc_error* unused_error) {
-    GrpcPolledFdWindows* grpc_polled_fd =
-        static_cast<GrpcPolledFdWindows*>(arg);
-    grpc_polled_fd->InnerContinueRegisterForOnWriteableLocked(GRPC_ERROR_NONE);
-  }
-
-  void InnerContinueRegisterForOnWriteableLocked(grpc_error* unused_error) {
+  void ContinueRegisterForOnWriteableLocked() {
     GRPC_CARES_TRACE_LOG(
         "fd:|%s| InnerContinueRegisterForOnWriteableLocked "
         "wsa_connect_error_:%d",
@@ -256,11 +240,7 @@ class GrpcPolledFdWindows {
             ScheduleAndNullWriteClosure(
                 GRPC_WSA_ERROR(wsa_error_code, "WSASend (overlapped)"));
           } else {
-            grpc_socket_notify_on_write(
-                winsocket_,
-                GRPC_CLOSURE_INIT(&outer_write_closure_,
-                                  &GrpcPolledFdWindows::OnIocpWriteable, this,
-                                  grpc_schedule_on_exec_ctx));
+            grpc_socket_notify_on_write(winsocket_, &outer_write_closure_);
           }
           break;
         case WRITE_PENDING:
@@ -440,24 +420,19 @@ class GrpcPolledFdWindows {
   static void OnTcpConnect(void* arg, grpc_error* error) {
     GrpcPolledFdWindows* grpc_polled_fd =
         static_cast<GrpcPolledFdWindows*>(arg);
-    grpc_polled_fd->combiner_->Run(
-        GRPC_CLOSURE_INIT(&grpc_polled_fd->on_tcp_connect_locked_,
-                          &GrpcPolledFdWindows::OnTcpConnectLocked,
-                          grpc_polled_fd, nullptr),
-        GRPC_ERROR_REF(error));
-  }
-
-  static void OnTcpConnectLocked(void* arg, grpc_error* error) {
-    GrpcPolledFdWindows* grpc_polled_fd =
-        static_cast<GrpcPolledFdWindows*>(arg);
-    grpc_polled_fd->InnerOnTcpConnectLocked(error);
+    GRPC_ERROR_REF(error);  // ref owned by lambda
+    grpc_polled_fd->work_serializer_->Run(
+        [grpc_polled_fd, error]() {
+          grpc_polled_fd->OnTcpConnectLocked(error);
+        },
+        DEBUG_LOCATION);
   }
 
-  void InnerOnTcpConnectLocked(grpc_error* error) {
+  void OnTcpConnectLocked(grpc_error* error) {
     GRPC_CARES_TRACE_LOG(
         "fd:%s InnerOnTcpConnectLocked error:|%s| "
-        "pending_register_for_readable:%" PRIdPTR
-        " pending_register_for_writeable:%" PRIdPTR,
+        "pending_register_for_readable:%d"
+        " pending_register_for_writeable:%d",
         GetName(), grpc_error_string(error),
         pending_continue_register_for_on_readable_locked_,
         pending_continue_register_for_on_writeable_locked_);
@@ -486,14 +461,15 @@ class GrpcPolledFdWindows {
       // this fd to abort.
       wsa_connect_error_ = WSA_OPERATION_ABORTED;
     }
-    if (pending_continue_register_for_on_readable_locked_ != nullptr) {
-      combiner_->Run(pending_continue_register_for_on_readable_locked_,
-                     GRPC_ERROR_NONE);
+    if (pending_continue_register_for_on_readable_locked_) {
+      work_serializer_->Run([this]() { ContinueRegisterForOnReadableLocked(); },
+                            DEBUG_LOCATION);
     }
-    if (pending_continue_register_for_on_writeable_locked_ != nullptr) {
-      combiner_->Run(pending_continue_register_for_on_writeable_locked_,
-                     GRPC_ERROR_NONE);
+    if (pending_continue_register_for_on_writeable_locked_) {
+      work_serializer_->Run(
+          [this]() { ContinueRegisterForOnWriteableLocked(); }, DEBUG_LOCATION);
     }
+    GRPC_ERROR_UNREF(error);
   }
 
   int Connect(WSAErrorContext* wsa_error_ctx, const struct sockaddr* target,
@@ -593,25 +569,16 @@ class GrpcPolledFdWindows {
         return -1;
       }
     }
-    GRPC_CLOSURE_INIT(&on_tcp_connect_locked_,
-                      &GrpcPolledFdWindows::OnTcpConnect, this,
-                      grpc_schedule_on_exec_ctx);
     grpc_socket_notify_on_write(winsocket_, &on_tcp_connect_locked_);
     return out;
   }
 
   static void OnIocpReadable(void* arg, grpc_error* error) {
     GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
-    polled_fd->combiner_->Run(
-        GRPC_CLOSURE_INIT(&polled_fd->outer_read_closure_,
-                          &GrpcPolledFdWindows::OnIocpReadableLocked, polled_fd,
-                          nullptr),
-        GRPC_ERROR_REF(error));
-  }
-
-  static void OnIocpReadableLocked(void* arg, grpc_error* error) {
-    GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
-    polled_fd->OnIocpReadableInner(error);
+    GRPC_ERROR_REF(error);  // ref owned by lambda
+    polled_fd->work_serializer_->Run(
+        [polled_fd, error]() { polled_fd->OnIocpReadableLocked(error); },
+        DEBUG_LOCATION);
   }
 
   // TODO(apolcyn): improve this error handling to be less conversative.
@@ -619,7 +586,7 @@ class GrpcPolledFdWindows {
   // c-ares reads from this socket later, but it shouldn't necessarily cancel
   // the entire resolution attempt. Doing so will allow the "inject broken
   // nameserver list" test to pass on Windows.
-  void OnIocpReadableInner(grpc_error* error) {
+  void OnIocpReadableLocked(grpc_error* error) {
     if (error == GRPC_ERROR_NONE) {
       if (winsocket_->read_info.wsa_error != 0) {
         /* WSAEMSGSIZE would be due to receiving more data
@@ -627,7 +594,6 @@ class GrpcPolledFdWindows {
          * the connection is TCP and read the leftovers
          * in subsequent c-ares reads. */
         if (winsocket_->read_info.wsa_error != WSAEMSGSIZE) {
-          GRPC_ERROR_UNREF(error);
           error = GRPC_WSA_ERROR(winsocket_->read_info.wsa_error,
                                  "OnIocpReadableInner");
           GRPC_CARES_TRACE_LOG(
@@ -654,24 +620,17 @@ class GrpcPolledFdWindows {
 
   static void OnIocpWriteable(void* arg, grpc_error* error) {
     GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
-    polled_fd->combiner_->Run(
-        GRPC_CLOSURE_INIT(&polled_fd->outer_write_closure_,
-                          &GrpcPolledFdWindows::OnIocpWriteableLocked,
-                          polled_fd, nullptr),
-        GRPC_ERROR_REF(error));
+    GRPC_ERROR_REF(error);  // error owned by lambda
+    polled_fd->work_serializer_->Run(
+        [polled_fd, error]() { polled_fd->OnIocpWriteableLocked(error); },
+        DEBUG_LOCATION);
   }
 
-  static void OnIocpWriteableLocked(void* arg, grpc_error* error) {
-    GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
-    polled_fd->OnIocpWriteableInner(error);
-  }
-
-  void OnIocpWriteableInner(grpc_error* error) {
+  void OnIocpWriteableLocked(grpc_error* error) {
     GRPC_CARES_TRACE_LOG("OnIocpWriteableInner. fd:|%s|", GetName());
     GPR_ASSERT(socket_type_ == SOCK_STREAM);
     if (error == GRPC_ERROR_NONE) {
       if (winsocket_->write_info.wsa_error != 0) {
-        GRPC_ERROR_UNREF(error);
         error = GRPC_WSA_ERROR(winsocket_->write_info.wsa_error,
                                "OnIocpWriteableInner");
         GRPC_CARES_TRACE_LOG(
@@ -698,7 +657,7 @@ class GrpcPolledFdWindows {
   bool gotten_into_driver_list() const { return gotten_into_driver_list_; }
   void set_gotten_into_driver_list() { gotten_into_driver_list_ = true; }
 
-  Combiner* combiner_;
+  std::shared_ptr<WorkSerializer> work_serializer_;
   char recv_from_source_addr_[200];
   ares_socklen_t recv_from_source_addr_len_;
   grpc_slice read_buf_;
@@ -721,10 +680,8 @@ class GrpcPolledFdWindows {
   // We don't run register_for_{readable,writeable} logic until
   // a socket is connected. In the interim, we queue readable/writeable
   // registrations with the following state.
-  grpc_closure continue_register_for_on_readable_locked_;
-  grpc_closure continue_register_for_on_writeable_locked_;
-  grpc_closure* pending_continue_register_for_on_readable_locked_ = nullptr;
-  grpc_closure* pending_continue_register_for_on_writeable_locked_ = nullptr;
+  bool pending_continue_register_for_on_readable_locked_ = false;
+  bool pending_continue_register_for_on_writeable_locked_ = false;
 };
 
 struct SockToPolledFdEntry {
@@ -742,14 +699,10 @@ struct SockToPolledFdEntry {
  * with a GrpcPolledFdWindows factory and event driver */
 class SockToPolledFdMap {
  public:
-  SockToPolledFdMap(Combiner* combiner) {
-    combiner_ = GRPC_COMBINER_REF(combiner, "sock to polled fd map");
-  }
+  explicit SockToPolledFdMap(std::shared_ptr<WorkSerializer> work_serializer)
+      : work_serializer_(std::move(work_serializer)) {}
 
-  ~SockToPolledFdMap() {
-    GPR_ASSERT(head_ == nullptr);
-    GRPC_COMBINER_UNREF(combiner_, "sock to polled fd map");
-  }
+  ~SockToPolledFdMap() { GPR_ASSERT(head_ == nullptr); }
 
   void AddNewSocket(SOCKET s, GrpcPolledFdWindows* polled_fd) {
     SockToPolledFdEntry* new_node = new SockToPolledFdEntry(s, polled_fd);
@@ -805,7 +758,7 @@ class SockToPolledFdMap {
     }
     grpc_tcp_set_non_block(s);
     GrpcPolledFdWindows* polled_fd =
-        new GrpcPolledFdWindows(s, map->combiner_, af, type);
+        new GrpcPolledFdWindows(s, map->work_serializer_, af, type);
     GRPC_CARES_TRACE_LOG(
         "fd:|%s| created with params af:%d type:%d protocol:%d",
         polled_fd->GetName(), af, type, protocol);
@@ -861,7 +814,7 @@ class SockToPolledFdMap {
 
  private:
   SockToPolledFdEntry* head_ = nullptr;
-  Combiner* combiner_;
+  std::shared_ptr<WorkSerializer> work_serializer_;
 };
 
 const struct ares_socket_functions custom_ares_sock_funcs = {
@@ -877,7 +830,7 @@ const struct ares_socket_functions custom_ares_sock_funcs = {
    so that c-ares can close it via usual socket teardown. */
 class GrpcPolledFdWindowsWrapper : public GrpcPolledFd {
  public:
-  GrpcPolledFdWindowsWrapper(GrpcPolledFdWindows* wrapped)
+  explicit GrpcPolledFdWindowsWrapper(GrpcPolledFdWindows* wrapped)
       : wrapped_(wrapped) {}
 
   ~GrpcPolledFdWindowsWrapper() {}
@@ -910,12 +863,13 @@ class GrpcPolledFdWindowsWrapper : public GrpcPolledFd {
 
 class GrpcPolledFdFactoryWindows : public GrpcPolledFdFactory {
  public:
-  GrpcPolledFdFactoryWindows(Combiner* combiner)
-      : sock_to_polled_fd_map_(combiner) {}
+  explicit GrpcPolledFdFactoryWindows(
+      std::shared_ptr<WorkSerializer> work_serializer)
+      : sock_to_polled_fd_map_(std::move(work_serializer)) {}
 
-  GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
-                                      grpc_pollset_set* driver_pollset_set,
-                                      Combiner* combiner) override {
+  GrpcPolledFd* NewGrpcPolledFdLocked(
+      ares_socket_t as, grpc_pollset_set* driver_pollset_set,
+      std::shared_ptr<WorkSerializer> work_serializer) override {
     GrpcPolledFdWindows* polled_fd = sock_to_polled_fd_map_.LookupPolledFd(as);
     // Set a flag so that the virtual socket "close" method knows it
     // doesn't need to call ShutdownLocked, since now the driver will.
@@ -933,8 +887,9 @@ class GrpcPolledFdFactoryWindows : public GrpcPolledFdFactory {
 };
 
 std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(
-    Combiner* combiner) {
-  return absl::make_unique<GrpcPolledFdFactoryWindows>(combiner);
+    std::shared_ptr<WorkSerializer> work_serializer) {
+  return absl::make_unique<GrpcPolledFdFactoryWindows>(
+      std::move(work_serializer));
 }
 
 }  // namespace grpc_core
index 7ca5c0e..2d4141c 100644 (file)
@@ -26,6 +26,8 @@
 #include <string.h>
 #include <sys/types.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include <ares.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -38,7 +40,6 @@
 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/host_port.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
@@ -74,6 +75,8 @@ struct grpc_ares_request {
   grpc_error* error;
 };
 
+// TODO(apolcyn): make grpc_ares_hostbyname_request a sub-class
+// of GrpcAresQuery.
 typedef struct grpc_ares_hostbyname_request {
   /** following members are set in create_hostbyname_request_locked
    */
@@ -85,27 +88,47 @@ typedef struct grpc_ares_hostbyname_request {
   uint16_t port;
   /** is it a grpclb address */
   bool is_balancer;
+  /** for logging and errors: the query type ("A" or "AAAA") */
+  const char* qtype;
 } grpc_ares_hostbyname_request;
 
+static void grpc_ares_request_ref_locked(grpc_ares_request* r);
+static void grpc_ares_request_unref_locked(grpc_ares_request* r);
+
+// TODO(apolcyn): as a part of C++-ification, find a way to
+// organize per-query and per-resolution information in such a way
+// that doesn't involve allocating a number of different data
+// structures.
+class GrpcAresQuery {
+ public:
+  explicit GrpcAresQuery(grpc_ares_request* r, const std::string& name)
+      : r_(r), name_(name) {
+    grpc_ares_request_ref_locked(r_);
+  }
+
+  ~GrpcAresQuery() { grpc_ares_request_unref_locked(r_); }
+
+  grpc_ares_request* parent_request() { return r_; }
+
+  const std::string& name() { return name_; }
+
+ private:
+  /* the top level request instance */
+  grpc_ares_request* r_;
+  /** for logging and errors */
+  const std::string name_;
+};
+
 static void log_address_sorting_list(const grpc_ares_request* r,
                                      const ServerAddressList& addresses,
                                      const char* input_output_str) {
   for (size_t i = 0; i < addresses.size(); i++) {
-    char* addr_str;
-    if (grpc_sockaddr_to_string(&addr_str, &addresses[i].address(), true)) {
-      gpr_log(
-          GPR_INFO,
-          "(c-ares resolver) request:%p c-ares address sorting: %s[%" PRIuPTR
-          "]=%s",
-          r, input_output_str, i, addr_str);
-      gpr_free(addr_str);
-    } else {
-      gpr_log(
-          GPR_INFO,
-          "(c-ares resolver) request:%p c-ares address sorting: %s[%" PRIuPTR
-          "]=<unprintable>",
-          r, input_output_str, i);
-    }
+    std::string addr_str =
+        grpc_sockaddr_to_string(&addresses[i].address(), true);
+    gpr_log(GPR_INFO,
+            "(c-ares resolver) request:%p c-ares address sorting: %s[%" PRIuPTR
+            "]=%s",
+            r, input_output_str, i, addr_str.c_str());
   }
 }
 
@@ -158,22 +181,30 @@ void grpc_ares_complete_request_locked(grpc_ares_request* r) {
     // TODO(apolcyn): allow c-ares to return a service config
     // with no addresses along side it
   }
+  if (r->balancer_addresses_out != nullptr) {
+    ServerAddressList* balancer_addresses = r->balancer_addresses_out->get();
+    if (balancer_addresses != nullptr) {
+      grpc_cares_wrapper_address_sorting_sort(r, balancer_addresses);
+    }
+  }
   grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, r->error);
 }
 
+/* Note that the returned object takes a reference to qtype, so
+ * qtype must outlive it. */
 static grpc_ares_hostbyname_request* create_hostbyname_request_locked(
-    grpc_ares_request* parent_request, char* host, uint16_t port,
-    bool is_balancer) {
+    grpc_ares_request* parent_request, const char* host, uint16_t port,
+    bool is_balancer, const char* qtype) {
   GRPC_CARES_TRACE_LOG(
       "request:%p create_hostbyname_request_locked host:%s port:%d "
-      "is_balancer:%d",
-      parent_request, host, port, is_balancer);
-  grpc_ares_hostbyname_request* hr = static_cast<grpc_ares_hostbyname_request*>(
-      gpr_zalloc(sizeof(grpc_ares_hostbyname_request)));
+      "is_balancer:%d qtype:%s",
+      parent_request, host, port, is_balancer, qtype);
+  grpc_ares_hostbyname_request* hr = new grpc_ares_hostbyname_request();
   hr->parent_request = parent_request;
   hr->host = gpr_strdup(host);
   hr->port = port;
   hr->is_balancer = is_balancer;
+  hr->qtype = qtype;
   grpc_ares_request_ref_locked(parent_request);
   return hr;
 }
@@ -182,7 +213,7 @@ static void destroy_hostbyname_request_locked(
     grpc_ares_hostbyname_request* hr) {
   grpc_ares_request_unref_locked(hr->parent_request);
   gpr_free(hr->host);
-  gpr_free(hr);
+  delete hr;
 }
 
 static void on_hostbyname_done_locked(void* arg, int status, int /*timeouts*/,
@@ -192,8 +223,8 @@ static void on_hostbyname_done_locked(void* arg, int status, int /*timeouts*/,
   grpc_ares_request* r = hr->parent_request;
   if (status == ARES_SUCCESS) {
     GRPC_CARES_TRACE_LOG(
-        "request:%p on_hostbyname_done_locked host=%s ARES_SUCCESS", r,
-        hr->host);
+        "request:%p on_hostbyname_done_locked qtype=%s host=%s ARES_SUCCESS", r,
+        hr->qtype, hr->host);
     std::unique_ptr<ServerAddressList>* address_list_ptr =
         hr->is_balancer ? r->balancer_addresses_out : r->addresses_out;
     if (*address_list_ptr == nullptr) {
@@ -201,7 +232,7 @@ static void on_hostbyname_done_locked(void* arg, int status, int /*timeouts*/,
     }
     ServerAddressList& addresses = **address_list_ptr;
     for (size_t i = 0; hostent->h_addr_list[i] != nullptr; ++i) {
-      grpc_core::InlinedVector<grpc_arg, 1> args_to_add;
+      absl::InlinedVector<grpc_arg, 1> args_to_add;
       if (hr->is_balancer) {
         args_to_add.emplace_back(
             grpc_core::CreateGrpclbBalancerNameArg(hr->host));
@@ -247,10 +278,12 @@ static void on_hostbyname_done_locked(void* arg, int status, int /*timeouts*/,
     }
   } else {
     char* error_msg;
-    gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
-                 ares_strerror(status));
-    GRPC_CARES_TRACE_LOG("request:%p on_hostbyname_done_locked host=%s %s", r,
-                         hr->host, error_msg);
+    gpr_asprintf(&error_msg,
+                 "C-ares status is not ARES_SUCCESS "
+                 "qtype=%s name=%s is_balancer=%d: %s",
+                 hr->qtype, hr->host, hr->is_balancer, ares_strerror(status));
+    GRPC_CARES_TRACE_LOG("request:%p on_hostbyname_done_locked: %s", r,
+                         error_msg);
     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
     gpr_free(error_msg);
     r->error = grpc_error_add_child(error, r->error);
@@ -260,9 +293,12 @@ static void on_hostbyname_done_locked(void* arg, int status, int /*timeouts*/,
 
 static void on_srv_query_done_locked(void* arg, int status, int /*timeouts*/,
                                      unsigned char* abuf, int alen) {
-  grpc_ares_request* r = static_cast<grpc_ares_request*>(arg);
+  GrpcAresQuery* q = static_cast<GrpcAresQuery*>(arg);
+  grpc_ares_request* r = q->parent_request();
   if (status == ARES_SUCCESS) {
-    GRPC_CARES_TRACE_LOG("request:%p on_srv_query_done_locked ARES_SUCCESS", r);
+    GRPC_CARES_TRACE_LOG(
+        "request:%p on_srv_query_done_locked name=%s ARES_SUCCESS", r,
+        q->name().c_str());
     struct ares_srv_reply* reply;
     const int parse_status = ares_parse_srv_reply(abuf, alen, &reply);
     GRPC_CARES_TRACE_LOG("request:%p ares_parse_srv_reply: %d", r,
@@ -274,12 +310,13 @@ static void on_srv_query_done_locked(void* arg, int status, int /*timeouts*/,
            srv_it = srv_it->next) {
         if (grpc_ares_query_ipv6()) {
           grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked(
-              r, srv_it->host, htons(srv_it->port), true /* is_balancer */);
+              r, srv_it->host, htons(srv_it->port), true /* is_balancer */,
+              "AAAA");
           ares_gethostbyname(*channel, hr->host, AF_INET6,
                              on_hostbyname_done_locked, hr);
         }
         grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked(
-            r, srv_it->host, htons(srv_it->port), true /* is_balancer */);
+            r, srv_it->host, htons(srv_it->port), true /* is_balancer */, "A");
         ares_gethostbyname(*channel, hr->host, AF_INET,
                            on_hostbyname_done_locked, hr);
         grpc_ares_ev_driver_start_locked(r->ev_driver);
@@ -290,15 +327,17 @@ static void on_srv_query_done_locked(void* arg, int status, int /*timeouts*/,
     }
   } else {
     char* error_msg;
-    gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
-                 ares_strerror(status));
-    GRPC_CARES_TRACE_LOG("request:%p on_srv_query_done_locked %s", r,
+    gpr_asprintf(&error_msg,
+                 "C-ares status is not ARES_SUCCESS "
+                 "qtype=SRV name=%s: %s",
+                 q->name().c_str(), ares_strerror(status));
+    GRPC_CARES_TRACE_LOG("request:%p on_srv_query_done_locked: %s", r,
                          error_msg);
     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
     gpr_free(error_msg);
     r->error = grpc_error_add_child(error, r->error);
   }
-  grpc_ares_request_unref_locked(r);
+  delete q;
 }
 
 static const char g_service_config_attribute_prefix[] = "grpc_config=";
@@ -306,13 +345,15 @@ static const char g_service_config_attribute_prefix[] = "grpc_config=";
 static void on_txt_done_locked(void* arg, int status, int /*timeouts*/,
                                unsigned char* buf, int len) {
   char* error_msg;
-  grpc_ares_request* r = static_cast<grpc_ares_request*>(arg);
+  GrpcAresQuery* q = static_cast<GrpcAresQuery*>(arg);
+  grpc_ares_request* r = q->parent_request();
   const size_t prefix_len = sizeof(g_service_config_attribute_prefix) - 1;
   struct ares_txt_ext* result = nullptr;
   struct ares_txt_ext* reply = nullptr;
   grpc_error* error = GRPC_ERROR_NONE;
   if (status != ARES_SUCCESS) goto fail;
-  GRPC_CARES_TRACE_LOG("request:%p on_txt_done_locked ARES_SUCCESS", r);
+  GRPC_CARES_TRACE_LOG("request:%p on_txt_done_locked name=%s ARES_SUCCESS", r,
+                       q->name().c_str());
   status = ares_parse_txt_reply_ext(buf, len, &reply);
   if (status != ARES_SUCCESS) goto fail;
   // Find service config in TXT record.
@@ -347,43 +388,47 @@ static void on_txt_done_locked(void* arg, int status, int /*timeouts*/,
   ares_free_data(reply);
   goto done;
 fail:
-  gpr_asprintf(&error_msg, "C-ares TXT lookup status is not ARES_SUCCESS: %s",
-               ares_strerror(status));
+  gpr_asprintf(&error_msg,
+               "C-ares status is not ARES_SUCCESS "
+               "qtype=TXT name=%s: %s",
+               q->name().c_str(), ares_strerror(status));
   error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
   GRPC_CARES_TRACE_LOG("request:%p on_txt_done_locked %s", r, error_msg);
   gpr_free(error_msg);
   r->error = grpc_error_add_child(error, r->error);
 done:
-  grpc_ares_request_unref_locked(r);
+  delete q;
 }
 
 void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
     grpc_ares_request* r, const char* dns_server, const char* name,
     const char* default_port, grpc_pollset_set* interested_parties,
-    int query_timeout_ms, grpc_core::Combiner* combiner) {
+    int query_timeout_ms,
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer) {
   grpc_error* error = GRPC_ERROR_NONE;
   grpc_ares_hostbyname_request* hr = nullptr;
   ares_channel* channel = nullptr;
   /* parse name, splitting it into host and port parts */
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
+  std::string host;
+  std::string port;
   grpc_core::SplitHostPort(name, &host, &port);
-  if (host == nullptr) {
+  if (host.empty()) {
     error = grpc_error_set_str(
         GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
         GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
     goto error_cleanup;
-  } else if (port == nullptr) {
+  } else if (port.empty()) {
     if (default_port == nullptr) {
       error = grpc_error_set_str(
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
       goto error_cleanup;
     }
-    port.reset(gpr_strdup(default_port));
+    port = default_port;
   }
   error = grpc_ares_ev_driver_create_locked(&r->ev_driver, interested_parties,
-                                            query_timeout_ms, combiner, r);
+                                            query_timeout_ms,
+                                            std::move(work_serializer), r);
   if (error != GRPC_ERROR_NONE) goto error_cleanup;
   channel = grpc_ares_ev_driver_get_channel_locked(r->ev_driver);
   // If dns_server is specified, use it.
@@ -424,32 +469,32 @@ void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
   }
   r->pending_queries = 1;
   if (grpc_ares_query_ipv6()) {
-    hr = create_hostbyname_request_locked(r, host.get(),
-                                          grpc_strhtons(port.get()),
-                                          /*is_balancer=*/false);
+    hr = create_hostbyname_request_locked(r, host.c_str(),
+                                          grpc_strhtons(port.c_str()),
+                                          /*is_balancer=*/false, "AAAA");
     ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked,
                        hr);
   }
-  hr =
-      create_hostbyname_request_locked(r, host.get(), grpc_strhtons(port.get()),
-                                       /*is_balancer=*/false);
+  hr = create_hostbyname_request_locked(r, host.c_str(),
+                                        grpc_strhtons(port.c_str()),
+                                        /*is_balancer=*/false, "A");
   ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_locked,
                      hr);
   if (r->balancer_addresses_out != nullptr) {
     /* Query the SRV record */
-    grpc_ares_request_ref_locked(r);
     char* service_name;
-    gpr_asprintf(&service_name, "_grpclb._tcp.%s", host.get());
+    gpr_asprintf(&service_name, "_grpclb._tcp.%s", host.c_str());
+    GrpcAresQuery* srv_query = new GrpcAresQuery(r, service_name);
     ares_query(*channel, service_name, ns_c_in, ns_t_srv,
-               on_srv_query_done_locked, r);
+               on_srv_query_done_locked, srv_query);
     gpr_free(service_name);
   }
   if (r->service_config_json_out != nullptr) {
-    grpc_ares_request_ref_locked(r);
     char* config_name;
-    gpr_asprintf(&config_name, "_grpc_config.%s", host.get());
+    gpr_asprintf(&config_name, "_grpc_config.%s", host.c_str());
+    GrpcAresQuery* txt_query = new GrpcAresQuery(r, config_name);
     ares_search(*channel, config_name, ns_c_in, ns_t_txt, on_txt_done_locked,
-                r);
+                txt_query);
     gpr_free(config_name);
   }
   grpc_ares_ev_driver_start_locked(r->ev_driver);
@@ -462,18 +507,16 @@ error_cleanup:
 
 static bool inner_resolve_as_ip_literal_locked(
     const char* name, const char* default_port,
-    std::unique_ptr<grpc_core::ServerAddressList>* addrs,
-    grpc_core::UniquePtr<char>* host, grpc_core::UniquePtr<char>* port,
-    grpc_core::UniquePtr<char>* hostport) {
-  grpc_core::SplitHostPort(name, host, port);
-  if (*host == nullptr) {
+    std::unique_ptr<grpc_core::ServerAddressList>* addrs, std::string* host,
+    std::string* port, std::string* hostport) {
+  if (!grpc_core::SplitHostPort(name, host, port)) {
     gpr_log(GPR_ERROR,
             "Failed to parse %s to host:port while attempting to resolve as ip "
             "literal.",
             name);
     return false;
   }
-  if (*port == nullptr) {
+  if (port->empty()) {
     if (default_port == nullptr) {
       gpr_log(GPR_ERROR,
               "No port or default port for %s while attempting to resolve as "
@@ -481,13 +524,13 @@ static bool inner_resolve_as_ip_literal_locked(
               name);
       return false;
     }
-    port->reset(gpr_strdup(default_port));
+    *port = default_port;
   }
   grpc_resolved_address addr;
-  GPR_ASSERT(grpc_core::JoinHostPort(hostport, host->get(), atoi(port->get())));
-  if (grpc_parse_ipv4_hostport(hostport->get(), &addr,
+  *hostport = grpc_core::JoinHostPort(*host, atoi(port->c_str()));
+  if (grpc_parse_ipv4_hostport(hostport->c_str(), &addr,
                                false /* log errors */) ||
-      grpc_parse_ipv6_hostport(hostport->get(), &addr,
+      grpc_parse_ipv6_hostport(hostport->c_str(), &addr,
                                false /* log errors */)) {
     GPR_ASSERT(*addrs == nullptr);
     *addrs = absl::make_unique<ServerAddressList>();
@@ -500,22 +543,21 @@ static bool inner_resolve_as_ip_literal_locked(
 static bool resolve_as_ip_literal_locked(
     const char* name, const char* default_port,
     std::unique_ptr<grpc_core::ServerAddressList>* addrs) {
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
-  grpc_core::UniquePtr<char> hostport;
+  std::string host;
+  std::string port;
+  std::string hostport;
   bool out = inner_resolve_as_ip_literal_locked(name, default_port, addrs,
                                                 &host, &port, &hostport);
   return out;
 }
 
-static bool target_matches_localhost_inner(const char* name,
-                                           grpc_core::UniquePtr<char>* host,
-                                           grpc_core::UniquePtr<char>* port) {
+static bool target_matches_localhost_inner(const char* name, std::string* host,
+                                           std::string* port) {
   if (!grpc_core::SplitHostPort(name, host, port)) {
     gpr_log(GPR_ERROR, "Unable to split host and port for name: %s", name);
     return false;
   }
-  if (gpr_stricmp(host->get(), "localhost") == 0) {
+  if (gpr_stricmp(host->c_str(), "localhost") == 0) {
     return true;
   } else {
     return false;
@@ -523,25 +565,25 @@ static bool target_matches_localhost_inner(const char* name,
 }
 
 static bool target_matches_localhost(const char* name) {
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
+  std::string host;
+  std::string port;
   return target_matches_localhost_inner(name, &host, &port);
 }
 
 #ifdef GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY
 static bool inner_maybe_resolve_localhost_manually_locked(
     const grpc_ares_request* r, const char* name, const char* default_port,
-    std::unique_ptr<grpc_core::ServerAddressList>* addrs,
-    grpc_core::UniquePtr<char>* host, grpc_core::UniquePtr<char>* port) {
+    std::unique_ptr<grpc_core::ServerAddressList>* addrs, std::string* host,
+    std::string* port) {
   grpc_core::SplitHostPort(name, host, port);
-  if (*host == nullptr) {
+  if (host->empty()) {
     gpr_log(GPR_ERROR,
             "Failed to parse %s into host:port during manual localhost "
             "resolution check.",
             name);
     return false;
   }
-  if (*port == nullptr) {
+  if (port->empty()) {
     if (default_port == nullptr) {
       gpr_log(GPR_ERROR,
               "No port or default port for %s during manual localhost "
@@ -549,12 +591,12 @@ static bool inner_maybe_resolve_localhost_manually_locked(
               name);
       return false;
     }
-    port->reset(gpr_strdup(default_port));
+    *port = default_port;
   }
-  if (gpr_stricmp(host->get(), "localhost") == 0) {
+  if (gpr_stricmp(host->c_str(), "localhost") == 0) {
     GPR_ASSERT(*addrs == nullptr);
     *addrs = absl::make_unique<grpc_core::ServerAddressList>();
-    uint16_t numeric_port = grpc_strhtons(port->get());
+    uint16_t numeric_port = grpc_strhtons(port->c_str());
     // Append the ipv6 loopback address.
     struct sockaddr_in6 ipv6_loopback_addr;
     memset(&ipv6_loopback_addr, 0, sizeof(ipv6_loopback_addr));
@@ -582,8 +624,8 @@ static bool inner_maybe_resolve_localhost_manually_locked(
 static bool grpc_ares_maybe_resolve_localhost_manually_locked(
     const grpc_ares_request* r, const char* name, const char* default_port,
     std::unique_ptr<grpc_core::ServerAddressList>* addrs) {
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
+  std::string host;
+  std::string port;
   return inner_maybe_resolve_localhost_manually_locked(r, name, default_port,
                                                        addrs, &host, &port);
 }
@@ -602,7 +644,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
     std::unique_ptr<grpc_core::ServerAddressList>* addrs,
     std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs,
     char** service_config_json, int query_timeout_ms,
-    grpc_core::Combiner* combiner) {
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer) {
   grpc_ares_request* r =
       static_cast<grpc_ares_request*>(gpr_zalloc(sizeof(grpc_ares_request)));
   r->ev_driver = nullptr;
@@ -637,7 +679,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
   // Look up name using c-ares lib.
   grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
       r, dns_server, name, default_port, interested_parties, query_timeout_ms,
-      combiner);
+      std::move(work_serializer));
   return r;
 }
 
@@ -647,7 +689,8 @@ grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
     std::unique_ptr<grpc_core::ServerAddressList>* addrs,
     std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs,
     char** service_config_json, int query_timeout_ms,
-    grpc_core::Combiner* combiner) = grpc_dns_lookup_ares_locked_impl;
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer) =
+    grpc_dns_lookup_ares_locked_impl;
 
 static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) {
   GPR_ASSERT(r != nullptr);
@@ -687,8 +730,8 @@ void grpc_ares_cleanup(void) {}
  */
 
 typedef struct grpc_resolve_address_ares_request {
-  /* combiner that queries and related callbacks run under */
-  grpc_core::Combiner* combiner;
+  /* work_serializer that queries and related callbacks run under */
+  std::shared_ptr<grpc_core::WorkSerializer> work_serializer;
   /** the pointer to receive the resolved addresses */
   grpc_resolved_addresses** addrs_out;
   /** currently resolving addresses */
@@ -708,9 +751,8 @@ typedef struct grpc_resolve_address_ares_request {
   grpc_ares_request* ares_request = nullptr;
 } grpc_resolve_address_ares_request;
 
-static void on_dns_lookup_done_locked(void* arg, grpc_error* error) {
-  grpc_resolve_address_ares_request* r =
-      static_cast<grpc_resolve_address_ares_request*>(arg);
+static void on_dns_lookup_done_locked(grpc_resolve_address_ares_request* r,
+                                      grpc_error* error) {
   gpr_free(r->ares_request);
   grpc_resolved_addresses** resolved_addresses = r->addrs_out;
   if (r->addresses == nullptr || r->addresses->empty()) {
@@ -727,22 +769,19 @@ static void on_dns_lookup_done_locked(void* arg, grpc_error* error) {
              sizeof(grpc_resolved_address));
     }
   }
-  grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_resolve_address_done,
-                          GRPC_ERROR_REF(error));
-  GRPC_COMBINER_UNREF(r->combiner, "on_dns_lookup_done_cb");
+  grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_resolve_address_done, error);
   delete r;
 }
 
 static void on_dns_lookup_done(void* arg, grpc_error* error) {
   grpc_resolve_address_ares_request* r =
       static_cast<grpc_resolve_address_ares_request*>(arg);
-  r->combiner->Run(GRPC_CLOSURE_INIT(&r->on_dns_lookup_done_locked,
-                                     on_dns_lookup_done_locked, r, nullptr),
-                   GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  r->work_serializer->Run([r, error]() { on_dns_lookup_done_locked(r, error); },
+                          DEBUG_LOCATION);
 }
 
-static void grpc_resolve_address_invoke_dns_lookup_ares_locked(
-    void* arg, grpc_error* /*unused_error*/) {
+static void grpc_resolve_address_invoke_dns_lookup_ares_locked(void* arg) {
   grpc_resolve_address_ares_request* r =
       static_cast<grpc_resolve_address_ares_request*>(arg);
   GRPC_CLOSURE_INIT(&r->on_dns_lookup_done_locked, on_dns_lookup_done, r,
@@ -751,7 +790,7 @@ static void grpc_resolve_address_invoke_dns_lookup_ares_locked(
       nullptr /* dns_server */, r->name, r->default_port, r->interested_parties,
       &r->on_dns_lookup_done_locked, &r->addresses,
       nullptr /* balancer_addresses */, nullptr /* service_config_json */,
-      GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS, r->combiner);
+      GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS, r->work_serializer);
 }
 
 static void grpc_resolve_address_ares_impl(const char* name,
@@ -761,16 +800,15 @@ static void grpc_resolve_address_ares_impl(const char* name,
                                            grpc_resolved_addresses** addrs) {
   grpc_resolve_address_ares_request* r =
       new grpc_resolve_address_ares_request();
-  r->combiner = grpc_combiner_create();
+  r->work_serializer = std::make_shared<grpc_core::WorkSerializer>();
   r->addrs_out = addrs;
   r->on_resolve_address_done = on_done;
   r->name = name;
   r->default_port = default_port;
   r->interested_parties = interested_parties;
-  r->combiner->Run(
-      GRPC_CLOSURE_CREATE(grpc_resolve_address_invoke_dns_lookup_ares_locked, r,
-                          nullptr),
-      GRPC_ERROR_NONE);
+  r->work_serializer->Run(
+      [r]() { grpc_resolve_address_invoke_dns_lookup_ares_locked(r); },
+      DEBUG_LOCATION);
 }
 
 void (*grpc_resolve_address_ares)(
index b14e21e..ddce754 100644 (file)
@@ -25,6 +25,7 @@
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/polling_entity.h"
 #include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 
 #define GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS 120000
 
@@ -66,7 +67,7 @@ extern grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
     std::unique_ptr<grpc_core::ServerAddressList>* addresses,
     std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses,
     char** service_config_json, int query_timeout_ms,
-    grpc_core::Combiner* combiner);
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer);
 
 /* Cancel the pending grpc_ares_request \a request */
 extern void (*grpc_cancel_ares_request_locked)(grpc_ares_request* request);
index be880f6..2049f37 100644 (file)
@@ -32,7 +32,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
     std::unique_ptr<grpc_core::ServerAddressList>* addrs,
     std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs,
     char** service_config_json, int query_timeout_ms,
-    grpc_core::Combiner* combiner) {
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer) {
   return NULL;
 }
 
@@ -42,7 +42,8 @@ grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
     std::unique_ptr<grpc_core::ServerAddressList>* addrs,
     std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs,
     char** service_config_json, int query_timeout_ms,
-    grpc_core::Combiner* combiner) = grpc_dns_lookup_ares_locked_impl;
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer) =
+    grpc_dns_lookup_ares_locked_impl;
 
 static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) {}
 
index 3b5b902..e98a3e6 100644 (file)
@@ -33,9 +33,9 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/manual_constructor.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 
 #define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1
 #define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6
@@ -67,9 +67,9 @@ class NativeDnsResolver : public Resolver {
   void StartResolvingLocked();
 
   static void OnNextResolution(void* arg, grpc_error* error);
-  static void OnNextResolutionLocked(void* arg, grpc_error* error);
+  void OnNextResolutionLocked(grpc_error* error);
   static void OnResolved(void* arg, grpc_error* error);
-  static void OnResolvedLocked(void* arg, grpc_error* error);
+  void OnResolvedLocked(grpc_error* error);
 
   /// name to resolve
   char* name_to_resolve_ = nullptr;
@@ -97,7 +97,7 @@ class NativeDnsResolver : public Resolver {
 };
 
 NativeDnsResolver::NativeDnsResolver(ResolverArgs args)
-    : Resolver(args.combiner, std::move(args.result_handler)),
+    : Resolver(std::move(args.work_serializer), std::move(args.result_handler)),
       backoff_(
           BackOff::Options()
               .set_initial_backoff(GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS *
@@ -149,79 +149,76 @@ void NativeDnsResolver::ShutdownLocked() {
 
 void NativeDnsResolver::OnNextResolution(void* arg, grpc_error* error) {
   NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg);
-  r->combiner()->Run(
-      GRPC_CLOSURE_INIT(&r->on_next_resolution_,
-                        NativeDnsResolver::OnNextResolutionLocked, r, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  r->work_serializer()->Run([r, error]() { r->OnNextResolutionLocked(error); },
+                            DEBUG_LOCATION);
 }
 
-void NativeDnsResolver::OnNextResolutionLocked(void* arg, grpc_error* error) {
-  NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg);
-  r->have_next_resolution_timer_ = false;
-  if (error == GRPC_ERROR_NONE && !r->resolving_) {
-    r->StartResolvingLocked();
+void NativeDnsResolver::OnNextResolutionLocked(grpc_error* error) {
+  have_next_resolution_timer_ = false;
+  if (error == GRPC_ERROR_NONE && !resolving_) {
+    StartResolvingLocked();
   }
-  r->Unref(DEBUG_LOCATION, "retry-timer");
+  Unref(DEBUG_LOCATION, "retry-timer");
+  GRPC_ERROR_UNREF(error);
 }
 
 void NativeDnsResolver::OnResolved(void* arg, grpc_error* error) {
   NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg);
-  r->combiner()->Run(
-      GRPC_CLOSURE_INIT(&r->on_resolved_, NativeDnsResolver::OnResolvedLocked,
-                        r, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // owned by lambda
+  r->work_serializer()->Run([r, error]() { r->OnResolvedLocked(error); },
+                            DEBUG_LOCATION);
 }
 
-void NativeDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
-  NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg);
-  GPR_ASSERT(r->resolving_);
-  r->resolving_ = false;
-  if (r->shutdown_) {
-    r->Unref(DEBUG_LOCATION, "dns-resolving");
+void NativeDnsResolver::OnResolvedLocked(grpc_error* error) {
+  GPR_ASSERT(resolving_);
+  resolving_ = false;
+  if (shutdown_) {
+    Unref(DEBUG_LOCATION, "dns-resolving");
+    GRPC_ERROR_UNREF(error);
     return;
   }
-  if (r->addresses_ != nullptr) {
+  if (addresses_ != nullptr) {
     Result result;
-    for (size_t i = 0; i < r->addresses_->naddrs; ++i) {
-      result.addresses.emplace_back(&r->addresses_->addrs[i].addr,
-                                    r->addresses_->addrs[i].len,
+    for (size_t i = 0; i < addresses_->naddrs; ++i) {
+      result.addresses.emplace_back(&addresses_->addrs[i].addr,
+                                    addresses_->addrs[i].len,
                                     nullptr /* args */);
     }
-    grpc_resolved_addresses_destroy(r->addresses_);
-    result.args = grpc_channel_args_copy(r->channel_args_);
-    r->result_handler()->ReturnResult(std::move(result));
+    grpc_resolved_addresses_destroy(addresses_);
+    result.args = grpc_channel_args_copy(channel_args_);
+    result_handler()->ReturnResult(std::move(result));
     // Reset backoff state so that we start from the beginning when the
     // next request gets triggered.
-    r->backoff_.Reset();
+    backoff_.Reset();
   } else {
     gpr_log(GPR_INFO, "dns resolution failed (will retry): %s",
             grpc_error_string(error));
     // Return transient error.
-    r->result_handler()->ReturnError(grpc_error_set_int(
+    result_handler()->ReturnError(grpc_error_set_int(
         GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
             "DNS resolution failed", &error, 1),
         GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
     // Set up for retry.
-    grpc_millis next_try = r->backoff_.NextAttemptTime();
+    grpc_millis next_try = backoff_.NextAttemptTime();
     grpc_millis timeout = next_try - ExecCtx::Get()->Now();
-    GPR_ASSERT(!r->have_next_resolution_timer_);
-    r->have_next_resolution_timer_ = true;
+    GPR_ASSERT(!have_next_resolution_timer_);
+    have_next_resolution_timer_ = true;
     // TODO(roth): We currently deal with this ref manually.  Once the
     // new closure API is done, find a way to track this ref with the timer
     // callback as part of the type system.
-    r->Ref(DEBUG_LOCATION, "next_resolution_timer").release();
+    Ref(DEBUG_LOCATION, "next_resolution_timer").release();
     if (timeout > 0) {
       gpr_log(GPR_DEBUG, "retrying in %" PRId64 " milliseconds", timeout);
     } else {
       gpr_log(GPR_DEBUG, "retrying immediately");
     }
-    GRPC_CLOSURE_INIT(&r->on_next_resolution_,
-                      NativeDnsResolver::OnNextResolution, r,
-                      grpc_schedule_on_exec_ctx);
-    grpc_timer_init(&r->next_resolution_timer_, next_try,
-                    &r->on_next_resolution_);
+    GRPC_CLOSURE_INIT(&on_next_resolution_, NativeDnsResolver::OnNextResolution,
+                      this, grpc_schedule_on_exec_ctx);
+    grpc_timer_init(&next_resolution_timer_, next_try, &on_next_resolution_);
   }
-  r->Unref(DEBUG_LOCATION, "dns-resolving");
+  Unref(DEBUG_LOCATION, "dns-resolving");
+  GRPC_ERROR_UNREF(error);
 }
 
 void NativeDnsResolver::MaybeStartResolvingLocked() {
index 3066689..499d14f 100644 (file)
@@ -35,9 +35,9 @@
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/iomgr/closure.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/unix_sockets_posix.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 
@@ -57,20 +57,15 @@ class FakeResolver : public Resolver {
 
  private:
   friend class FakeResolverResponseGenerator;
+  friend class FakeResolverResponseSetter;
 
   virtual ~FakeResolver();
 
-  void ShutdownLocked() override {
-    shutdown_ = true;
-    if (response_generator_ != nullptr) {
-      response_generator_->SetFakeResolver(nullptr);
-      response_generator_.reset();
-    }
-  }
+  void ShutdownLocked() override;
 
   void MaybeSendResultLocked();
 
-  static void ReturnReresolutionResult(void* arg, grpc_error* error);
+  void ReturnReresolutionResult();
 
   // passed-in parameters
   grpc_channel_args* channel_args_ = nullptr;
@@ -90,12 +85,11 @@ class FakeResolver : public Resolver {
   // if true, return failure
   bool return_failure_ = false;
   // pending re-resolution
-  grpc_closure reresolution_closure_;
   bool reresolution_closure_pending_ = false;
 };
 
 FakeResolver::FakeResolver(ResolverArgs args)
-    : Resolver(args.combiner, std::move(args.result_handler)),
+    : Resolver(std::move(args.work_serializer), std::move(args.result_handler)),
       response_generator_(
           FakeResolverResponseGenerator::GetFromArgs(args.args)) {
   // Channels sharing the same subchannels may have different resolver response
@@ -127,13 +121,20 @@ void FakeResolver::RequestReresolutionLocked() {
     if (!reresolution_closure_pending_) {
       reresolution_closure_pending_ = true;
       Ref().release();  // ref held by closure
-      GRPC_CLOSURE_INIT(&reresolution_closure_, ReturnReresolutionResult, this,
-                        nullptr);
-      combiner()->Run(&reresolution_closure_, GRPC_ERROR_NONE);
+      work_serializer()->Run([this]() { ReturnReresolutionResult(); },
+                             DEBUG_LOCATION);
     }
   }
 }
 
+void FakeResolver::ShutdownLocked() {
+  shutdown_ = true;
+  if (response_generator_ != nullptr) {
+    response_generator_->SetFakeResolver(nullptr);
+    response_generator_.reset();
+  }
+}
+
 void FakeResolver::MaybeSendResultLocked() {
   if (!started_ || shutdown_) return;
   if (return_failure_) {
@@ -159,11 +160,59 @@ void FakeResolver::MaybeSendResultLocked() {
   }
 }
 
-void FakeResolver::ReturnReresolutionResult(void* arg, grpc_error* /*error*/) {
-  FakeResolver* self = static_cast<FakeResolver*>(arg);
-  self->reresolution_closure_pending_ = false;
-  self->MaybeSendResultLocked();
-  self->Unref();
+void FakeResolver::ReturnReresolutionResult() {
+  reresolution_closure_pending_ = false;
+  MaybeSendResultLocked();
+  Unref();
+}
+
+class FakeResolverResponseSetter {
+ public:
+  explicit FakeResolverResponseSetter(RefCountedPtr<FakeResolver> resolver,
+                                      Resolver::Result result,
+                                      bool has_result = false,
+                                      bool immediate = true)
+      : resolver_(std::move(resolver)),
+        result_(std::move(result)),
+        has_result_(has_result),
+        immediate_(immediate) {}
+  void SetResponseLocked();
+  void SetReresolutionResponseLocked();
+  void SetFailureLocked();
+
+ private:
+  RefCountedPtr<FakeResolver> resolver_;
+  Resolver::Result result_;
+  bool has_result_;
+  bool immediate_;
+};
+
+// Deletes object when done
+void FakeResolverResponseSetter::SetReresolutionResponseLocked() {
+  if (!resolver_->shutdown_) {
+    resolver_->reresolution_result_ = std::move(result_);
+    resolver_->has_reresolution_result_ = has_result_;
+  }
+  delete this;
+}
+
+// Deletes object when done
+void FakeResolverResponseSetter::SetResponseLocked() {
+  if (!resolver_->shutdown_) {
+    resolver_->next_result_ = std::move(result_);
+    resolver_->has_next_result_ = true;
+    resolver_->MaybeSendResultLocked();
+  }
+  delete this;
+}
+
+// Deletes object when done
+void FakeResolverResponseSetter::SetFailureLocked() {
+  if (!resolver_->shutdown_) {
+    resolver_->return_failure_ = true;
+    if (immediate_) resolver_->MaybeSendResultLocked();
+  }
+  delete this;
 }
 
 //
@@ -174,26 +223,6 @@ FakeResolverResponseGenerator::FakeResolverResponseGenerator() {}
 
 FakeResolverResponseGenerator::~FakeResolverResponseGenerator() {}
 
-struct SetResponseClosureArg {
-  grpc_closure set_response_closure;
-  RefCountedPtr<FakeResolver> resolver;
-  Resolver::Result result;
-  bool has_result = false;
-  bool immediate = true;
-};
-
-void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
-                                                      grpc_error* /*error*/) {
-  SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
-  auto& resolver = closure_arg->resolver;
-  if (!resolver->shutdown_) {
-    resolver->next_result_ = std::move(closure_arg->result);
-    resolver->has_next_result_ = true;
-    resolver->MaybeSendResultLocked();
-  }
-  delete closure_arg;
-}
-
 void FakeResolverResponseGenerator::SetResponse(Resolver::Result result) {
   RefCountedPtr<FakeResolver> resolver;
   {
@@ -205,24 +234,10 @@ void FakeResolverResponseGenerator::SetResponse(Resolver::Result result) {
     }
     resolver = resolver_->Ref();
   }
-  SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
-  closure_arg->resolver = std::move(resolver);
-  closure_arg->result = std::move(result);
-  closure_arg->resolver->combiner()->Run(
-      GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
-                        closure_arg, nullptr),
-      GRPC_ERROR_NONE);
-}
-
-void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
-    void* arg, grpc_error* /*error*/) {
-  SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
-  auto& resolver = closure_arg->resolver;
-  if (!resolver->shutdown_) {
-    resolver->reresolution_result_ = std::move(closure_arg->result);
-    resolver->has_reresolution_result_ = closure_arg->has_result;
-  }
-  delete closure_arg;
+  FakeResolverResponseSetter* arg =
+      new FakeResolverResponseSetter(resolver, std::move(result));
+  resolver->work_serializer()->Run([arg]() { arg->SetResponseLocked(); },
+                                   DEBUG_LOCATION);
 }
 
 void FakeResolverResponseGenerator::SetReresolutionResponse(
@@ -233,14 +248,10 @@ void FakeResolverResponseGenerator::SetReresolutionResponse(
     GPR_ASSERT(resolver_ != nullptr);
     resolver = resolver_->Ref();
   }
-  SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
-  closure_arg->resolver = std::move(resolver);
-  closure_arg->result = std::move(result);
-  closure_arg->has_result = true;
-  closure_arg->resolver->combiner()->Run(
-      GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
-                        SetReresolutionResponseLocked, closure_arg, nullptr),
-      GRPC_ERROR_NONE);
+  FakeResolverResponseSetter* arg = new FakeResolverResponseSetter(
+      resolver, std::move(result), true /* has_result */);
+  resolver->work_serializer()->Run(
+      [arg]() { arg->SetReresolutionResponseLocked(); }, DEBUG_LOCATION);
 }
 
 void FakeResolverResponseGenerator::UnsetReresolutionResponse() {
@@ -250,23 +261,10 @@ void FakeResolverResponseGenerator::UnsetReresolutionResponse() {
     GPR_ASSERT(resolver_ != nullptr);
     resolver = resolver_->Ref();
   }
-  SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
-  closure_arg->resolver = std::move(resolver);
-  closure_arg->resolver->combiner()->Run(
-      GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
-                        SetReresolutionResponseLocked, closure_arg, nullptr),
-      GRPC_ERROR_NONE);
-}
-
-void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
-                                                     grpc_error* /*error*/) {
-  SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
-  auto& resolver = closure_arg->resolver;
-  if (!resolver->shutdown_) {
-    resolver->return_failure_ = true;
-    if (closure_arg->immediate) resolver->MaybeSendResultLocked();
-  }
-  delete closure_arg;
+  FakeResolverResponseSetter* arg =
+      new FakeResolverResponseSetter(resolver, Resolver::Result());
+  resolver->work_serializer()->Run(
+      [arg]() { arg->SetReresolutionResponseLocked(); }, DEBUG_LOCATION);
 }
 
 void FakeResolverResponseGenerator::SetFailure() {
@@ -276,12 +274,10 @@ void FakeResolverResponseGenerator::SetFailure() {
     GPR_ASSERT(resolver_ != nullptr);
     resolver = resolver_->Ref();
   }
-  SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
-  closure_arg->resolver = std::move(resolver);
-  closure_arg->resolver->combiner()->Run(
-      GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
-                        closure_arg, nullptr),
-      GRPC_ERROR_NONE);
+  FakeResolverResponseSetter* arg =
+      new FakeResolverResponseSetter(resolver, Resolver::Result());
+  resolver->work_serializer()->Run([arg]() { arg->SetFailureLocked(); },
+                                   DEBUG_LOCATION);
 }
 
 void FakeResolverResponseGenerator::SetFailureOnReresolution() {
@@ -291,13 +287,11 @@ void FakeResolverResponseGenerator::SetFailureOnReresolution() {
     GPR_ASSERT(resolver_ != nullptr);
     resolver = resolver_->Ref();
   }
-  SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
-  closure_arg->resolver = std::move(resolver);
-  closure_arg->immediate = false;
-  closure_arg->resolver->combiner()->Run(
-      GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
-                        closure_arg, nullptr),
-      GRPC_ERROR_NONE);
+  FakeResolverResponseSetter* arg = new FakeResolverResponseSetter(
+      resolver, Resolver::Result(), false /* has_result */,
+      false /* immediate */);
+  resolver->work_serializer()->Run([arg]() { arg->SetFailureLocked(); },
+                                   DEBUG_LOCATION);
 }
 
 void FakeResolverResponseGenerator::SetFakeResolver(
@@ -306,13 +300,10 @@ void FakeResolverResponseGenerator::SetFakeResolver(
   resolver_ = std::move(resolver);
   if (resolver_ == nullptr) return;
   if (has_result_) {
-    SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
-    closure_arg->resolver = resolver_->Ref();
-    closure_arg->result = std::move(result_);
-    resolver_->combiner()->Run(
-        GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
-                          closure_arg, nullptr),
-        GRPC_ERROR_NONE);
+    FakeResolverResponseSetter* arg =
+        new FakeResolverResponseSetter(resolver_, std::move(result_));
+    resolver_->work_serializer()->Run([arg]() { arg->SetResponseLocked(); },
+                                      DEBUG_LOCATION);
     has_result_ = false;
   }
 }
index c04c7c3..b9fd90c 100644 (file)
@@ -80,10 +80,6 @@ class FakeResolverResponseGenerator
   // Set the corresponding FakeResolver to this generator.
   void SetFakeResolver(RefCountedPtr<FakeResolver> resolver);
 
-  static void SetResponseLocked(void* arg, grpc_error* error);
-  static void SetReresolutionResponseLocked(void* arg, grpc_error* error);
-  static void SetFailureLocked(void* arg, grpc_error* error);
-
   // Mutex protecting the members below.
   Mutex mu_;
   RefCountedPtr<FakeResolver> resolver_;
index ef13043..20061f8 100644 (file)
@@ -31,9 +31,9 @@
 #include "src/core/ext/filters/client_channel/server_address.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/unix_sockets_posix.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 
@@ -57,7 +57,7 @@ class SockaddrResolver : public Resolver {
 
 SockaddrResolver::SockaddrResolver(ServerAddressList addresses,
                                    ResolverArgs args)
-    : Resolver(args.combiner, std::move(args.result_handler)),
+    : Resolver(std::move(args.work_serializer), std::move(args.result_handler)),
       addresses_(std::move(addresses)),
       channel_args_(grpc_channel_args_copy(args.args)) {}
 
index 95fc153..d3b79e3 100644 (file)
@@ -20,7 +20,6 @@
 
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
 #include "src/core/ext/filters/client_channel/xds/xds_client.h"
-#include "src/core/lib/gprpp/string_view.h"
 
 namespace grpc_core {
 
@@ -35,7 +34,8 @@ namespace {
 class XdsResolver : public Resolver {
  public:
   explicit XdsResolver(ResolverArgs args)
-      : Resolver(args.combiner, std::move(args.result_handler)),
+      : Resolver(std::move(args.work_serializer),
+                 std::move(args.result_handler)),
         args_(grpc_channel_args_copy(args.args)),
         interested_parties_(args.pollset_set) {
     char* path = args.uri->path;
@@ -71,6 +71,7 @@ class XdsResolver : public Resolver {
     void OnServiceConfigChanged(
         RefCountedPtr<ServiceConfig> service_config) override;
     void OnError(grpc_error* error) override;
+    void OnResourceDoesNotExist() override;
 
    private:
     RefCountedPtr<XdsResolver> resolver_;
@@ -109,10 +110,24 @@ void XdsResolver::ServiceConfigWatcher::OnError(grpc_error* error) {
   resolver_->result_handler()->ReturnResult(std::move(result));
 }
 
+void XdsResolver::ServiceConfigWatcher::OnResourceDoesNotExist() {
+  if (resolver_->xds_client_ == nullptr) return;
+  gpr_log(GPR_ERROR,
+          "[xds_resolver %p] LDS/RDS resource does not exist -- returning "
+          "empty service config",
+          resolver_.get());
+  Result result;
+  result.service_config =
+      ServiceConfig::Create("{}", &result.service_config_error);
+  GPR_ASSERT(result.service_config != nullptr);
+  result.args = grpc_channel_args_copy(resolver_->args_);
+  resolver_->result_handler()->ReturnResult(std::move(result));
+}
+
 void XdsResolver::StartLocked() {
   grpc_error* error = GRPC_ERROR_NONE;
   xds_client_ = MakeOrphanable<XdsClient>(
-      combiner(), interested_parties_, server_name_,
+      work_serializer(), interested_parties_, server_name_,
       absl::make_unique<ServiceConfigWatcher>(Ref()), *args_, &error);
   if (error != GRPC_ERROR_NONE) {
     gpr_log(GPR_ERROR,
@@ -129,6 +144,8 @@ void XdsResolver::StartLocked() {
 
 class XdsResolverFactory : public ResolverFactory {
  public:
+  explicit XdsResolverFactory(const char* scheme) : scheme_(scheme) {}
+
   bool IsValidUri(const grpc_uri* uri) const override {
     if (GPR_UNLIKELY(0 != strcmp(uri->authority, ""))) {
       gpr_log(GPR_ERROR, "URI authority not supported");
@@ -142,16 +159,26 @@ class XdsResolverFactory : public ResolverFactory {
     return MakeOrphanable<XdsResolver>(std::move(args));
   }
 
-  const char* scheme() const override { return "xds-experimental"; }
+  const char* scheme() const override { return scheme_; }
+
+ private:
+  const char* scheme_;
 };
 
+constexpr char kXdsScheme[] = "xds";
+constexpr char kXdsExperimentalScheme[] = "xds-experimental";
+
 }  // namespace
 
 }  // namespace grpc_core
 
 void grpc_resolver_xds_init() {
   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
-      absl::make_unique<grpc_core::XdsResolverFactory>());
+      absl::make_unique<grpc_core::XdsResolverFactory>(grpc_core::kXdsScheme));
+  // TODO(roth): Remov this in the 1.31 release.
+  grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
+      absl::make_unique<grpc_core::XdsResolverFactory>(
+          grpc_core::kXdsExperimentalScheme));
 }
 
 void grpc_resolver_xds_shutdown() {}
index b6a1e30..d8dd801 100644 (file)
@@ -38,8 +38,8 @@ struct ResolverArgs {
   const grpc_channel_args* args = nullptr;
   /// Used to drive I/O in the name resolution process.
   grpc_pollset_set* pollset_set = nullptr;
-  /// The combiner under which all resolver calls will be run.
-  Combiner* combiner = nullptr;
+  /// The work_serializer under which all resolver calls will be run.
+  std::shared_ptr<WorkSerializer> work_serializer;
   /// The result handler to be used by the resolver.
   std::unique_ptr<Resolver::ResultHandler> result_handler;
 };
index 4e5bc59..c7f7838 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <string.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -90,7 +92,7 @@ class RegistryState {
   // more factories are needed and the additional allocations are
   // hurting performance (which is unlikely, since these allocations
   // only occur at gRPC initialization time).
-  InlinedVector<std::unique_ptr<ResolverFactory>, 10> factories_;
+  absl::InlinedVector<std::unique_ptr<ResolverFactory>, 10> factories_;
   grpc_core::UniquePtr<char> default_prefix_;
 };
 
@@ -145,7 +147,8 @@ bool ResolverRegistry::IsValidTarget(const char* target) {
 
 OrphanablePtr<Resolver> ResolverRegistry::CreateResolver(
     const char* target, const grpc_channel_args* args,
-    grpc_pollset_set* pollset_set, Combiner* combiner,
+    grpc_pollset_set* pollset_set,
+    std::shared_ptr<WorkSerializer> work_serializer,
     std::unique_ptr<Resolver::ResultHandler> result_handler) {
   GPR_ASSERT(g_state != nullptr);
   grpc_uri* uri = nullptr;
@@ -156,7 +159,7 @@ OrphanablePtr<Resolver> ResolverRegistry::CreateResolver(
   resolver_args.uri = uri;
   resolver_args.args = args;
   resolver_args.pollset_set = pollset_set;
-  resolver_args.combiner = combiner;
+  resolver_args.work_serializer = std::move(work_serializer);
   resolver_args.result_handler = std::move(result_handler);
   OrphanablePtr<Resolver> resolver =
       factory == nullptr ? nullptr
index 718750a..bf34216 100644 (file)
@@ -22,7 +22,6 @@
 #include <grpc/support/port_platform.h>
 
 #include "src/core/ext/filters/client_channel/resolver_factory.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/iomgr/pollset_set.h"
@@ -61,15 +60,16 @@ class ResolverRegistry {
   /// prepends default_prefix to target and tries again.
   /// If a resolver factory is found, uses it to instantiate a resolver and
   /// returns it; otherwise, returns nullptr.
-  /// \a args, \a pollset_set, and \a combiner are passed to the factory's
-  /// \a CreateResolver() method.
-  /// \a args are the channel args to be included in resolver results.
-  /// \a pollset_set is used to drive I/O in the name resolution process.
-  /// \a combiner is the combiner under which all resolver calls will be run.
-  /// \a result_handler is used to return results from the resolver.
+  /// \a args, \a pollset_set, and \a work_serializer are passed to the
+  /// factory's \a CreateResolver() method. \a args are the channel args to be
+  /// included in resolver results. \a pollset_set is used to drive I/O in the
+  /// name resolution process. \a work_serializer is the work_serializer under
+  /// which all resolver calls will be run. \a result_handler is used to return
+  /// results from the resolver.
   static OrphanablePtr<Resolver> CreateResolver(
       const char* target, const grpc_channel_args* args,
-      grpc_pollset_set* pollset_set, Combiner* combiner,
+      grpc_pollset_set* pollset_set,
+      std::shared_ptr<WorkSerializer> work_serializer,
       std::unique_ptr<Resolver::ResultHandler> result_handler);
 
   /// Returns the default authority to pass from a client for \a target.
index d87890d..e7afde9 100644 (file)
@@ -24,6 +24,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "absl/types/optional.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -35,7 +37,6 @@
 #include "src/core/lib/channel/status_util.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/memory.h"
-#include "src/core/lib/gprpp/optional.h"
 #include "src/core/lib/uri/uri_parser.h"
 
 // As per the retry design, we do not allow more than 5 retry attempts.
@@ -53,8 +54,9 @@ size_t ClientChannelServiceConfigParser::ParserIndex() {
 }
 
 void ClientChannelServiceConfigParser::Register() {
-  g_client_channel_service_config_parser_index = ServiceConfig::RegisterParser(
-      absl::make_unique<ClientChannelServiceConfigParser>());
+  g_client_channel_service_config_parser_index =
+      ServiceConfigParser::RegisterParser(
+          absl::make_unique<ClientChannelServiceConfigParser>());
 }
 
 namespace {
@@ -311,14 +313,15 @@ const char* ParseHealthCheckConfig(const Json& field, grpc_error** error) {
 
 }  // namespace
 
-std::unique_ptr<ServiceConfig::ParsedConfig>
+std::unique_ptr<ServiceConfigParser::ParsedConfig>
 ClientChannelServiceConfigParser::ParseGlobalParams(const Json& json,
                                                     grpc_error** error) {
   GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
   std::vector<grpc_error*> error_list;
   RefCountedPtr<LoadBalancingPolicy::Config> parsed_lb_config;
   std::string lb_policy_name;
-  Optional<ClientChannelGlobalParsedConfig::RetryThrottling> retry_throttling;
+  absl::optional<ClientChannelGlobalParsedConfig::RetryThrottling>
+      retry_throttling;
   const char* health_check_service_name = nullptr;
   // Parse LB config.
   auto it = json.object_value().find("loadBalancingConfig");
@@ -391,12 +394,12 @@ ClientChannelServiceConfigParser::ParseGlobalParams(const Json& json,
   return nullptr;
 }
 
-std::unique_ptr<ServiceConfig::ParsedConfig>
+std::unique_ptr<ServiceConfigParser::ParsedConfig>
 ClientChannelServiceConfigParser::ParsePerMethodParams(const Json& json,
                                                        grpc_error** error) {
   GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
   std::vector<grpc_error*> error_list;
-  Optional<bool> wait_for_ready;
+  absl::optional<bool> wait_for_ready;
   grpc_millis timeout = 0;
   std::unique_ptr<ClientChannelMethodParsedConfig::RetryPolicy> retry_policy;
   // Parse waitForReady.
index 1f928cf..7e85868 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
+#include "absl/types/optional.h"
+
 #include "src/core/ext/filters/client_channel/lb_policy.h"
 #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
 #include "src/core/ext/filters/client_channel/resolver.h"
 #include "src/core/ext/filters/client_channel/retry_throttle.h"
 #include "src/core/ext/filters/client_channel/service_config.h"
 #include "src/core/lib/channel/status_util.h"
-#include "src/core/lib/gprpp/optional.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/iomgr/exec_ctx.h"  // for grpc_millis
@@ -37,7 +38,8 @@
 namespace grpc_core {
 namespace internal {
 
-class ClientChannelGlobalParsedConfig : public ServiceConfig::ParsedConfig {
+class ClientChannelGlobalParsedConfig
+    : public ServiceConfigParser::ParsedConfig {
  public:
   struct RetryThrottling {
     intptr_t max_milli_tokens = 0;
@@ -47,14 +49,14 @@ class ClientChannelGlobalParsedConfig : public ServiceConfig::ParsedConfig {
   ClientChannelGlobalParsedConfig(
       RefCountedPtr<LoadBalancingPolicy::Config> parsed_lb_config,
       std::string parsed_deprecated_lb_policy,
-      const Optional<RetryThrottling>& retry_throttling,
+      const absl::optional<RetryThrottling>& retry_throttling,
       const char* health_check_service_name)
       : parsed_lb_config_(std::move(parsed_lb_config)),
         parsed_deprecated_lb_policy_(std::move(parsed_deprecated_lb_policy)),
         retry_throttling_(retry_throttling),
         health_check_service_name_(health_check_service_name) {}
 
-  Optional<RetryThrottling> retry_throttling() const {
+  absl::optional<RetryThrottling> retry_throttling() const {
     return retry_throttling_;
   }
 
@@ -73,11 +75,12 @@ class ClientChannelGlobalParsedConfig : public ServiceConfig::ParsedConfig {
  private:
   RefCountedPtr<LoadBalancingPolicy::Config> parsed_lb_config_;
   std::string parsed_deprecated_lb_policy_;
-  Optional<RetryThrottling> retry_throttling_;
+  absl::optional<RetryThrottling> retry_throttling_;
   const char* health_check_service_name_;
 };
 
-class ClientChannelMethodParsedConfig : public ServiceConfig::ParsedConfig {
+class ClientChannelMethodParsedConfig
+    : public ServiceConfigParser::ParsedConfig {
  public:
   struct RetryPolicy {
     int max_attempts = 0;
@@ -88,7 +91,7 @@ class ClientChannelMethodParsedConfig : public ServiceConfig::ParsedConfig {
   };
 
   ClientChannelMethodParsedConfig(grpc_millis timeout,
-                                  const Optional<bool>& wait_for_ready,
+                                  const absl::optional<bool>& wait_for_ready,
                                   std::unique_ptr<RetryPolicy> retry_policy)
       : timeout_(timeout),
         wait_for_ready_(wait_for_ready),
@@ -96,22 +99,22 @@ class ClientChannelMethodParsedConfig : public ServiceConfig::ParsedConfig {
 
   grpc_millis timeout() const { return timeout_; }
 
-  Optional<bool> wait_for_ready() const { return wait_for_ready_; }
+  absl::optional<bool> wait_for_ready() const { return wait_for_ready_; }
 
   const RetryPolicy* retry_policy() const { return retry_policy_.get(); }
 
  private:
   grpc_millis timeout_ = 0;
-  Optional<bool> wait_for_ready_;
+  absl::optional<bool> wait_for_ready_;
   std::unique_ptr<RetryPolicy> retry_policy_;
 };
 
-class ClientChannelServiceConfigParser : public ServiceConfig::Parser {
+class ClientChannelServiceConfigParser : public ServiceConfigParser::Parser {
  public:
-  std::unique_ptr<ServiceConfig::ParsedConfig> ParseGlobalParams(
+  std::unique_ptr<ServiceConfigParser::ParsedConfig> ParseGlobalParams(
       const Json& json, grpc_error** error) override;
 
-  std::unique_ptr<ServiceConfig::ParsedConfig> ParsePerMethodParams(
+  std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
       const Json& json, grpc_error** error) override;
 
   static size_t ParserIndex();
index b05590d..74a5c29 100644 (file)
@@ -26,6 +26,9 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/status_util.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/manual_constructor.h"
 #include "src/core/lib/gprpp/sync.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/polling_entity.h"
 #include "src/core/lib/profiling/timers.h"
@@ -128,7 +129,8 @@ class ResolvingLoadBalancingPolicy::ResolvingControlHelper
     parent_->resolver_->RequestReresolutionLocked();
   }
 
-  void AddTraceEvent(TraceSeverity severity, StringView message) override {
+  void AddTraceEvent(TraceSeverity severity,
+                     absl::string_view message) override {
     if (parent_->resolver_ == nullptr) return;  // Shutting down.
     parent_->channel_control_helper()->AddTraceEvent(severity, message);
   }
@@ -152,7 +154,7 @@ ResolvingLoadBalancingPolicy::ResolvingLoadBalancingPolicy(
       process_resolver_result_user_data_(process_resolver_result_user_data) {
   GPR_ASSERT(process_resolver_result != nullptr);
   resolver_ = ResolverRegistry::CreateResolver(
-      target_uri_.get(), args.args, interested_parties(), combiner(),
+      target_uri_.get(), args.args, interested_parties(), work_serializer(),
       absl::make_unique<ResolverResultHandler>(Ref()));
   // Since the validity of args has been checked when create the channel,
   // CreateResolver() must return a non-null result.
@@ -242,12 +244,11 @@ void ResolvingLoadBalancingPolicy::CreateOrUpdateLbPolicyLocked(
 }
 
 // Creates a new LB policy.
-// Updates trace_strings to indicate what was done.
 OrphanablePtr<LoadBalancingPolicy>
 ResolvingLoadBalancingPolicy::CreateLbPolicyLocked(
     const grpc_channel_args& args) {
   LoadBalancingPolicy::Args lb_policy_args;
-  lb_policy_args.combiner = combiner();
+  lb_policy_args.work_serializer = work_serializer();
   lb_policy_args.channel_control_helper =
       absl::make_unique<ResolvingControlHelper>(Ref());
   lb_policy_args.args = &args;
@@ -266,31 +267,21 @@ void ResolvingLoadBalancingPolicy::MaybeAddTraceMessagesForAddressChangesLocked(
     bool resolution_contains_addresses, TraceStringVector* trace_strings) {
   if (!resolution_contains_addresses &&
       previous_resolution_contained_addresses_) {
-    trace_strings->push_back(gpr_strdup("Address list became empty"));
+    trace_strings->push_back("Address list became empty");
   } else if (resolution_contains_addresses &&
              !previous_resolution_contained_addresses_) {
-    trace_strings->push_back(gpr_strdup("Address list became non-empty"));
+    trace_strings->push_back("Address list became non-empty");
   }
   previous_resolution_contained_addresses_ = resolution_contains_addresses;
 }
 
 void ResolvingLoadBalancingPolicy::ConcatenateAndAddChannelTraceLocked(
-    TraceStringVector* trace_strings) const {
-  if (!trace_strings->empty()) {
-    gpr_strvec v;
-    gpr_strvec_init(&v);
-    gpr_strvec_add(&v, gpr_strdup("Resolution event: "));
-    bool is_first = 1;
-    for (size_t i = 0; i < trace_strings->size(); ++i) {
-      if (!is_first) gpr_strvec_add(&v, gpr_strdup(", "));
-      is_first = false;
-      gpr_strvec_add(&v, (*trace_strings)[i]);
-    }
-    size_t len = 0;
-    grpc_core::UniquePtr<char> message(gpr_strvec_flatten(&v, &len));
+    const TraceStringVector& trace_strings) const {
+  if (!trace_strings.empty()) {
+    std::string message =
+        absl::StrCat("Resolution event: ", absl::StrJoin(trace_strings, ", "));
     channel_control_helper()->AddTraceEvent(ChannelControlHelper::TRACE_INFO,
-                                            StringView(message.get()));
-    gpr_strvec_destroy(&v);
+                                            message);
   }
 }
 
@@ -315,7 +306,7 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
   // Process the resolver result.
   RefCountedPtr<LoadBalancingPolicy::Config> lb_policy_config;
   bool service_config_changed = false;
-  char* service_config_error_string = nullptr;
+  std::string service_config_error_string;
   if (process_resolver_result_ != nullptr) {
     grpc_error* service_config_error = GRPC_ERROR_NONE;
     bool no_valid_service_config = false;
@@ -323,8 +314,7 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
         process_resolver_result_user_data_, result, &lb_policy_config,
         &service_config_error, &no_valid_service_config);
     if (service_config_error != GRPC_ERROR_NONE) {
-      service_config_error_string =
-          gpr_strdup(grpc_error_string(service_config_error));
+      service_config_error_string = grpc_error_string(service_config_error);
       if (no_valid_service_config) {
         // We received an invalid service config and we don't have a
         // fallback service config.
@@ -345,15 +335,14 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
   if (service_config_changed) {
     // TODO(ncteisen): might be worth somehow including a snippet of the
     // config in the trace, at the risk of bloating the trace logs.
-    trace_strings.push_back(gpr_strdup("Service config changed"));
+    trace_strings.push_back("Service config changed");
   }
-  if (service_config_error_string != nullptr) {
-    trace_strings.push_back(service_config_error_string);
-    service_config_error_string = nullptr;
+  if (!service_config_error_string.empty()) {
+    trace_strings.push_back(service_config_error_string.c_str());
   }
   MaybeAddTraceMessagesForAddressChangesLocked(resolution_contains_addresses,
                                                &trace_strings);
-  ConcatenateAndAddChannelTraceLocked(&trace_strings);
+  ConcatenateAndAddChannelTraceLocked(trace_strings);
 }
 
 }  // namespace grpc_core
index ba53368..39815e2 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include "src/core/ext/filters/client_channel/lb_policy.h"
 #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
 #include "src/core/ext/filters/client_channel/resolver.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/debug/trace.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/iomgr/call_combiner.h"
 #include "src/core/lib/iomgr/closure.h"
@@ -80,7 +81,7 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
   void ResetBackoffLocked() override;
 
  private:
-  using TraceStringVector = InlinedVector<char*, 3>;
+  using TraceStringVector = absl::InlinedVector<const char*, 3>;
 
   class ResolverResultHandler;
   class ResolvingControlHelper;
@@ -98,7 +99,7 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
   void MaybeAddTraceMessagesForAddressChangesLocked(
       bool resolution_contains_addresses, TraceStringVector* trace_strings);
   void ConcatenateAndAddChannelTraceLocked(
-      TraceStringVector* trace_strings) const;
+      const TraceStringVector& trace_strings) const;
   void OnResolverResultChangedLocked(Resolver::Result result);
 
   // Passed in from caller at construction time.
index 10f49f2..f53dd3c 100644 (file)
@@ -21,8 +21,9 @@
 
 #include <grpc/support/port_platform.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 
 namespace grpc_core {
@@ -82,7 +83,7 @@ class ServerAddress {
 // ServerAddressList
 //
 
-typedef InlinedVector<ServerAddress, 1> ServerAddressList;
+typedef absl::InlinedVector<ServerAddress, 1> ServerAddressList;
 
 }  // namespace grpc_core
 
index f08ebe1..a8c0d93 100644 (file)
 
 #include "src/core/ext/filters/client_channel/service_config.h"
 
-#include <string.h>
+#include <string>
 
 #include "absl/strings/str_cat.h"
 
-#include <grpc/impl/codegen/grpc_types.h>
-#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
 
-#include "src/core/lib/gpr/string.h"
+#include "src/core/ext/filters/client_channel/service_config_parser.h"
 #include "src/core/lib/json/json.h"
 #include "src/core/lib/slice/slice_internal.h"
 
 namespace grpc_core {
 
-namespace {
-typedef InlinedVector<std::unique_ptr<ServiceConfig::Parser>,
-                      ServiceConfig::kNumPreallocatedParsers>
-    ServiceConfigParserList;
-ServiceConfigParserList* g_registered_parsers;
-}  // namespace
-
-RefCountedPtr<ServiceConfig> ServiceConfig::Create(StringView json_string,
-                                                   grpc_error** error) {
+RefCountedPtr<ServiceConfig> ServiceConfig::Create(
+    absl::string_view json_string, grpc_error** error) {
   GPR_DEBUG_ASSERT(error != nullptr);
   Json json = Json::Parse(json_string, error);
   if (*error != GRPC_ERROR_NONE) return nullptr;
@@ -59,21 +49,16 @@ ServiceConfig::ServiceConfig(std::string json_string, Json json,
         GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON value is not an object");
     return;
   }
-  grpc_error* error_list[2];
-  int error_count = 0;
-  grpc_error* global_error = ParseGlobalParams();
+  std::vector<grpc_error*> error_list;
+  grpc_error* global_error = GRPC_ERROR_NONE;
+  parsed_global_configs_ =
+      ServiceConfigParser::ParseGlobalParameters(json_, &global_error);
+  if (global_error != GRPC_ERROR_NONE) error_list.push_back(global_error);
   grpc_error* local_error = ParsePerMethodParams();
-  if (global_error != GRPC_ERROR_NONE) {
-    error_list[error_count++] = global_error;
-  }
-  if (local_error != GRPC_ERROR_NONE) {
-    error_list[error_count++] = local_error;
-  }
-  if (error_count > 0) {
-    *error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
-        "Service config parsing error", error_list, error_count);
-    GRPC_ERROR_UNREF(global_error);
-    GRPC_ERROR_UNREF(local_error);
+  if (local_error != GRPC_ERROR_NONE) error_list.push_back(local_error);
+  if (!error_list.empty()) {
+    *error = GRPC_ERROR_CREATE_FROM_VECTOR("Service config parsing error",
+                                           &error_list);
   }
 }
 
@@ -83,34 +68,18 @@ ServiceConfig::~ServiceConfig() {
   }
 }
 
-grpc_error* ServiceConfig::ParseGlobalParams() {
-  std::vector<grpc_error*> error_list;
-  for (size_t i = 0; i < g_registered_parsers->size(); i++) {
-    grpc_error* parser_error = GRPC_ERROR_NONE;
-    auto parsed_obj =
-        (*g_registered_parsers)[i]->ParseGlobalParams(json_, &parser_error);
-    if (parser_error != GRPC_ERROR_NONE) {
-      error_list.push_back(parser_error);
-    }
-    parsed_global_configs_.push_back(std::move(parsed_obj));
-  }
-  return GRPC_ERROR_CREATE_FROM_VECTOR("Global Params", &error_list);
-}
-
 grpc_error* ServiceConfig::ParseJsonMethodConfig(const Json& json) {
+  std::vector<grpc_error*> error_list;
   // Parse method config with each registered parser.
-  auto objs_vector = absl::make_unique<ParsedConfigVector>();
-  InlinedVector<grpc_error*, 4> error_list;
-  for (size_t i = 0; i < g_registered_parsers->size(); i++) {
-    grpc_error* parser_error = GRPC_ERROR_NONE;
-    auto parsed_obj =
-        (*g_registered_parsers)[i]->ParsePerMethodParams(json, &parser_error);
-    if (parser_error != GRPC_ERROR_NONE) {
-      error_list.push_back(parser_error);
-    }
-    objs_vector->push_back(std::move(parsed_obj));
+  auto parsed_configs =
+      absl::make_unique<ServiceConfigParser::ParsedConfigVector>();
+  grpc_error* parser_error = GRPC_ERROR_NONE;
+  *parsed_configs =
+      ServiceConfigParser::ParsePerMethodParameters(json, &parser_error);
+  if (parser_error != GRPC_ERROR_NONE) {
+    error_list.push_back(parser_error);
   }
-  parsed_method_config_vectors_storage_.push_back(std::move(objs_vector));
+  parsed_method_config_vectors_storage_.push_back(std::move(parsed_configs));
   const auto* vector_ptr = parsed_method_config_vectors_storage_.back().get();
   // Add an entry for each path.
   bool found_name = false;
@@ -231,7 +200,7 @@ std::string ServiceConfig::ParseJsonMethodName(const Json& json,
                       method_name == nullptr ? "" : *method_name);
 }
 
-const ServiceConfig::ParsedConfigVector*
+const ServiceConfigParser::ParsedConfigVector*
 ServiceConfig::GetMethodParsedConfigVector(const grpc_slice& path) const {
   // Try looking up the full path in the map.
   auto it = parsed_method_configs_map_.find(path);
@@ -249,19 +218,4 @@ ServiceConfig::GetMethodParsedConfigVector(const grpc_slice& path) const {
   return default_method_config_vector_;
 }
 
-size_t ServiceConfig::RegisterParser(std::unique_ptr<Parser> parser) {
-  g_registered_parsers->push_back(std::move(parser));
-  return g_registered_parsers->size() - 1;
-}
-
-void ServiceConfig::Init() {
-  GPR_ASSERT(g_registered_parsers == nullptr);
-  g_registered_parsers = new ServiceConfigParserList();
-}
-
-void ServiceConfig::Shutdown() {
-  delete g_registered_parsers;
-  g_registered_parsers = nullptr;
-}
-
 }  // namespace grpc_core
index 3bba4ec..8c37621 100644 (file)
 
 #include <unordered_map>
 
+#include "absl/container/inlined_vector.h"
+
 #include <grpc/impl/codegen/grpc_types.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/lib/gprpp/inlined_vector.h"
+#include "src/core/ext/filters/client_channel/service_config_parser.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/iomgr/error.h"
 
 namespace grpc_core {
 
+// TODO(roth): Consider stripping this down further to the completely minimal
+// interface requied to be exposed as part of the resolver API.
 class ServiceConfig : public RefCounted<ServiceConfig> {
  public:
-  /// This is the base class that all service config parsers MUST use to store
-  /// parsed service config data.
-  class ParsedConfig {
-   public:
-    virtual ~ParsedConfig() = default;
-  };
-
-  /// This is the base class that all service config parsers should derive from.
-  class Parser {
-   public:
-    virtual ~Parser() = default;
-
-    virtual std::unique_ptr<ParsedConfig> ParseGlobalParams(
-        const Json& /* json */, grpc_error** error) {
-      // Avoid unused parameter warning on debug-only parameter
-      (void)error;
-      GPR_DEBUG_ASSERT(error != nullptr);
-      return nullptr;
-    }
-
-    virtual std::unique_ptr<ParsedConfig> ParsePerMethodParams(
-        const Json& /* json */, grpc_error** error) {
-      // Avoid unused parameter warning on debug-only parameter
-      (void)error;
-      GPR_DEBUG_ASSERT(error != nullptr);
-      return nullptr;
-    }
-  };
-
-  static constexpr int kNumPreallocatedParsers = 4;
-  typedef InlinedVector<std::unique_ptr<ParsedConfig>, kNumPreallocatedParsers>
-      ParsedConfigVector;
-
-  /// When a service config is applied to a call in the client_channel_filter,
-  /// we create an instance of this object and store it in the call_data for
-  /// client_channel. A pointer to this object is also stored in the
-  /// call_context, so that future filters can easily access method and global
-  /// parameters for the call.
-  class CallData {
-   public:
-    CallData() = default;
-    CallData(RefCountedPtr<ServiceConfig> svc_cfg, const grpc_slice& path)
-        : service_config_(std::move(svc_cfg)) {
-      if (service_config_ != nullptr) {
-        method_params_vector_ =
-            service_config_->GetMethodParsedConfigVector(path);
-      }
-    }
-
-    ServiceConfig* service_config() { return service_config_.get(); }
-
-    ParsedConfig* GetMethodParsedConfig(size_t index) const {
-      return method_params_vector_ != nullptr
-                 ? (*method_params_vector_)[index].get()
-                 : nullptr;
-    }
-
-    ParsedConfig* GetGlobalParsedConfig(size_t index) const {
-      return service_config_->GetGlobalParsedConfig(index);
-    }
-
-   private:
-    RefCountedPtr<ServiceConfig> service_config_;
-    const ParsedConfigVector* method_params_vector_ = nullptr;
-  };
-
   /// Creates a new service config from parsing \a json_string.
   /// Returns null on parse error.
-  static RefCountedPtr<ServiceConfig> Create(StringView json_string,
+  static RefCountedPtr<ServiceConfig> Create(absl::string_view json_string,
                                              grpc_error** error);
 
   ServiceConfig(std::string json_string, Json json, grpc_error** error);
@@ -138,7 +76,7 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
   /// Retrieves the global parsed config at index \a index. The
   /// lifetime of the returned object is tied to the lifetime of the
   /// ServiceConfig object.
-  ParsedConfig* GetGlobalParsedConfig(size_t index) {
+  ServiceConfigParser::ParsedConfig* GetGlobalParsedConfig(size_t index) {
     GPR_DEBUG_ASSERT(index < parsed_global_configs_.size());
     return parsed_global_configs_[index].get();
   }
@@ -146,47 +84,37 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
   /// Retrieves the vector of parsed configs for the method identified
   /// by \a path.  The lifetime of the returned vector and contained objects
   /// is tied to the lifetime of the ServiceConfig object.
-  const ParsedConfigVector* GetMethodParsedConfigVector(
+  const ServiceConfigParser::ParsedConfigVector* GetMethodParsedConfigVector(
       const grpc_slice& path) const;
 
-  /// Globally register a service config parser. On successful registration, it
-  /// returns the index at which the parser was registered. On failure, -1 is
-  /// returned. Each new service config update will go through all the
-  /// registered parser. Each parser is responsible for reading the service
-  /// config json and returning a parsed config. This parsed config can later be
-  /// retrieved using the same index that was returned at registration time.
-  static size_t RegisterParser(std::unique_ptr<Parser> parser);
-
-  static void Init();
-
-  static void Shutdown();
-
  private:
-  // Helper functions to parse the service config
-  grpc_error* ParseGlobalParams();
+  // Helper functions for parsing the method configs.
   grpc_error* ParsePerMethodParams();
+  grpc_error* ParseJsonMethodConfig(const Json& json);
 
   // Returns a path string for the JSON name object specified by json.
   // Sets *error on error.
   static std::string ParseJsonMethodName(const Json& json, grpc_error** error);
 
-  grpc_error* ParseJsonMethodConfig(const Json& json);
-
   std::string json_string_;
   Json json_;
 
-  InlinedVector<std::unique_ptr<ParsedConfig>, kNumPreallocatedParsers>
+  absl::InlinedVector<std::unique_ptr<ServiceConfigParser::ParsedConfig>,
+                      ServiceConfigParser::kNumPreallocatedParsers>
       parsed_global_configs_;
   // A map from the method name to the parsed config vector. Note that we are
   // using a raw pointer and not a unique pointer so that we can use the same
   // vector for multiple names.
-  std::unordered_map<grpc_slice, const ParsedConfigVector*, SliceHash>
+  std::unordered_map<grpc_slice, const ServiceConfigParser::ParsedConfigVector*,
+                     SliceHash>
       parsed_method_configs_map_;
   // Default method config.
-  const ParsedConfigVector* default_method_config_vector_ = nullptr;
+  const ServiceConfigParser::ParsedConfigVector* default_method_config_vector_ =
+      nullptr;
   // Storage for all the vectors that are being used in
   // parsed_method_configs_table_.
-  InlinedVector<std::unique_ptr<ParsedConfigVector>, 32>
+  absl::InlinedVector<std::unique_ptr<ServiceConfigParser::ParsedConfigVector>,
+                      32>
       parsed_method_config_vectors_storage_;
 };
 
diff --git a/src/core/ext/filters/client_channel/service_config_call_data.h b/src/core/ext/filters/client_channel/service_config_call_data.h
new file mode 100644 (file)
index 0000000..b6b5b73
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Copyright 2016 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_CALL_DATA_H
+#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_CALL_DATA_H
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/filters/client_channel/service_config_parser.h"
+#include "src/core/lib/channel/context.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+
+namespace grpc_core {
+
+/// When a service config is applied to a call in the client_channel_filter,
+/// we create an instance of this object on the arena.  A pointer to this
+/// object is also stored in the call_context, so that future filters can
+/// easily access method and global parameters for the call.
+class ServiceConfigCallData {
+ public:
+  ServiceConfigCallData(
+      RefCountedPtr<ServiceConfig> service_config,
+      const ServiceConfigParser::ParsedConfigVector* method_configs,
+      grpc_call_context_element* call_context)
+      : service_config_(std::move(service_config)),
+        method_configs_(method_configs) {
+    call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = this;
+    call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].destroy = Destroy;
+  }
+
+  ServiceConfig* service_config() { return service_config_.get(); }
+
+  ServiceConfigParser::ParsedConfig* GetMethodParsedConfig(size_t index) const {
+    return method_configs_ != nullptr ? (*method_configs_)[index].get()
+                                      : nullptr;
+  }
+
+  ServiceConfigParser::ParsedConfig* GetGlobalParsedConfig(size_t index) const {
+    return service_config_->GetGlobalParsedConfig(index);
+  }
+
+ private:
+  static void Destroy(void* ptr) {
+    ServiceConfigCallData* self = static_cast<ServiceConfigCallData*>(ptr);
+    self->~ServiceConfigCallData();
+  }
+
+  RefCountedPtr<ServiceConfig> service_config_;
+  const ServiceConfigParser::ParsedConfigVector* method_configs_ = nullptr;
+};
+
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_CALL_DATA_H */
diff --git a/src/core/ext/filters/client_channel/service_config_parser.cc b/src/core/ext/filters/client_channel/service_config_parser.cc
new file mode 100644 (file)
index 0000000..87aa513
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/ext/filters/client_channel/service_config_parser.h"
+
+#include <grpc/support/log.h>
+
+namespace grpc_core {
+
+namespace {
+typedef absl::InlinedVector<std::unique_ptr<ServiceConfigParser::Parser>,
+                            ServiceConfigParser::kNumPreallocatedParsers>
+    ServiceConfigParserList;
+ServiceConfigParserList* g_registered_parsers;
+}  // namespace
+
+void ServiceConfigParser::Init() {
+  GPR_ASSERT(g_registered_parsers == nullptr);
+  g_registered_parsers = new ServiceConfigParserList();
+}
+
+void ServiceConfigParser::Shutdown() {
+  delete g_registered_parsers;
+  g_registered_parsers = nullptr;
+}
+
+size_t ServiceConfigParser::RegisterParser(std::unique_ptr<Parser> parser) {
+  g_registered_parsers->push_back(std::move(parser));
+  return g_registered_parsers->size() - 1;
+}
+
+ServiceConfigParser::ParsedConfigVector
+ServiceConfigParser::ParseGlobalParameters(const Json& json,
+                                           grpc_error** error) {
+  ParsedConfigVector parsed_global_configs;
+  std::vector<grpc_error*> error_list;
+  for (size_t i = 0; i < g_registered_parsers->size(); i++) {
+    grpc_error* parser_error = GRPC_ERROR_NONE;
+    auto parsed_config =
+        (*g_registered_parsers)[i]->ParseGlobalParams(json, &parser_error);
+    if (parser_error != GRPC_ERROR_NONE) {
+      error_list.push_back(parser_error);
+    }
+    parsed_global_configs.push_back(std::move(parsed_config));
+  }
+  if (!error_list.empty()) {
+    *error = GRPC_ERROR_CREATE_FROM_VECTOR("Global Params", &error_list);
+  }
+  return parsed_global_configs;
+}
+
+ServiceConfigParser::ParsedConfigVector
+ServiceConfigParser::ParsePerMethodParameters(const Json& json,
+                                              grpc_error** error) {
+  ParsedConfigVector parsed_method_configs;
+  std::vector<grpc_error*> error_list;
+  for (size_t i = 0; i < g_registered_parsers->size(); i++) {
+    grpc_error* parser_error = GRPC_ERROR_NONE;
+    auto parsed_config =
+        (*g_registered_parsers)[i]->ParsePerMethodParams(json, &parser_error);
+    if (parser_error != GRPC_ERROR_NONE) {
+      error_list.push_back(parser_error);
+    }
+    parsed_method_configs.push_back(std::move(parsed_config));
+  }
+  if (!error_list.empty()) {
+    *error = GRPC_ERROR_CREATE_FROM_VECTOR("methodConfig", &error_list);
+  }
+  return parsed_method_configs;
+}
+
+}  // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/service_config_parser.h b/src/core/ext/filters/client_channel/service_config_parser.h
new file mode 100644 (file)
index 0000000..a101ef3
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Copyright 2016 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_PARSER_H
+#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_PARSER_H
+
+#include <grpc/support/port_platform.h>
+
+#include <memory>
+
+#include "absl/container/inlined_vector.h"
+
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/json/json.h"
+
+namespace grpc_core {
+
+// Service config parser registry.
+// See service_config.h for more information.
+class ServiceConfigParser {
+ public:
+  /// This is the base class that all service config parsers MUST use to store
+  /// parsed service config data.
+  class ParsedConfig {
+   public:
+    virtual ~ParsedConfig() = default;
+  };
+
+  /// This is the base class that all service config parsers should derive from.
+  class Parser {
+   public:
+    virtual ~Parser() = default;
+
+    virtual std::unique_ptr<ParsedConfig> ParseGlobalParams(
+        const Json& /* json */, grpc_error** error) {
+      // Avoid unused parameter warning on debug-only parameter
+      (void)error;
+      GPR_DEBUG_ASSERT(error != nullptr);
+      return nullptr;
+    }
+
+    virtual std::unique_ptr<ParsedConfig> ParsePerMethodParams(
+        const Json& /* json */, grpc_error** error) {
+      // Avoid unused parameter warning on debug-only parameter
+      (void)error;
+      GPR_DEBUG_ASSERT(error != nullptr);
+      return nullptr;
+    }
+  };
+
+  static constexpr int kNumPreallocatedParsers = 4;
+  typedef absl::InlinedVector<std::unique_ptr<ParsedConfig>,
+                              kNumPreallocatedParsers>
+      ParsedConfigVector;
+
+  static void Init();
+  static void Shutdown();
+
+  /// Globally register a service config parser. On successful registration, it
+  /// returns the index at which the parser was registered. On failure, -1 is
+  /// returned. Each new service config update will go through all the
+  /// registered parser. Each parser is responsible for reading the service
+  /// config json and returning a parsed config. This parsed config can later be
+  /// retrieved using the same index that was returned at registration time.
+  static size_t RegisterParser(std::unique_ptr<Parser> parser);
+
+  static ParsedConfigVector ParseGlobalParameters(const Json& json,
+                                                  grpc_error** error);
+
+  static ParsedConfigVector ParsePerMethodParameters(const Json& json,
+                                                     grpc_error** error);
+};
+
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_PARSER_H */
index 8ef241b..f350b2e 100644 (file)
@@ -362,12 +362,44 @@ class Subchannel::ConnectedSubchannelStateWatcher
   Subchannel* subchannel_;
 };
 
+// Asynchronously notifies the \a watcher of a change in the connectvity state
+// of \a subchannel to the current \a state. Deletes itself when done.
+class Subchannel::AsyncWatcherNotifierLocked {
+ public:
+  AsyncWatcherNotifierLocked(
+      RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher,
+      Subchannel* subchannel, grpc_connectivity_state state)
+      : watcher_(std::move(watcher)) {
+    RefCountedPtr<ConnectedSubchannel> connected_subchannel;
+    if (state == GRPC_CHANNEL_READY) {
+      connected_subchannel = subchannel->connected_subchannel_;
+    }
+    watcher_->PushConnectivityStateChange(
+        {state, std::move(connected_subchannel)});
+    ExecCtx::Run(
+        DEBUG_LOCATION,
+        GRPC_CLOSURE_INIT(&closure_,
+                          [](void* arg, grpc_error* /*error*/) {
+                            auto* self =
+                                static_cast<AsyncWatcherNotifierLocked*>(arg);
+                            self->watcher_->OnConnectivityStateChange();
+                            delete self;
+                          },
+                          this, nullptr),
+        GRPC_ERROR_NONE);
+  }
+
+ private:
+  RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher_;
+  grpc_closure closure_;
+};
+
 //
 // Subchannel::ConnectivityStateWatcherList
 //
 
 void Subchannel::ConnectivityStateWatcherList::AddWatcherLocked(
-    OrphanablePtr<ConnectivityStateWatcherInterface> watcher) {
+    RefCountedPtr<ConnectivityStateWatcherInterface> watcher) {
   watchers_.insert(std::make_pair(watcher.get(), std::move(watcher)));
 }
 
@@ -379,19 +411,7 @@ void Subchannel::ConnectivityStateWatcherList::RemoveWatcherLocked(
 void Subchannel::ConnectivityStateWatcherList::NotifyLocked(
     Subchannel* subchannel, grpc_connectivity_state state) {
   for (const auto& p : watchers_) {
-    RefCountedPtr<ConnectedSubchannel> connected_subchannel;
-    if (state == GRPC_CHANNEL_READY) {
-      connected_subchannel = subchannel->connected_subchannel_;
-    }
-    // TODO(roth): In principle, it seems wrong to send this notification
-    // to the watcher while holding the subchannel's mutex, since it could
-    // lead to a deadlock if the watcher calls back into the subchannel
-    // before returning back to us.  In practice, this doesn't happen,
-    // because the LB policy code that watches subchannels always bounces
-    // the notification into the client_channel control-plane combiner
-    // before processing it.  But if we ever have any other callers here,
-    // we will probably need to change this.
-    p.second->OnConnectivityStateChange(state, std::move(connected_subchannel));
+    new AsyncWatcherNotifierLocked(p.second, subchannel, state);
   }
 }
 
@@ -428,14 +448,9 @@ class Subchannel::HealthWatcherMap::HealthWatcher
 
   void AddWatcherLocked(
       grpc_connectivity_state initial_state,
-      OrphanablePtr<Subchannel::ConnectivityStateWatcherInterface> watcher) {
+      RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher) {
     if (state_ != initial_state) {
-      RefCountedPtr<ConnectedSubchannel> connected_subchannel;
-      if (state_ == GRPC_CHANNEL_READY) {
-        connected_subchannel = subchannel_->connected_subchannel_;
-      }
-      watcher->OnConnectivityStateChange(state_,
-                                         std::move(connected_subchannel));
+      new AsyncWatcherNotifierLocked(watcher, subchannel_, state_);
     }
     watcher_list_.AddWatcherLocked(std::move(watcher));
   }
@@ -503,7 +518,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
 void Subchannel::HealthWatcherMap::AddWatcherLocked(
     Subchannel* subchannel, grpc_connectivity_state initial_state,
     grpc_core::UniquePtr<char> health_check_service_name,
-    OrphanablePtr<ConnectivityStateWatcherInterface> watcher) {
+    RefCountedPtr<ConnectivityStateWatcherInterface> watcher) {
   // If the health check service name is not already present in the map,
   // add it.
   auto it = map_.find(health_check_service_name.get());
@@ -613,6 +628,21 @@ BackOff::Options ParseArgsForBackoffValues(
 
 }  // namespace
 
+void Subchannel::ConnectivityStateWatcherInterface::PushConnectivityStateChange(
+    ConnectivityStateChange state_change) {
+  MutexLock lock(&mu_);
+  connectivity_state_queue_.push_back(std::move(state_change));
+}
+
+Subchannel::ConnectivityStateWatcherInterface::ConnectivityStateChange
+Subchannel::ConnectivityStateWatcherInterface::PopConnectivityStateChange() {
+  MutexLock lock(&mu_);
+  GPR_ASSERT(!connectivity_state_queue_.empty());
+  ConnectivityStateChange state_change = connectivity_state_queue_.front();
+  connectivity_state_queue_.pop_front();
+  return state_change;
+}
+
 Subchannel::Subchannel(SubchannelKey* key,
                        OrphanablePtr<SubchannelConnector> connector,
                        const grpc_channel_args* args)
@@ -788,7 +818,7 @@ grpc_connectivity_state Subchannel::CheckConnectivityState(
 void Subchannel::WatchConnectivityState(
     grpc_connectivity_state initial_state,
     grpc_core::UniquePtr<char> health_check_service_name,
-    OrphanablePtr<ConnectivityStateWatcherInterface> watcher) {
+    RefCountedPtr<ConnectivityStateWatcherInterface> watcher) {
   MutexLock lock(&mu_);
   grpc_pollset_set* interested_parties = watcher->interested_parties();
   if (interested_parties != nullptr) {
@@ -796,7 +826,7 @@ void Subchannel::WatchConnectivityState(
   }
   if (health_check_service_name == nullptr) {
     if (state_ != initial_state) {
-      watcher->OnConnectivityStateChange(state_, connected_subchannel_);
+      new AsyncWatcherNotifierLocked(watcher, this, state_);
     }
     watcher_list_.AddWatcherLocked(std::move(watcher));
   } else {
index cf4ddaf..9478fa7 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <grpc/support/port_platform.h>
 
+#include <deque>
+
 #include "src/core/ext/filters/client_channel/client_channel_channelz.h"
 #include "src/core/ext/filters/client_channel/connector.h"
 #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
@@ -176,24 +178,44 @@ class SubchannelCall {
 class Subchannel {
  public:
   class ConnectivityStateWatcherInterface
-      : public InternallyRefCounted<ConnectivityStateWatcherInterface> {
+      : public RefCounted<ConnectivityStateWatcherInterface> {
    public:
+    struct ConnectivityStateChange {
+      grpc_connectivity_state state;
+      RefCountedPtr<ConnectedSubchannel> connected_subchannel;
+    };
+
     virtual ~ConnectivityStateWatcherInterface() = default;
 
     // Will be invoked whenever the subchannel's connectivity state
     // changes.  There will be only one invocation of this method on a
     // given watcher instance at any given time.
-    //
+    // Implementations should call PopConnectivityStateChange to get the next
+    // connectivity state change.
+    virtual void OnConnectivityStateChange() = 0;
+
+    virtual grpc_pollset_set* interested_parties() = 0;
+
+    // Enqueues connectivity state change notifications.
     // When the state changes to READY, connected_subchannel will
     // contain a ref to the connected subchannel.  When it changes from
     // READY to some other state, the implementation must release its
     // ref to the connected subchannel.
-    virtual void OnConnectivityStateChange(
-        grpc_connectivity_state new_state,
-        RefCountedPtr<ConnectedSubchannel> connected_subchannel)  // NOLINT
-        = 0;
+    // TODO(yashkt): This is currently needed to send the state updates in the
+    // right order when asynchronously notifying. This will no longer be
+    // necessary when we have access to EventManager.
+    void PushConnectivityStateChange(ConnectivityStateChange state_change);
 
-    virtual grpc_pollset_set* interested_parties() = 0;
+    // Dequeues connectivity state change notifications.
+    ConnectivityStateChange PopConnectivityStateChange();
+
+   private:
+    // Keeps track of the updates that the watcher instance must be notified of.
+    // TODO(yashkt): This is currently needed to send the state updates in the
+    // right order when asynchronously notifying. This will no longer be
+    // necessary when we have access to EventManager.
+    std::deque<ConnectivityStateChange> connectivity_state_queue_;
+    Mutex mu_;  // protects the queue
   };
 
   // The ctor and dtor are not intended to use directly.
@@ -243,7 +265,7 @@ class Subchannel {
   void WatchConnectivityState(
       grpc_connectivity_state initial_state,
       grpc_core::UniquePtr<char> health_check_service_name,
-      OrphanablePtr<ConnectivityStateWatcherInterface> watcher);
+      RefCountedPtr<ConnectivityStateWatcherInterface> watcher);
 
   // Cancels a connectivity state watch.
   // If the watcher has already been destroyed, this is a no-op.
@@ -280,7 +302,7 @@ class Subchannel {
     ~ConnectivityStateWatcherList() { Clear(); }
 
     void AddWatcherLocked(
-        OrphanablePtr<ConnectivityStateWatcherInterface> watcher);
+        RefCountedPtr<ConnectivityStateWatcherInterface> watcher);
     void RemoveWatcherLocked(ConnectivityStateWatcherInterface* watcher);
 
     // Notifies all watchers in the list about a change to state.
@@ -294,7 +316,7 @@ class Subchannel {
     // TODO(roth): Once we can use C++-14 heterogeneous lookups, this can
     // be a set instead of a map.
     std::map<ConnectivityStateWatcherInterface*,
-             OrphanablePtr<ConnectivityStateWatcherInterface>>
+             RefCountedPtr<ConnectivityStateWatcherInterface>>
         watchers_;
   };
 
@@ -312,7 +334,7 @@ class Subchannel {
     void AddWatcherLocked(
         Subchannel* subchannel, grpc_connectivity_state initial_state,
         grpc_core::UniquePtr<char> health_check_service_name,
-        OrphanablePtr<ConnectivityStateWatcherInterface> watcher);
+        RefCountedPtr<ConnectivityStateWatcherInterface> watcher);
     void RemoveWatcherLocked(const char* health_check_service_name,
                              ConnectivityStateWatcherInterface* watcher);
 
@@ -332,6 +354,8 @@ class Subchannel {
 
   class ConnectedSubchannelStateWatcher;
 
+  class AsyncWatcherNotifierLocked;
+
   // Sets the subchannel's connectivity state to \a state.
   void SetConnectivityStateLocked(grpc_connectivity_state state);
 
index 4be62a3..69490b7 100644 (file)
@@ -31,7 +31,9 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/ext/filters/client_channel/xds/xds_api.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 
@@ -127,10 +129,23 @@ const char* XdsApi::kCdsTypeUrl = "type.googleapis.com/envoy.api.v2.Cluster";
 const char* XdsApi::kEdsTypeUrl =
     "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
 
+namespace {
+
+bool XdsRoutingEnabled() {
+  char* value = gpr_getenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
+  bool parsed_value;
+  bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value);
+  gpr_free(value);
+  return parse_succeeded && parsed_value;
+}
+
+}  // namespace
+
 XdsApi::XdsApi(XdsClient* client, TraceFlag* tracer,
                const XdsBootstrap::Node* node)
     : client_(client),
       tracer_(tracer),
+      xds_routing_enabled_(XdsRoutingEnabled()),
       node_(node),
       build_version_(absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING, " ",
                                   grpc_version_string())),
@@ -258,46 +273,14 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node,
       arena);
 }
 
-envoy_api_v2_DiscoveryRequest* CreateDiscoveryRequest(
-    upb_arena* arena, const char* type_url, const std::string& version,
-    const std::string& nonce, grpc_error* error) {
-  // Create a request.
-  envoy_api_v2_DiscoveryRequest* request =
-      envoy_api_v2_DiscoveryRequest_new(arena);
-  // Set type_url.
-  envoy_api_v2_DiscoveryRequest_set_type_url(request,
-                                             upb_strview_makez(type_url));
-  // Set version_info.
-  if (!version.empty()) {
-    envoy_api_v2_DiscoveryRequest_set_version_info(
-        request, upb_strview_makez(version.c_str()));
-  }
-  // Set nonce.
-  if (!nonce.empty()) {
-    envoy_api_v2_DiscoveryRequest_set_response_nonce(
-        request, upb_strview_makez(nonce.c_str()));
-  }
-  // Set error_detail if it's a NACK.
-  if (error != GRPC_ERROR_NONE) {
-    grpc_slice error_description_slice;
-    GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION,
-                                  &error_description_slice));
-    upb_strview error_description_strview =
-        upb_strview_make(reinterpret_cast<const char*>(
-                             GPR_SLICE_START_PTR(error_description_slice)),
-                         GPR_SLICE_LENGTH(error_description_slice));
-    google_rpc_Status* error_detail =
-        envoy_api_v2_DiscoveryRequest_mutable_error_detail(request, arena);
-    google_rpc_Status_set_message(error_detail, error_description_strview);
-    GRPC_ERROR_UNREF(error);
-  }
-  return request;
-}
-
 inline absl::string_view UpbStringToAbsl(const upb_strview& str) {
   return absl::string_view(str.data, str.size);
 }
 
+inline std::string UpbStringToStdString(const upb_strview& str) {
+  return std::string(str.data, str.size);
+}
+
 inline void AddStringField(const char* name, const upb_strview& value,
                            std::vector<std::string>* fields,
                            bool add_if_empty = false) {
@@ -307,6 +290,15 @@ inline void AddStringField(const char* name, const upb_strview& value,
   }
 }
 
+inline void AddUInt32ValueField(const char* name,
+                                const google_protobuf_UInt32Value* value,
+                                std::vector<std::string>* fields) {
+  if (value != nullptr) {
+    fields->emplace_back(absl::StrCat(
+        name, " { value: ", google_protobuf_UInt32Value_value(value), " }"));
+  }
+}
+
 inline void AddLocalityField(int indent_level,
                              const envoy_api_v2_core_Locality* locality,
                              std::vector<std::string>* fields) {
@@ -460,91 +452,43 @@ grpc_slice SerializeDiscoveryRequest(upb_arena* arena,
 
 }  // namespace
 
-grpc_slice XdsApi::CreateUnsupportedTypeNackRequest(const std::string& type_url,
-                                                    const std::string& nonce,
-                                                    grpc_error* error) {
-  upb::Arena arena;
-  envoy_api_v2_DiscoveryRequest* request = CreateDiscoveryRequest(
-      arena.ptr(), type_url.c_str(), /*version=*/"", nonce, error);
-  MaybeLogDiscoveryRequest(client_, tracer_, request);
-  return SerializeDiscoveryRequest(arena.ptr(), request);
-}
-
-grpc_slice XdsApi::CreateLdsRequest(const std::string& server_name,
-                                    const std::string& version,
-                                    const std::string& nonce, grpc_error* error,
-                                    bool populate_node) {
-  upb::Arena arena;
-  envoy_api_v2_DiscoveryRequest* request =
-      CreateDiscoveryRequest(arena.ptr(), kLdsTypeUrl, version, nonce, error);
-  // Populate node.
-  if (populate_node) {
-    envoy_api_v2_core_Node* node_msg =
-        envoy_api_v2_DiscoveryRequest_mutable_node(request, arena.ptr());
-    PopulateNode(arena.ptr(), node_, build_version_, user_agent_name_, "",
-                 node_msg);
-  }
-  // Add resource_name.
-  envoy_api_v2_DiscoveryRequest_add_resource_names(
-      request, upb_strview_make(server_name.data(), server_name.size()),
-      arena.ptr());
-  MaybeLogDiscoveryRequest(client_, tracer_, request);
-  return SerializeDiscoveryRequest(arena.ptr(), request);
-}
-
-grpc_slice XdsApi::CreateRdsRequest(const std::string& route_config_name,
-                                    const std::string& version,
-                                    const std::string& nonce, grpc_error* error,
-                                    bool populate_node) {
+grpc_slice XdsApi::CreateAdsRequest(
+    const std::string& type_url,
+    const std::set<absl::string_view>& resource_names,
+    const std::string& version, const std::string& nonce, grpc_error* error,
+    bool populate_node) {
   upb::Arena arena;
+  // Create a request.
   envoy_api_v2_DiscoveryRequest* request =
-      CreateDiscoveryRequest(arena.ptr(), kRdsTypeUrl, version, nonce, error);
-  // Populate node.
-  if (populate_node) {
-    envoy_api_v2_core_Node* node_msg =
-        envoy_api_v2_DiscoveryRequest_mutable_node(request, arena.ptr());
-    PopulateNode(arena.ptr(), node_, build_version_, user_agent_name_, "",
-                 node_msg);
+      envoy_api_v2_DiscoveryRequest_new(arena.ptr());
+  // Set type_url.
+  envoy_api_v2_DiscoveryRequest_set_type_url(
+      request, upb_strview_make(type_url.data(), type_url.size()));
+  // Set version_info.
+  if (!version.empty()) {
+    envoy_api_v2_DiscoveryRequest_set_version_info(
+        request, upb_strview_make(version.data(), version.size()));
   }
-  // Add resource_name.
-  envoy_api_v2_DiscoveryRequest_add_resource_names(
-      request,
-      upb_strview_make(route_config_name.data(), route_config_name.size()),
-      arena.ptr());
-  MaybeLogDiscoveryRequest(client_, tracer_, request);
-  return SerializeDiscoveryRequest(arena.ptr(), request);
-}
-
-grpc_slice XdsApi::CreateCdsRequest(const std::set<StringView>& cluster_names,
-                                    const std::string& version,
-                                    const std::string& nonce, grpc_error* error,
-                                    bool populate_node) {
-  upb::Arena arena;
-  envoy_api_v2_DiscoveryRequest* request =
-      CreateDiscoveryRequest(arena.ptr(), kCdsTypeUrl, version, nonce, error);
-  // Populate node.
-  if (populate_node) {
-    envoy_api_v2_core_Node* node_msg =
-        envoy_api_v2_DiscoveryRequest_mutable_node(request, arena.ptr());
-    PopulateNode(arena.ptr(), node_, build_version_, user_agent_name_, "",
-                 node_msg);
+  // Set nonce.
+  if (!nonce.empty()) {
+    envoy_api_v2_DiscoveryRequest_set_response_nonce(
+        request, upb_strview_make(nonce.data(), nonce.size()));
   }
-  // Add resource_names.
-  for (const auto& cluster_name : cluster_names) {
-    envoy_api_v2_DiscoveryRequest_add_resource_names(
-        request, upb_strview_make(cluster_name.data(), cluster_name.size()),
-        arena.ptr());
+  // Set error_detail if it's a NACK.
+  if (error != GRPC_ERROR_NONE) {
+    grpc_slice error_description_slice;
+    GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION,
+                                  &error_description_slice));
+    upb_strview error_description_strview =
+        upb_strview_make(reinterpret_cast<const char*>(
+                             GPR_SLICE_START_PTR(error_description_slice)),
+                         GPR_SLICE_LENGTH(error_description_slice));
+    google_rpc_Status* error_detail =
+        envoy_api_v2_DiscoveryRequest_mutable_error_detail(request,
+                                                           arena.ptr());
+    google_rpc_Status_set_message(error_detail, error_description_strview);
+    GRPC_ERROR_UNREF(error);
   }
-  MaybeLogDiscoveryRequest(client_, tracer_, request);
-  return SerializeDiscoveryRequest(arena.ptr(), request);
-}
-
-grpc_slice XdsApi::CreateEdsRequest(
-    const std::set<StringView>& eds_service_names, const std::string& version,
-    const std::string& nonce, grpc_error* error, bool populate_node) {
-  upb::Arena arena;
-  envoy_api_v2_DiscoveryRequest* request =
-      CreateDiscoveryRequest(arena.ptr(), kEdsTypeUrl, version, nonce, error);
   // Populate node.
   if (populate_node) {
     envoy_api_v2_core_Node* node_msg =
@@ -553,10 +497,9 @@ grpc_slice XdsApi::CreateEdsRequest(
                  node_msg);
   }
   // Add resource_names.
-  for (const auto& eds_service_name : eds_service_names) {
+  for (const auto& resource_name : resource_names) {
     envoy_api_v2_DiscoveryRequest_add_resource_names(
-        request,
-        upb_strview_make(eds_service_name.data(), eds_service_name.size()),
+        request, upb_strview_make(resource_name.data(), resource_name.size()),
         arena.ptr());
   }
   MaybeLogDiscoveryRequest(client_, tracer_, request);
@@ -679,7 +622,34 @@ void MaybeLogRouteConfiguration(
                 envoy_api_v2_route_RouteAction_cluster_header(action), &fields);
           } else if (envoy_api_v2_route_RouteAction_has_weighted_clusters(
                          action)) {
-            fields.emplace_back("      weighted_clusters: <not printed>");
+            const envoy_api_v2_route_WeightedCluster* weighted_clusters =
+                envoy_api_v2_route_RouteAction_weighted_clusters(action);
+            fields.emplace_back("      weighted_clusters {");
+            size_t num_cluster_weights;
+            const envoy_api_v2_route_WeightedCluster_ClusterWeight* const*
+                cluster_weights = envoy_api_v2_route_WeightedCluster_clusters(
+                    weighted_clusters, &num_cluster_weights);
+            for (size_t i = 0; i < num_cluster_weights; ++i) {
+              const envoy_api_v2_route_WeightedCluster_ClusterWeight*
+                  cluster_weight = cluster_weights[i];
+              fields.emplace_back("        clusters {");
+              AddStringField(
+                  "          name",
+                  envoy_api_v2_route_WeightedCluster_ClusterWeight_name(
+                      cluster_weight),
+                  &fields);
+              AddUInt32ValueField(
+                  "          weight",
+                  envoy_api_v2_route_WeightedCluster_ClusterWeight_weight(
+                      cluster_weight),
+                  &fields);
+              fields.emplace_back("        }");
+            }
+            AddUInt32ValueField("        total_weight",
+                                envoy_api_v2_route_WeightedCluster_total_weight(
+                                    weighted_clusters),
+                                &fields);
+            fields.emplace_back("      }");
           }
           fields.emplace_back("    }");
         } else if (envoy_api_v2_route_Route_has_redirect(route)) {
@@ -840,14 +810,11 @@ void MaybeLogClusterLoadAssignment(
         fields.emplace_back("  }");
       }
       // load_balancing_weight
-      const google_protobuf_UInt32Value* lb_weight =
+      AddUInt32ValueField(
+          "  load_balancing_weight",
           envoy_api_v2_endpoint_LocalityLbEndpoints_load_balancing_weight(
-              locality_endpoint);
-      if (lb_weight != nullptr) {
-        fields.emplace_back(
-            absl::StrCat("  load_balancing_weight { value: ",
-                         google_protobuf_UInt32Value_value(lb_weight), " }"));
-      }
+              locality_endpoint),
+          &fields);
       // priority
       uint32_t priority =
           envoy_api_v2_endpoint_LocalityLbEndpoints_priority(locality_endpoint);
@@ -924,16 +891,18 @@ bool DomainMatch(MatchType match_type, std::string domain_pattern,
   } else if (match_type == SUFFIX_MATCH) {
     // Asterisk must match at least one char.
     if (expected_host_name.size() < domain_pattern.size()) return false;
-    StringView pattern_suffix(domain_pattern.c_str() + 1);
-    StringView host_suffix(expected_host_name.c_str() +
-                           expected_host_name.size() - pattern_suffix.size());
+    absl::string_view pattern_suffix(domain_pattern.c_str() + 1);
+    absl::string_view host_suffix(expected_host_name.c_str() +
+                                  expected_host_name.size() -
+                                  pattern_suffix.size());
     return pattern_suffix == host_suffix;
   } else if (match_type == PREFIX_MATCH) {
     // Asterisk must match at least one char.
     if (expected_host_name.size() < domain_pattern.size()) return false;
-    StringView pattern_prefix(domain_pattern.c_str(),
-                              domain_pattern.size() - 1);
-    StringView host_prefix(expected_host_name.c_str(), pattern_prefix.size());
+    absl::string_view pattern_prefix(domain_pattern.c_str(),
+                                     domain_pattern.size() - 1);
+    absl::string_view host_prefix(expected_host_name.c_str(),
+                                  pattern_prefix.size());
     return pattern_prefix == host_prefix;
   } else {
     return match_type == UNIVERSE_MATCH;
@@ -949,6 +918,76 @@ MatchType DomainPatternMatchType(const std::string& domain_pattern) {
   return INVALID_MATCH;
 }
 
+grpc_error* RouteActionParse(const envoy_api_v2_route_Route* route,
+                             XdsApi::RdsUpdate::RdsRoute* rds_route) {
+  if (!envoy_api_v2_route_Route_has_route(route)) {
+    return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "No RouteAction found in route.");
+  }
+  const envoy_api_v2_route_RouteAction* route_action =
+      envoy_api_v2_route_Route_route(route);
+  // Get the cluster or weighted_clusters in the RouteAction.
+  if (envoy_api_v2_route_RouteAction_has_cluster(route_action)) {
+    const upb_strview cluster_name =
+        envoy_api_v2_route_RouteAction_cluster(route_action);
+    if (cluster_name.size == 0) {
+      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "RouteAction cluster contains empty cluster name.");
+    }
+    rds_route->cluster_name = UpbStringToStdString(cluster_name);
+  } else if (envoy_api_v2_route_RouteAction_has_weighted_clusters(
+                 route_action)) {
+    const envoy_api_v2_route_WeightedCluster* weighted_cluster =
+        envoy_api_v2_route_RouteAction_weighted_clusters(route_action);
+    uint32_t total_weight = 100;
+    const google_protobuf_UInt32Value* weight =
+        envoy_api_v2_route_WeightedCluster_total_weight(weighted_cluster);
+    if (weight != nullptr) {
+      total_weight = google_protobuf_UInt32Value_value(weight);
+    }
+    size_t clusters_size;
+    const envoy_api_v2_route_WeightedCluster_ClusterWeight* const* clusters =
+        envoy_api_v2_route_WeightedCluster_clusters(weighted_cluster,
+                                                    &clusters_size);
+    uint32_t sum_of_weights = 0;
+    for (size_t j = 0; j < clusters_size; ++j) {
+      const envoy_api_v2_route_WeightedCluster_ClusterWeight* cluster_weight =
+          clusters[j];
+      XdsApi::RdsUpdate::RdsRoute::ClusterWeight cluster;
+      cluster.name = UpbStringToStdString(
+          envoy_api_v2_route_WeightedCluster_ClusterWeight_name(
+              cluster_weight));
+      if (cluster.name.empty()) {
+        return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+            "RouteAction weighted_cluster cluster contains empty cluster "
+            "name.");
+      }
+      const google_protobuf_UInt32Value* weight =
+          envoy_api_v2_route_WeightedCluster_ClusterWeight_weight(
+              cluster_weight);
+      if (weight == nullptr) {
+        return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+            "RouteAction weighted_cluster cluster missing weight");
+      }
+      cluster.weight = google_protobuf_UInt32Value_value(weight);
+      sum_of_weights += cluster.weight;
+      rds_route->weighted_clusters.emplace_back(std::move(cluster));
+    }
+    if (total_weight != sum_of_weights) {
+      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "RouteAction weighted_cluster has incorrect total weight");
+    }
+    if (rds_route->weighted_clusters.empty()) {
+      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "RouteAction weighted_cluster has no valid clusters specified.");
+    }
+  } else {
+    return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "No cluster or weighted_clusters found in RouteAction.");
+  }
+  return GRPC_ERROR_NONE;
+}
+
 grpc_error* RouteConfigParse(
     XdsClient* client, TraceFlag* tracer,
     const envoy_api_v2_RouteConfiguration* route_config,
@@ -1015,12 +1054,34 @@ grpc_error* RouteConfigParse(
   }
   // If xds_routing is not configured, only look at the last one in the route
   // list (the default route)
-  size_t start_index = xds_routing_enabled ? 0 : size - 1;
-  for (size_t i = start_index; i < size; ++i) {
+  if (!xds_routing_enabled) {
+    const envoy_api_v2_route_Route* route = routes[size - 1];
+    const envoy_api_v2_route_RouteMatch* match =
+        envoy_api_v2_route_Route_match(route);
+    XdsApi::RdsUpdate::RdsRoute rds_route;
+    // if xds routing is not enabled, we must be working on the default route;
+    // in this case, we must have an empty or single slash prefix.
+    if (!envoy_api_v2_route_RouteMatch_has_prefix(match)) {
+      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "No prefix field found in Default RouteMatch.");
+    }
+    const upb_strview prefix = envoy_api_v2_route_RouteMatch_prefix(match);
+    if (!upb_strview_eql(prefix, upb_strview_makez("")) &&
+        !upb_strview_eql(prefix, upb_strview_makez("/"))) {
+      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "Default route must have empty prefix.");
+    }
+    grpc_error* error = RouteActionParse(route, &rds_route);
+    if (error != GRPC_ERROR_NONE) return error;
+    rds_update->routes.emplace_back(std::move(rds_route));
+    return GRPC_ERROR_NONE;
+  }
+  // Loop over the whole list of routes
+  for (size_t i = 0; i < size; ++i) {
     const envoy_api_v2_route_Route* route = routes[i];
     const envoy_api_v2_route_RouteMatch* match =
         envoy_api_v2_route_Route_match(route);
-    XdsApi::RdsRoute rds_route;
+    XdsApi::RdsUpdate::RdsRoute rds_route;
     if (envoy_api_v2_route_RouteMatch_has_prefix(match)) {
       upb_strview prefix = envoy_api_v2_route_RouteMatch_prefix(match);
       // Empty prefix "" is accepted.
@@ -1072,38 +1133,16 @@ grpc_error* RouteConfigParse(
       rds_route.service = std::string(path_elements[0]);
       rds_route.method = std::string(path_elements[1]);
     } else {
-      // TODO(donnadionne): We may change this behavior once we decide how to
-      // handle unsupported fields.
+      // Path specifier types will be supported, ignore but not reject until
+      // they are implemented.
       continue;
     }
-    if (!envoy_api_v2_route_Route_has_route(route)) {
-      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-          "No RouteAction found in route.");
-    }
-    const envoy_api_v2_route_RouteAction* route_action =
-        envoy_api_v2_route_Route_route(route);
-    // Get the cluster in the RouteAction.
-    if (!envoy_api_v2_route_RouteAction_has_cluster(route_action)) {
-      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-          "No cluster found in RouteAction.");
-    }
-    const upb_strview action =
-        envoy_api_v2_route_RouteAction_cluster(route_action);
-    if (action.size == 0) {
-      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-          "RouteAction contains empty cluster.");
-    }
-    rds_route.cluster_name = std::string(action.data, action.size);
+    grpc_error* error = RouteActionParse(route, &rds_route);
+    if (error != GRPC_ERROR_NONE) return error;
     rds_update->routes.emplace_back(std::move(rds_route));
   }
   if (rds_update->routes.empty()) {
     return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No valid routes specified.");
-  } else {
-    if (!rds_update->routes.back().service.empty() ||
-        !rds_update->routes.back().method.empty()) {
-      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-          "Default route must have empty service and method");
-    }
   }
   return GRPC_ERROR_NONE;
 }
@@ -1142,7 +1181,7 @@ grpc_error* LdsResponseParse(XdsClient* client, TraceFlag* tracer,
         envoy_api_v2_Listener_api_listener(listener);
     if (api_listener == nullptr) {
       return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-          "Listener doesn't have ApiListener.");
+          "Listener has no ApiListener.");
     }
     const upb_strview encoded_api_listener = google_protobuf_Any_value(
         envoy_config_listener_v2_ApiListener_api_listener(api_listener));
@@ -1171,28 +1210,38 @@ grpc_error* LdsResponseParse(XdsClient* client, TraceFlag* tracer,
       return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
           "HttpConnectionManager neither has inlined route_config nor RDS.");
     }
-    // Get the route_config_name.
     const envoy_config_filter_network_http_connection_manager_v2_Rds* rds =
         envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_rds(
             http_connection_manager);
-    const upb_strview route_config_name =
-        envoy_config_filter_network_http_connection_manager_v2_Rds_route_config_name(
+    // Check that the ConfigSource specifies ADS.
+    const envoy_api_v2_core_ConfigSource* config_source =
+        envoy_config_filter_network_http_connection_manager_v2_Rds_config_source(
             rds);
+    if (config_source == nullptr) {
+      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "HttpConnectionManager missing config_source for RDS.");
+    }
+    if (!envoy_api_v2_core_ConfigSource_has_ads(config_source)) {
+      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "HttpConnectionManager ConfigSource for RDS does not specify ADS.");
+    }
+    // Get the route_config_name.
     lds_update->emplace();
-    (*lds_update)->route_config_name =
-        std::string(route_config_name.data, route_config_name.size);
+    (*lds_update)->route_config_name = UpbStringToStdString(
+        envoy_config_filter_network_http_connection_manager_v2_Rds_route_config_name(
+            rds));
     return GRPC_ERROR_NONE;
   }
   return GRPC_ERROR_NONE;
 }
 
-grpc_error* RdsResponseParse(XdsClient* client, TraceFlag* tracer,
-                             const envoy_api_v2_DiscoveryResponse* response,
-                             const std::string& expected_server_name,
-                             const std::string& expected_route_config_name,
-                             const bool xds_routing_enabled,
-                             absl::optional<XdsApi::RdsUpdate>* rds_update,
-                             upb_arena* arena) {
+grpc_error* RdsResponseParse(
+    XdsClient* client, TraceFlag* tracer,
+    const envoy_api_v2_DiscoveryResponse* response,
+    const std::string& expected_server_name,
+    const std::set<absl::string_view>& expected_route_configuration_names,
+    const bool xds_routing_enabled,
+    absl::optional<XdsApi::RdsUpdate>* rds_update, upb_arena* arena) {
   // Get the resources from the response.
   size_t size;
   const google_protobuf_Any* const* resources =
@@ -1213,10 +1262,14 @@ grpc_error* RdsResponseParse(XdsClient* client, TraceFlag* tracer,
       return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode route_config.");
     }
     // Check route_config_name. Ignore unexpected route_config.
-    const upb_strview name = envoy_api_v2_RouteConfiguration_name(route_config);
-    const upb_strview expected_name =
-        upb_strview_makez(expected_route_config_name.c_str());
-    if (!upb_strview_eql(name, expected_name)) continue;
+    const upb_strview route_config_name =
+        envoy_api_v2_RouteConfiguration_name(route_config);
+    absl::string_view route_config_name_strview(route_config_name.data,
+                                                route_config_name.size);
+    if (expected_route_configuration_names.find(route_config_name_strview) ==
+        expected_route_configuration_names.end()) {
+      continue;
+    }
     // Parse the route_config.
     XdsApi::RdsUpdate local_rds_update;
     grpc_error* error =
@@ -1229,11 +1282,11 @@ grpc_error* RdsResponseParse(XdsClient* client, TraceFlag* tracer,
   return GRPC_ERROR_NONE;
 }
 
-grpc_error* CdsResponseParse(XdsClient* client, TraceFlag* tracer,
-                             const envoy_api_v2_DiscoveryResponse* response,
-                             const std::set<StringView>& expected_cluster_names,
-                             XdsApi::CdsUpdateMap* cds_update_map,
-                             upb_arena* arena) {
+grpc_error* CdsResponseParse(
+    XdsClient* client, TraceFlag* tracer,
+    const envoy_api_v2_DiscoveryResponse* response,
+    const std::set<absl::string_view>& expected_cluster_names,
+    XdsApi::CdsUpdateMap* cds_update_map, upb_arena* arena) {
   // Get the resources from the response.
   size_t size;
   const google_protobuf_Any* const* resources =
@@ -1256,7 +1309,8 @@ grpc_error* CdsResponseParse(XdsClient* client, TraceFlag* tracer,
     MaybeLogCluster(client, tracer, cluster);
     // Ignore unexpected cluster names.
     upb_strview cluster_name = envoy_api_v2_Cluster_name(cluster);
-    StringView cluster_name_strview(cluster_name.data, cluster_name.size);
+    absl::string_view cluster_name_strview(cluster_name.data,
+                                           cluster_name.size);
     if (expected_cluster_names.find(cluster_name_strview) ==
         expected_cluster_names.end()) {
       continue;
@@ -1274,14 +1328,14 @@ grpc_error* CdsResponseParse(XdsClient* client, TraceFlag* tracer,
     const envoy_api_v2_core_ConfigSource* eds_config =
         envoy_api_v2_Cluster_EdsClusterConfig_eds_config(eds_cluster_config);
     if (!envoy_api_v2_core_ConfigSource_has_ads(eds_config)) {
-      return GRPC_ERROR_CREATE_FROM_STATIC_STRING("ConfigSource is not ADS.");
+      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "EDS ConfigSource is not ADS.");
     }
     // Record EDS service_name (if any).
     upb_strview service_name =
         envoy_api_v2_Cluster_EdsClusterConfig_service_name(eds_cluster_config);
     if (service_name.size != 0) {
-      cds_update.eds_service_name =
-          std::string(service_name.data, service_name.size);
+      cds_update.eds_service_name = UpbStringToStdString(service_name);
     }
     // Check the LB policy.
     if (envoy_api_v2_Cluster_lb_policy(cluster) !=
@@ -1295,11 +1349,11 @@ grpc_error* CdsResponseParse(XdsClient* client, TraceFlag* tracer,
     if (lrs_server != nullptr) {
       if (!envoy_api_v2_core_ConfigSource_has_self(lrs_server)) {
         return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-            "ConfigSource is not self.");
+            "LRS ConfigSource is not self.");
       }
       cds_update.lrs_load_reporting_server_name.emplace("");
     }
-    cds_update_map->emplace(std::string(cluster_name.data, cluster_name.size),
+    cds_update_map->emplace(UpbStringToStdString(cluster_name),
                             std::move(cds_update));
   }
   return GRPC_ERROR_NONE;
@@ -1360,8 +1414,8 @@ grpc_error* LocalityParse(
   upb_strview zone = envoy_api_v2_core_Locality_region(locality);
   upb_strview sub_zone = envoy_api_v2_core_Locality_sub_zone(locality);
   output_locality->name = MakeRefCounted<XdsLocalityName>(
-      std::string(region.data, region.size), std::string(zone.data, zone.size),
-      std::string(sub_zone.data, sub_zone.size));
+      UpbStringToStdString(region), UpbStringToStdString(zone),
+      UpbStringToStdString(sub_zone));
   // Parse the addresses.
   size_t size;
   const envoy_api_v2_endpoint_LbEndpoint* const* lb_endpoints =
@@ -1411,15 +1465,14 @@ grpc_error* DropParseAndAppend(
   }
   // Cap numerator to 1000000.
   numerator = GPR_MIN(numerator, 1000000);
-  drop_config->AddCategory(std::string(category.data, category.size),
-                           numerator);
+  drop_config->AddCategory(UpbStringToStdString(category), numerator);
   return GRPC_ERROR_NONE;
 }
 
 grpc_error* EdsResponseParse(
     XdsClient* client, TraceFlag* tracer,
     const envoy_api_v2_DiscoveryResponse* response,
-    const std::set<StringView>& expected_eds_service_names,
+    const std::set<absl::string_view>& expected_eds_service_names,
     XdsApi::EdsUpdateMap* eds_update_map, upb_arena* arena) {
   // Get the resources from the response.
   size_t size;
@@ -1448,7 +1501,8 @@ grpc_error* EdsResponseParse(
     // unexpected names.
     upb_strview cluster_name = envoy_api_v2_ClusterLoadAssignment_cluster_name(
         cluster_load_assignment);
-    StringView cluster_name_strview(cluster_name.data, cluster_name.size);
+    absl::string_view cluster_name_strview(cluster_name.data,
+                                           cluster_name.size);
     if (expected_eds_service_names.find(cluster_name_strview) ==
         expected_eds_service_names.end()) {
       continue;
@@ -1490,7 +1544,7 @@ grpc_error* EdsResponseParse(
         if (error != GRPC_ERROR_NONE) return error;
       }
     }
-    eds_update_map->emplace(std::string(cluster_name.data, cluster_name.size),
+    eds_update_map->emplace(UpbStringToStdString(cluster_name),
                             std::move(eds_update));
   }
   return GRPC_ERROR_NONE;
@@ -1500,10 +1554,9 @@ grpc_error* EdsResponseParse(
 
 grpc_error* XdsApi::ParseAdsResponse(
     const grpc_slice& encoded_response, const std::string& expected_server_name,
-    const std::string& expected_route_config_name,
-    const bool xds_routing_enabled,
-    const std::set<StringView>& expected_cluster_names,
-    const std::set<StringView>& expected_eds_service_names,
+    const std::set<absl::string_view>& expected_route_configuration_names,
+    const std::set<absl::string_view>& expected_cluster_names,
+    const std::set<absl::string_view>& expected_eds_service_names,
     absl::optional<LdsUpdate>* lds_update,
     absl::optional<RdsUpdate>* rds_update, CdsUpdateMap* cds_update_map,
     EdsUpdateMap* eds_update_map, std::string* version, std::string* nonce,
@@ -1524,20 +1577,20 @@ grpc_error* XdsApi::ParseAdsResponse(
   // Record the type_url, the version_info, and the nonce of the response.
   upb_strview type_url_strview =
       envoy_api_v2_DiscoveryResponse_type_url(response);
-  *type_url = std::string(type_url_strview.data, type_url_strview.size);
+  *type_url = UpbStringToStdString(type_url_strview);
   upb_strview version_info =
       envoy_api_v2_DiscoveryResponse_version_info(response);
-  *version = std::string(version_info.data, version_info.size);
+  *version = UpbStringToStdString(version_info);
   upb_strview nonce_strview = envoy_api_v2_DiscoveryResponse_nonce(response);
-  *nonce = std::string(nonce_strview.data, nonce_strview.size);
+  *nonce = UpbStringToStdString(nonce_strview);
   // Parse the response according to the resource type.
   if (*type_url == kLdsTypeUrl) {
     return LdsResponseParse(client_, tracer_, response, expected_server_name,
-                            xds_routing_enabled, lds_update, arena.ptr());
+                            xds_routing_enabled_, lds_update, arena.ptr());
   } else if (*type_url == kRdsTypeUrl) {
     return RdsResponseParse(client_, tracer_, response, expected_server_name,
-                            expected_route_config_name, xds_routing_enabled,
-                            rds_update, arena.ptr());
+                            expected_route_configuration_names,
+                            xds_routing_enabled_, rds_update, arena.ptr());
   } else if (*type_url == kCdsTypeUrl) {
     return CdsResponseParse(client_, tracer_, response, expected_cluster_names,
                             cds_update_map, arena.ptr());
@@ -1690,6 +1743,9 @@ grpc_slice XdsApi::CreateLrsInitialRequest(const std::string& server_name) {
                                                                 arena.ptr());
   PopulateNode(arena.ptr(), node_, build_version_, user_agent_name_,
                server_name, node_msg);
+  envoy_api_v2_core_Node_add_client_features(
+      node_msg, upb_strview_makez("envoy.lrs.supports_send_all_clusters"),
+      arena.ptr());
   MaybeLogLrsRequest(client_, tracer_, request);
   return SerializeLrsRequest(request, arena.ptr());
 }
@@ -1808,6 +1864,7 @@ grpc_slice XdsApi::CreateLrsRequest(
 }
 
 grpc_error* XdsApi::ParseLrsResponse(const grpc_slice& encoded_response,
+                                     bool* send_all_clusters,
                                      std::set<std::string>* cluster_names,
                                      grpc_millis* load_reporting_interval) {
   upb::Arena arena;
@@ -1820,13 +1877,19 @@ grpc_error* XdsApi::ParseLrsResponse(const grpc_slice& encoded_response,
   if (decoded_response == nullptr) {
     return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode response.");
   }
-  // Store the cluster names.
-  size_t size;
-  const upb_strview* clusters =
-      envoy_service_load_stats_v2_LoadStatsResponse_clusters(decoded_response,
-                                                             &size);
-  for (size_t i = 0; i < size; ++i) {
-    cluster_names->emplace(clusters[i].data, clusters[i].size);
+  // Check send_all_clusters.
+  if (envoy_service_load_stats_v2_LoadStatsResponse_send_all_clusters(
+          decoded_response)) {
+    *send_all_clusters = true;
+  } else {
+    // Store the cluster names.
+    size_t size;
+    const upb_strview* clusters =
+        envoy_service_load_stats_v2_LoadStatsResponse_clusters(decoded_response,
+                                                               &size);
+    for (size_t i = 0; i < size; ++i) {
+      cluster_names->emplace(clusters[i].data, clusters[i].size);
+    }
   }
   // Get the load report interval.
   const google_protobuf_Duration* load_reporting_interval_duration =
index 9bd74c7..8971faf 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <set>
 
+#include "absl/container/inlined_vector.h"
 #include "absl/types/optional.h"
 
 #include <grpc/slice_buffer.h>
@@ -44,18 +45,31 @@ class XdsApi {
   static const char* kCdsTypeUrl;
   static const char* kEdsTypeUrl;
 
-  struct RdsRoute {
-    std::string service;
-    std::string method;
-    std::string cluster_name;
+  struct RdsUpdate {
+    struct RdsRoute {
+      std::string service;
+      std::string method;
+      // TODO(donnadionne): When we can use absl::variant<>, consider using that
+      // here, to enforce the fact that only one of cluster_name and
+      // weighted_clusters can be set.
+      std::string cluster_name;
+      struct ClusterWeight {
+        std::string name;
+        uint32_t weight;
+
+        bool operator==(const ClusterWeight& other) const {
+          return (name == other.name && weight == other.weight);
+        }
+      };
+      std::vector<ClusterWeight> weighted_clusters;
 
-    bool operator==(const RdsRoute& other) const {
-      return (service == other.service && method == other.method &&
-              cluster_name == other.cluster_name);
-    }
-  };
+      bool operator==(const RdsRoute& other) const {
+        return (service == other.service && method == other.method &&
+                cluster_name == other.cluster_name &&
+                weighted_clusters == other.weighted_clusters);
+      }
+    };
 
-  struct RdsUpdate {
     std::vector<RdsRoute> routes;
 
     bool operator==(const RdsUpdate& other) const {
@@ -150,7 +164,7 @@ class XdsApi {
     }
 
    private:
-    InlinedVector<LocalityMap, 2> priorities_;
+    absl::InlinedVector<LocalityMap, 2> priorities_;
   };
 
   // There are two phases of accessing this class's content:
@@ -169,7 +183,7 @@ class XdsApi {
       const uint32_t parts_per_million;
     };
 
-    using DropCategoryList = InlinedVector<DropCategory, 2>;
+    using DropCategoryList = absl::InlinedVector<DropCategory, 2>;
 
     void AddCategory(std::string name, uint32_t parts_per_million) {
       drop_category_list_.emplace_back(
@@ -216,36 +230,10 @@ class XdsApi {
 
   XdsApi(XdsClient* client, TraceFlag* tracer, const XdsBootstrap::Node* node);
 
-  // Creates a request to nack an unsupported resource type.
-  // Takes ownership of \a error.
-  grpc_slice CreateUnsupportedTypeNackRequest(const std::string& type_url,
-                                              const std::string& nonce,
-                                              grpc_error* error);
-
-  // Creates an LDS request querying \a server_name.
-  // Takes ownership of \a error.
-  grpc_slice CreateLdsRequest(const std::string& server_name,
-                              const std::string& version,
-                              const std::string& nonce, grpc_error* error,
-                              bool populate_node);
-
-  // Creates an RDS request querying \a route_config_name.
-  // Takes ownership of \a error.
-  grpc_slice CreateRdsRequest(const std::string& route_config_name,
-                              const std::string& version,
-                              const std::string& nonce, grpc_error* error,
-                              bool populate_node);
-
-  // Creates a CDS request querying \a cluster_names.
-  // Takes ownership of \a error.
-  grpc_slice CreateCdsRequest(const std::set<StringView>& cluster_names,
-                              const std::string& version,
-                              const std::string& nonce, grpc_error* error,
-                              bool populate_node);
-
-  // Creates an EDS request querying \a eds_service_names.
+  // Creates an ADS request.
   // Takes ownership of \a error.
-  grpc_slice CreateEdsRequest(const std::set<StringView>& eds_service_names,
+  grpc_slice CreateAdsRequest(const std::string& type_url,
+                              const std::set<absl::string_view>& resource_names,
                               const std::string& version,
                               const std::string& nonce, grpc_error* error,
                               bool populate_node);
@@ -256,10 +244,9 @@ class XdsApi {
   grpc_error* ParseAdsResponse(
       const grpc_slice& encoded_response,
       const std::string& expected_server_name,
-      const std::string& expected_route_config_name,
-      const bool xds_routing_enabled,
-      const std::set<StringView>& expected_cluster_names,
-      const std::set<StringView>& expected_eds_service_names,
+      const std::set<absl::string_view>& expected_route_configuration_names,
+      const std::set<absl::string_view>& expected_cluster_names,
+      const std::set<absl::string_view>& expected_eds_service_names,
       absl::optional<LdsUpdate>* lds_update,
       absl::optional<RdsUpdate>* rds_update, CdsUpdateMap* cds_update_map,
       EdsUpdateMap* eds_update_map, std::string* version, std::string* nonce,
@@ -275,12 +262,14 @@ class XdsApi {
   // load_reporting_interval for client-side load reporting. If there is any
   // error, the output config is invalid.
   grpc_error* ParseLrsResponse(const grpc_slice& encoded_response,
+                               bool* send_all_clusters,
                                std::set<std::string>* cluster_names,
                                grpc_millis* load_reporting_interval);
 
  private:
   XdsClient* client_;
   TraceFlag* tracer_;
+  const bool xds_routing_enabled_;
   const XdsBootstrap::Node* node_;
   const std::string build_version_;
   const std::string user_agent_name_;
index 6a64171..25ce4a7 100644 (file)
 
 #include "src/core/ext/filters/client_channel/xds/xds_bootstrap.h"
 
+#include <vector>
+
 #include <errno.h>
 #include <stdlib.h>
 
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
+
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/string.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/slice/slice_internal.h"
 
@@ -31,47 +38,36 @@ namespace grpc_core {
 
 namespace {
 
-UniquePtr<char> BootstrapString(const XdsBootstrap& bootstrap) {
-  gpr_strvec v;
-  gpr_strvec_init(&v);
-  char* tmp;
+std::string BootstrapString(const XdsBootstrap& bootstrap) {
+  std::vector<std::string> parts;
   if (bootstrap.node() != nullptr) {
-    gpr_asprintf(&tmp,
-                 "node={\n"
-                 "  id=\"%s\",\n"
-                 "  cluster=\"%s\",\n"
-                 "  locality={\n"
-                 "    region=\"%s\",\n"
-                 "    zone=\"%s\",\n"
-                 "    subzone=\"%s\"\n"
-                 "  },\n"
-                 "  metadata=%s,\n"
-                 "},\n",
-                 bootstrap.node()->id.c_str(),
-                 bootstrap.node()->cluster.c_str(),
-                 bootstrap.node()->locality_region.c_str(),
-                 bootstrap.node()->locality_zone.c_str(),
-                 bootstrap.node()->locality_subzone.c_str(),
-                 bootstrap.node()->metadata.Dump().c_str());
-    gpr_strvec_add(&v, tmp);
+    parts.push_back(absl::StrFormat(
+        "node={\n"
+        "  id=\"%s\",\n"
+        "  cluster=\"%s\",\n"
+        "  locality={\n"
+        "    region=\"%s\",\n"
+        "    zone=\"%s\",\n"
+        "    subzone=\"%s\"\n"
+        "  },\n"
+        "  metadata=%s,\n"
+        "},\n",
+        bootstrap.node()->id, bootstrap.node()->cluster,
+        bootstrap.node()->locality_region, bootstrap.node()->locality_zone,
+        bootstrap.node()->locality_subzone, bootstrap.node()->metadata.Dump()));
   }
-  gpr_asprintf(&tmp,
-               "servers=[\n"
-               "  {\n"
-               "    uri=\"%s\",\n"
-               "    creds=[\n",
-               bootstrap.server().server_uri.c_str());
-  gpr_strvec_add(&v, tmp);
-  for (size_t i = 0; i < bootstrap.server().channel_creds.size(); ++i) {
-    const auto& creds = bootstrap.server().channel_creds[i];
-    gpr_asprintf(&tmp, "      {type=\"%s\", config=%s},\n", creds.type.c_str(),
-                 creds.config.Dump().c_str());
-    gpr_strvec_add(&v, tmp);
+  parts.push_back(
+      absl::StrFormat("servers=[\n"
+                      "  {\n"
+                      "    uri=\"%s\",\n"
+                      "    creds=[\n",
+                      bootstrap.server().server_uri));
+  for (const auto& creds : bootstrap.server().channel_creds) {
+    parts.push_back(absl::StrFormat("      {type=\"%s\", config=%s},\n",
+                                    creds.type, creds.config.Dump()));
   }
-  gpr_strvec_add(&v, gpr_strdup("    ]\n  }\n]"));
-  UniquePtr<char> result(gpr_strvec_flatten(&v, nullptr));
-  gpr_strvec_destroy(&v);
-  return result;
+  parts.push_back("    ]\n  }\n]");
+  return absl::StrJoin(parts, "");
 }
 
 }  // namespace
@@ -94,11 +90,10 @@ std::unique_ptr<XdsBootstrap> XdsBootstrap::ReadFromFile(XdsClient* client,
   grpc_slice contents;
   *error = grpc_load_file(path.get(), /*add_null_terminator=*/true, &contents);
   if (*error != GRPC_ERROR_NONE) return nullptr;
-  StringView contents_str_view = StringViewFromSlice(contents);
+  absl::string_view contents_str_view = StringViewFromSlice(contents);
   if (GRPC_TRACE_FLAG_ENABLED(*tracer)) {
-    UniquePtr<char> str = StringViewToCString(contents_str_view);
     gpr_log(GPR_DEBUG, "[xds_client %p] Bootstrap file contents: %s", client,
-            str.get());
+            std::string(contents_str_view).c_str());
   }
   Json json = Json::Parse(contents_str_view, error);
   grpc_slice_unref_internal(contents);
@@ -117,7 +112,7 @@ std::unique_ptr<XdsBootstrap> XdsBootstrap::ReadFromFile(XdsClient* client,
   if (*error == GRPC_ERROR_NONE && GRPC_TRACE_FLAG_ENABLED(*tracer)) {
     gpr_log(GPR_INFO,
             "[xds_client %p] Bootstrap config for creating xds client:\n%s",
-            client, BootstrapString(*result).get());
+            client, BootstrapString(*result).c_str());
   }
   return result;
 }
@@ -128,7 +123,7 @@ XdsBootstrap::XdsBootstrap(Json json, grpc_error** error) {
         "malformed JSON in bootstrap file");
     return;
   }
-  InlinedVector<grpc_error*, 1> error_list;
+  std::vector<grpc_error*> error_list;
   auto it = json.mutable_object()->find("xds_servers");
   if (it == json.mutable_object()->end()) {
     error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
@@ -155,7 +150,7 @@ XdsBootstrap::XdsBootstrap(Json json, grpc_error** error) {
 }
 
 grpc_error* XdsBootstrap::ParseXdsServerList(Json* json) {
-  InlinedVector<grpc_error*, 1> error_list;
+  std::vector<grpc_error*> error_list;
   for (size_t i = 0; i < json->mutable_array()->size(); ++i) {
     Json& child = json->mutable_array()->at(i);
     if (child.type() != Json::Type::OBJECT) {
@@ -173,7 +168,7 @@ grpc_error* XdsBootstrap::ParseXdsServerList(Json* json) {
 }
 
 grpc_error* XdsBootstrap::ParseXdsServer(Json* json, size_t idx) {
-  InlinedVector<grpc_error*, 1> error_list;
+  std::vector<grpc_error*> error_list;
   servers_.emplace_back();
   XdsServer& server = servers_[servers_.size() - 1];
   auto it = json->mutable_object()->find("server_uri");
@@ -211,7 +206,7 @@ grpc_error* XdsBootstrap::ParseXdsServer(Json* json, size_t idx) {
 
 grpc_error* XdsBootstrap::ParseChannelCredsArray(Json* json,
                                                  XdsServer* server) {
-  InlinedVector<grpc_error*, 1> error_list;
+  std::vector<grpc_error*> error_list;
   for (size_t i = 0; i < json->mutable_array()->size(); ++i) {
     Json& child = json->mutable_array()->at(i);
     if (child.type() != Json::Type::OBJECT) {
@@ -230,7 +225,7 @@ grpc_error* XdsBootstrap::ParseChannelCredsArray(Json* json,
 
 grpc_error* XdsBootstrap::ParseChannelCreds(Json* json, size_t idx,
                                             XdsServer* server) {
-  InlinedVector<grpc_error*, 1> error_list;
+  std::vector<grpc_error*> error_list;
   ChannelCreds channel_creds;
   auto it = json->mutable_object()->find("type");
   if (it == json->mutable_object()->end()) {
@@ -268,7 +263,7 @@ grpc_error* XdsBootstrap::ParseChannelCreds(Json* json, size_t idx,
 }
 
 grpc_error* XdsBootstrap::ParseNode(Json* json) {
-  InlinedVector<grpc_error*, 1> error_list;
+  std::vector<grpc_error*> error_list;
   node_ = absl::make_unique<Node>();
   auto it = json->mutable_object()->find("id");
   if (it != json->mutable_object()->end()) {
@@ -312,7 +307,7 @@ grpc_error* XdsBootstrap::ParseNode(Json* json) {
 }
 
 grpc_error* XdsBootstrap::ParseLocality(Json* json) {
-  InlinedVector<grpc_error*, 1> error_list;
+  std::vector<grpc_error*> error_list;
   auto it = json->mutable_object()->find("region");
   if (it != json->mutable_object()->end()) {
     if (it->second.type() != Json::Type::STRING) {
index d3b04ad..13eff49 100644 (file)
 #include <string>
 #include <vector>
 
+#include "absl/container/inlined_vector.h"
+
 #include <grpc/impl/codegen/slice.h>
 
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/map.h"
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/iomgr/error.h"
@@ -53,7 +54,7 @@ class XdsBootstrap {
 
   struct XdsServer {
     std::string server_uri;
-    InlinedVector<ChannelCreds, 1> channel_creds;
+    absl::InlinedVector<ChannelCreds, 1> channel_creds;
   };
 
   // If *error is not GRPC_ERROR_NONE after returning, then there was an
@@ -78,7 +79,7 @@ class XdsBootstrap {
   grpc_error* ParseNode(Json* json);
   grpc_error* ParseLocality(Json* json);
 
-  InlinedVector<XdsServer, 1> servers_;
+  absl::InlinedVector<XdsServer, 1> servers_;
   std::unique_ptr<Node> node_;
 };
 
index 52d226c..c218db8 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <string.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
@@ -39,8 +41,8 @@
 namespace grpc_core {
 
 grpc_channel_args* ModifyXdsChannelArgs(grpc_channel_args* args) {
-  InlinedVector<const char*, 1> args_to_remove;
-  InlinedVector<grpc_arg, 2> args_to_add;
+  absl::InlinedVector<const char*, 1> args_to_remove;
+  absl::InlinedVector<grpc_arg, 2> args_to_add;
   // Substitute the channel credentials with a version without call
   // credentials: the load balancer is not necessarily trusted to handle
   // bearer token credentials.
index b2cbb58..db48084 100644 (file)
 #include <limits.h>
 #include <string.h>
 
+#include "absl/container/inlined_vector.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
 
 #include <grpc/byte_buffer_reader.h>
 #include <grpc/grpc.h>
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/gprpp/sync.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "src/core/lib/slice/slice_hash_table.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
@@ -96,7 +98,7 @@ class XdsClient::ChannelState::RetryableCall
   void StartNewCallLocked();
   void StartRetryTimerLocked();
   static void OnRetryTimer(void* arg, grpc_error* error);
-  static void OnRetryTimerLocked(void* arg, grpc_error* error);
+  void OnRetryTimerLocked(grpc_error* error);
 
   // The wrapped xds call that talks to the xds server. It's instantiated
   // every time we start a new call. It's null during call retry backoff.
@@ -170,51 +172,48 @@ class XdsClient::ChannelState::AdsCallState
    private:
     static void OnTimer(void* arg, grpc_error* error) {
       ResourceState* self = static_cast<ResourceState*>(arg);
-      self->ads_calld_->xds_client()->combiner_->Run(
-          GRPC_CLOSURE_INIT(&self->timer_callback_, OnTimerLocked, self,
-                            nullptr),
-          GRPC_ERROR_REF(error));
+      GRPC_ERROR_REF(error);  // ref owned by lambda
+      self->ads_calld_->xds_client()->work_serializer_->Run(
+          [self, error]() { self->OnTimerLocked(error); }, DEBUG_LOCATION);
     }
 
-    static void OnTimerLocked(void* arg, grpc_error* error) {
-      ResourceState* self = static_cast<ResourceState*>(arg);
-      if (error == GRPC_ERROR_NONE && self->timer_pending_) {
-        self->timer_pending_ = false;
+    void OnTimerLocked(grpc_error* error) {
+      if (error == GRPC_ERROR_NONE && timer_pending_) {
+        timer_pending_ = false;
         char* msg;
         gpr_asprintf(
             &msg,
             "timeout obtaining resource {type=%s name=%s} from xds server",
-            self->type_url_.c_str(), self->name_.c_str());
-        grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
+            type_url_.c_str(), name_.c_str());
+        grpc_error* watcher_error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
         gpr_free(msg);
         if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
-          gpr_log(GPR_INFO, "[xds_client %p] %s",
-                  self->ads_calld_->xds_client(), grpc_error_string(error));
+          gpr_log(GPR_INFO, "[xds_client %p] %s", ads_calld_->xds_client(),
+                  grpc_error_string(watcher_error));
         }
-        if (self->type_url_ == XdsApi::kLdsTypeUrl ||
-            self->type_url_ == XdsApi::kRdsTypeUrl) {
-          self->ads_calld_->xds_client()->service_config_watcher_->OnError(
-              error);
-        } else if (self->type_url_ == XdsApi::kCdsTypeUrl) {
-          ClusterState& state =
-              self->ads_calld_->xds_client()->cluster_map_[self->name_];
+        if (type_url_ == XdsApi::kLdsTypeUrl ||
+            type_url_ == XdsApi::kRdsTypeUrl) {
+          ads_calld_->xds_client()->service_config_watcher_->OnError(
+              watcher_error);
+        } else if (type_url_ == XdsApi::kCdsTypeUrl) {
+          ClusterState& state = ads_calld_->xds_client()->cluster_map_[name_];
           for (const auto& p : state.watchers) {
-            p.first->OnError(GRPC_ERROR_REF(error));
+            p.first->OnError(GRPC_ERROR_REF(watcher_error));
           }
-          GRPC_ERROR_UNREF(error);
-        } else if (self->type_url_ == XdsApi::kEdsTypeUrl) {
-          EndpointState& state =
-              self->ads_calld_->xds_client()->endpoint_map_[self->name_];
+          GRPC_ERROR_UNREF(watcher_error);
+        } else if (type_url_ == XdsApi::kEdsTypeUrl) {
+          EndpointState& state = ads_calld_->xds_client()->endpoint_map_[name_];
           for (const auto& p : state.watchers) {
-            p.first->OnError(GRPC_ERROR_REF(error));
+            p.first->OnError(GRPC_ERROR_REF(watcher_error));
           }
-          GRPC_ERROR_UNREF(error);
+          GRPC_ERROR_UNREF(watcher_error);
         } else {
           GPR_UNREACHABLE_CODE(return );
         }
       }
-      self->ads_calld_.reset();
-      self->Unref();
+      ads_calld_.reset();
+      Unref();
+      GRPC_ERROR_UNREF(error);
     }
 
     const std::string type_url_;
@@ -248,16 +247,16 @@ class XdsClient::ChannelState::AdsCallState
   void AcceptEdsUpdate(XdsApi::EdsUpdateMap eds_update_map);
 
   static void OnRequestSent(void* arg, grpc_error* error);
-  static void OnRequestSentLocked(void* arg, grpc_error* error);
+  void OnRequestSentLocked(grpc_error* error);
   static void OnResponseReceived(void* arg, grpc_error* error);
-  static void OnResponseReceivedLocked(void* arg, grpc_error* error);
+  void OnResponseReceivedLocked();
   static void OnStatusReceived(void* arg, grpc_error* error);
-  static void OnStatusReceivedLocked(void* arg, grpc_error* error);
+  void OnStatusReceivedLocked(grpc_error* error);
 
   bool IsCurrentCallOnChannel() const;
 
-  std::set<StringView> ClusterNamesForRequest();
-  std::set<StringView> EdsServiceNamesForRequest();
+  std::set<absl::string_view> ResourceNamesForRequest(
+      const std::string& type_url);
 
   // The owning RetryableCall<>.
   RefCountedPtr<RetryableCall<AdsCallState>> parent_;
@@ -315,6 +314,10 @@ class XdsClient::ChannelState::LrsCallState
    public:
     Reporter(RefCountedPtr<LrsCallState> parent, grpc_millis report_interval)
         : parent_(std::move(parent)), report_interval_(report_interval) {
+      GRPC_CLOSURE_INIT(&on_next_report_timer_, OnNextReportTimer, this,
+                        grpc_schedule_on_exec_ctx);
+      GRPC_CLOSURE_INIT(&on_report_done_, OnReportDone, this,
+                        grpc_schedule_on_exec_ctx);
       ScheduleNextReportLocked();
     }
 
@@ -323,10 +326,10 @@ class XdsClient::ChannelState::LrsCallState
    private:
     void ScheduleNextReportLocked();
     static void OnNextReportTimer(void* arg, grpc_error* error);
-    static void OnNextReportTimerLocked(void* arg, grpc_error* error);
+    void OnNextReportTimerLocked(grpc_error* error);
     void SendReportLocked();
     static void OnReportDone(void* arg, grpc_error* error);
-    static void OnReportDoneLocked(void* arg, grpc_error* error);
+    void OnReportDoneLocked(grpc_error* error);
 
     bool IsCurrentReporterOnCall() const {
       return this == parent_->reporter_.get();
@@ -346,11 +349,11 @@ class XdsClient::ChannelState::LrsCallState
   };
 
   static void OnInitialRequestSent(void* arg, grpc_error* error);
+  void OnInitialRequestSentLocked();
   static void OnResponseReceived(void* arg, grpc_error* error);
+  void OnResponseReceivedLocked();
   static void OnStatusReceived(void* arg, grpc_error* error);
-  static void OnInitialRequestSentLocked(void* arg, grpc_error* error);
-  static void OnResponseReceivedLocked(void* arg, grpc_error* error);
-  static void OnStatusReceivedLocked(void* arg, grpc_error* error);
+  void OnStatusReceivedLocked(grpc_error* error);
 
   bool IsCurrentCallOnChannel() const;
 
@@ -379,6 +382,7 @@ class XdsClient::ChannelState::LrsCallState
   grpc_closure on_status_received_;
 
   // Load reporting state.
+  bool send_all_clusters_ = false;
   std::set<std::string> cluster_names_;  // Asked for by the LRS server.
   grpc_millis load_reporting_interval_ = 0;
   OrphanablePtr<Reporter> reporter_;
@@ -392,7 +396,8 @@ class XdsClient::ChannelState::StateWatcher
     : public AsyncConnectivityStateWatcherInterface {
  public:
   explicit StateWatcher(RefCountedPtr<ChannelState> parent)
-      : AsyncConnectivityStateWatcherInterface(parent->xds_client()->combiner_),
+      : AsyncConnectivityStateWatcherInterface(
+            parent->xds_client()->work_serializer_),
         parent_(std::move(parent)) {}
 
  private:
@@ -445,7 +450,7 @@ grpc_channel_args* BuildXdsChannelArgs(const grpc_channel_args& args) {
       GRPC_ARG_KEEPALIVE_TIME_MS,
   };
   // Channel args to add.
-  InlinedVector<grpc_arg, 3> args_to_add;
+  absl::InlinedVector<grpc_arg, 3> args_to_add;
   // Keepalive interval.
   args_to_add.emplace_back(grpc_channel_arg_integer_create(
       const_cast<char*>(GRPC_ARG_KEEPALIVE_TIME_MS), 5000));
@@ -581,6 +586,9 @@ XdsClient::ChannelState::RetryableCall<T>::RetryableCall(
               .set_multiplier(GRPC_XDS_RECONNECT_BACKOFF_MULTIPLIER)
               .set_jitter(GRPC_XDS_RECONNECT_JITTER)
               .set_max_backoff(GRPC_XDS_RECONNECT_MAX_BACKOFF_SECONDS * 1000)) {
+  // Closure Initialization
+  GRPC_CLOSURE_INIT(&on_retry_timer_, OnRetryTimer, this,
+                    grpc_schedule_on_exec_ctx);
   StartNewCallLocked();
 }
 
@@ -634,8 +642,6 @@ void XdsClient::ChannelState::RetryableCall<T>::StartRetryTimerLocked() {
             chand()->xds_client(), chand(), timeout);
   }
   this->Ref(DEBUG_LOCATION, "RetryableCall+retry_timer_start").release();
-  GRPC_CLOSURE_INIT(&on_retry_timer_, OnRetryTimer, this,
-                    grpc_schedule_on_exec_ctx);
   grpc_timer_init(&retry_timer_, next_attempt_time, &on_retry_timer_);
   retry_timer_callback_pending_ = true;
 }
@@ -644,27 +650,26 @@ template <typename T>
 void XdsClient::ChannelState::RetryableCall<T>::OnRetryTimer(
     void* arg, grpc_error* error) {
   RetryableCall* calld = static_cast<RetryableCall*>(arg);
-  calld->chand_->xds_client()->combiner_->Run(
-      GRPC_CLOSURE_INIT(&calld->on_retry_timer_, OnRetryTimerLocked, calld,
-                        nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  calld->chand_->xds_client()->work_serializer_->Run(
+      [calld, error]() { calld->OnRetryTimerLocked(error); }, DEBUG_LOCATION);
 }
 
 template <typename T>
 void XdsClient::ChannelState::RetryableCall<T>::OnRetryTimerLocked(
-    void* arg, grpc_error* error) {
-  RetryableCall* calld = static_cast<RetryableCall*>(arg);
-  calld->retry_timer_callback_pending_ = false;
-  if (!calld->shutting_down_ && error == GRPC_ERROR_NONE) {
+    grpc_error* error) {
+  retry_timer_callback_pending_ = false;
+  if (!shutting_down_ && error == GRPC_ERROR_NONE) {
     if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
       gpr_log(
           GPR_INFO,
           "[xds_client %p] Retry timer fires (chand: %p, retryable call: %p)",
-          calld->chand()->xds_client(), calld->chand(), calld);
+          chand()->xds_client(), chand(), this);
     }
-    calld->StartNewCallLocked();
+    StartNewCallLocked();
   }
-  calld->Unref(DEBUG_LOCATION, "RetryableCall+retry_timer_done");
+  this->Unref(DEBUG_LOCATION, "RetryableCall+retry_timer_done");
+  GRPC_ERROR_UNREF(error);
 }
 
 //
@@ -799,33 +804,13 @@ void XdsClient::ChannelState::AdsCallState::SendMessageLocked(
   }
   auto& state = state_map_[type_url];
   grpc_slice request_payload_slice;
-  std::set<StringView> resource_names;
-  if (type_url == XdsApi::kLdsTypeUrl) {
-    resource_names.insert(xds_client()->server_name_);
-    request_payload_slice = xds_client()->api_.CreateLdsRequest(
-        xds_client()->server_name_, state.version, state.nonce,
-        GRPC_ERROR_REF(state.error), !sent_initial_message_);
-    state.subscribed_resources[xds_client()->server_name_]->Start(Ref());
-  } else if (type_url == XdsApi::kRdsTypeUrl) {
-    resource_names.insert(xds_client()->lds_result_->route_config_name);
-    request_payload_slice = xds_client()->api_.CreateRdsRequest(
-        xds_client()->lds_result_->route_config_name, state.version,
-        state.nonce, GRPC_ERROR_REF(state.error), !sent_initial_message_);
-    state.subscribed_resources[xds_client()->lds_result_->route_config_name]
-        ->Start(Ref());
-  } else if (type_url == XdsApi::kCdsTypeUrl) {
-    resource_names = ClusterNamesForRequest();
-    request_payload_slice = xds_client()->api_.CreateCdsRequest(
-        resource_names, state.version, state.nonce, GRPC_ERROR_REF(state.error),
-        !sent_initial_message_);
-  } else if (type_url == XdsApi::kEdsTypeUrl) {
-    resource_names = EdsServiceNamesForRequest();
-    request_payload_slice = xds_client()->api_.CreateEdsRequest(
-        resource_names, state.version, state.nonce, GRPC_ERROR_REF(state.error),
-        !sent_initial_message_);
-  } else {
-    request_payload_slice = xds_client()->api_.CreateUnsupportedTypeNackRequest(
-        type_url, state.nonce, GRPC_ERROR_REF(state.error));
+  std::set<absl::string_view> resource_names =
+      ResourceNamesForRequest(type_url);
+  request_payload_slice = xds_client()->api_.CreateAdsRequest(
+      type_url, resource_names, state.version, state.nonce,
+      GRPC_ERROR_REF(state.error), !sent_initial_message_);
+  if (type_url != XdsApi::kLdsTypeUrl && type_url != XdsApi::kRdsTypeUrl &&
+      type_url != XdsApi::kCdsTypeUrl && type_url != XdsApi::kEdsTypeUrl) {
     state_map_.erase(type_url);
   }
   sent_initial_message_ = true;
@@ -890,9 +875,15 @@ void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdate(
     gpr_log(GPR_INFO,
             "[xds_client %p] LDS update does not include requested resource",
             xds_client());
-    xds_client()->service_config_watcher_->OnError(
-        GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-            "LDS update does not include requested resource"));
+    if (xds_client()->lds_result_.has_value() &&
+        !xds_client()->lds_result_->route_config_name.empty()) {
+      Unsubscribe(XdsApi::kRdsTypeUrl,
+                  xds_client()->lds_result_->route_config_name,
+                  /*delay_unsubscription=*/false);
+      xds_client()->rds_result_.reset();
+    }
+    xds_client()->lds_result_.reset();
+    xds_client()->service_config_watcher_->OnResourceDoesNotExist();
     return;
   }
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
@@ -931,6 +922,7 @@ void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdate(
     Unsubscribe(
         XdsApi::kRdsTypeUrl, xds_client()->lds_result_->route_config_name,
         /*delay_unsubscription=*/!lds_update->route_config_name.empty());
+    xds_client()->rds_result_.reset();
   }
   xds_client()->lds_result_ = std::move(lds_update);
   if (xds_client()->lds_result_->rds_update.has_value()) {
@@ -958,9 +950,8 @@ void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdate(
     gpr_log(GPR_INFO,
             "[xds_client %p] RDS update does not include requested resource",
             xds_client());
-    xds_client()->service_config_watcher_->OnError(
-        GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-            "RDS update does not include requested resource"));
+    xds_client()->rds_result_.reset();
+    xds_client()->service_config_watcher_->OnResourceDoesNotExist();
     return;
   }
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
@@ -1046,20 +1037,20 @@ void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate(
     }
   }
   // For any subscribed resource that is not present in the update,
-  // remove it from the cache and notify watchers of the error.
+  // remove it from the cache and notify watchers that it does not exist.
   for (const auto& p : cds_state.subscribed_resources) {
     const std::string& cluster_name = p.first;
     if (cds_update_map.find(cluster_name) == cds_update_map.end()) {
       ClusterState& cluster_state = xds_client()->cluster_map_[cluster_name];
       cluster_state.update.reset();
       for (const auto& p : cluster_state.watchers) {
-        p.first->OnError(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-            "Cluster not present in CDS update"));
+        p.first->OnResourceDoesNotExist();
       }
     }
   }
-  // Also remove any EDS resources that are no longer referred to by any CDS
-  // resources.
+  // For any EDS resource that is no longer referred to by any CDS
+  // resources, remove it from the cache and notify watchers that it
+  // does not exist.
   auto& eds_state = state_map_[XdsApi::kEdsTypeUrl];
   for (const auto& p : eds_state.subscribed_resources) {
     const std::string& eds_resource_name = p.first;
@@ -1069,8 +1060,7 @@ void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate(
           xds_client()->endpoint_map_[eds_resource_name];
       endpoint_state.update.reset();
       for (const auto& p : endpoint_state.watchers) {
-        p.first->OnError(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-            "ClusterLoadAssignment resource removed due to CDS update"));
+        p.first->OnResourceDoesNotExist();
       }
     }
   }
@@ -1110,15 +1100,13 @@ void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdate(
                   locality.name->AsHumanReadableString(), locality.lb_weight,
                   locality.serverlist.size());
           for (size_t i = 0; i < locality.serverlist.size(); ++i) {
-            char* ipport;
-            grpc_sockaddr_to_string(&ipport, &locality.serverlist[i].address(),
-                                    false);
+            std::string ipport = grpc_sockaddr_to_string(
+                &locality.serverlist[i].address(), false);
             gpr_log(GPR_INFO,
                     "[xds_client %p] Priority %" PRIuPTR ", locality %" PRIuPTR
                     " %s, server address %" PRIuPTR ": %s",
                     xds_client(), priority, locality_count,
-                    locality.name->AsHumanReadableString(), i, ipport);
-            gpr_free(ipport);
+                    locality.name->AsHumanReadableString(), i, ipport.c_str());
           }
           ++locality_count;
         }
@@ -1164,19 +1152,18 @@ void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdate(
 void XdsClient::ChannelState::AdsCallState::OnRequestSent(void* arg,
                                                           grpc_error* error) {
   AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
-  ads_calld->xds_client()->combiner_->Run(
-      GRPC_CLOSURE_INIT(&ads_calld->on_request_sent_, OnRequestSentLocked,
-                        ads_calld, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  ads_calld->xds_client()->work_serializer_->Run(
+      [ads_calld, error]() { ads_calld->OnRequestSentLocked(error); },
+      DEBUG_LOCATION);
 }
 
 void XdsClient::ChannelState::AdsCallState::OnRequestSentLocked(
-    void* arg, grpc_error* error) {
-  AdsCallState* self = static_cast<AdsCallState*>(arg);
-  if (self->IsCurrentCallOnChannel() && error == GRPC_ERROR_NONE) {
+    grpc_error* error) {
+  if (IsCurrentCallOnChannel() && error == GRPC_ERROR_NONE) {
     // Clean up the sent message.
-    grpc_byte_buffer_destroy(self->send_message_payload_);
-    self->send_message_payload_ = nullptr;
+    grpc_byte_buffer_destroy(send_message_payload_);
+    send_message_payload_ = nullptr;
     // Continue to send another pending message if any.
     // TODO(roth): The current code to handle buffered messages has the
     // advantage of sending only the most recent list of resource names for
@@ -1186,41 +1173,36 @@ void XdsClient::ChannelState::AdsCallState::OnRequestSentLocked(
     // order of resource types. We need to fix this if we are seeing some
     // resource type(s) starved due to frequent requests of other resource
     // type(s).
-    auto it = self->buffered_requests_.begin();
-    if (it != self->buffered_requests_.end()) {
-      self->SendMessageLocked(*it);
-      self->buffered_requests_.erase(it);
+    auto it = buffered_requests_.begin();
+    if (it != buffered_requests_.end()) {
+      SendMessageLocked(*it);
+      buffered_requests_.erase(it);
     }
   }
-  self->Unref(DEBUG_LOCATION, "ADS+OnRequestSentLocked");
+  Unref(DEBUG_LOCATION, "ADS+OnRequestSentLocked");
+  GRPC_ERROR_UNREF(error);
 }
 
 void XdsClient::ChannelState::AdsCallState::OnResponseReceived(
-    void* arg, grpc_error* error) {
+    void* arg, grpc_error* /* error */) {
   AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
-  ads_calld->xds_client()->combiner_->Run(
-      GRPC_CLOSURE_INIT(&ads_calld->on_response_received_,
-                        OnResponseReceivedLocked, ads_calld, nullptr),
-      GRPC_ERROR_REF(error));
+  ads_calld->xds_client()->work_serializer_->Run(
+      [ads_calld]() { ads_calld->OnResponseReceivedLocked(); }, DEBUG_LOCATION);
 }
 
-void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked(
-    void* arg, grpc_error* /*error*/) {
-  AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
-  XdsClient* xds_client = ads_calld->xds_client();
+void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() {
   // Empty payload means the call was cancelled.
-  if (!ads_calld->IsCurrentCallOnChannel() ||
-      ads_calld->recv_message_payload_ == nullptr) {
-    ads_calld->Unref(DEBUG_LOCATION, "ADS+OnResponseReceivedLocked");
+  if (!IsCurrentCallOnChannel() || recv_message_payload_ == nullptr) {
+    Unref(DEBUG_LOCATION, "ADS+OnResponseReceivedLocked");
     return;
   }
   // Read the response.
   grpc_byte_buffer_reader bbr;
-  grpc_byte_buffer_reader_init(&bbr, ads_calld->recv_message_payload_);
+  grpc_byte_buffer_reader_init(&bbr, recv_message_payload_);
   grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
   grpc_byte_buffer_reader_destroy(&bbr);
-  grpc_byte_buffer_destroy(ads_calld->recv_message_payload_);
-  ads_calld->recv_message_payload_ = nullptr;
+  grpc_byte_buffer_destroy(recv_message_payload_);
+  recv_message_payload_ = nullptr;
   // TODO(juanlishen): When we convert this to use the xds protocol, the
   // balancer will send us a fallback timeout such that we should go into
   // fallback mode if we have lost contact with the balancer after a certain
@@ -1238,24 +1220,22 @@ void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked(
   std::string nonce;
   std::string type_url;
   // Note that ParseAdsResponse() also validates the response.
-  grpc_error* parse_error = xds_client->api_.ParseAdsResponse(
-      response_slice, xds_client->server_name_,
-      (xds_client->lds_result_.has_value()
-           ? xds_client->lds_result_->route_config_name
-           : ""),
-      xds_client->xds_routing_enabled_, ads_calld->ClusterNamesForRequest(),
-      ads_calld->EdsServiceNamesForRequest(), &lds_update, &rds_update,
+  grpc_error* parse_error = xds_client()->api_.ParseAdsResponse(
+      response_slice, xds_client()->server_name_,
+      ResourceNamesForRequest(XdsApi::kRdsTypeUrl),
+      ResourceNamesForRequest(XdsApi::kCdsTypeUrl),
+      ResourceNamesForRequest(XdsApi::kEdsTypeUrl), &lds_update, &rds_update,
       &cds_update_map, &eds_update_map, &version, &nonce, &type_url);
   grpc_slice_unref_internal(response_slice);
   if (type_url.empty()) {
     // Ignore unparsable response.
     gpr_log(GPR_ERROR,
             "[xds_client %p] Error parsing ADS response (%s) -- ignoring",
-            xds_client, grpc_error_string(parse_error));
+            xds_client(), grpc_error_string(parse_error));
     GRPC_ERROR_UNREF(parse_error);
   } else {
     // Update nonce.
-    auto& state = ads_calld->state_map_[type_url];
+    auto& state = state_map_[type_url];
     state.nonce = std::move(nonce);
     // NACK or ACK the response.
     if (parse_error != GRPC_ERROR_NONE) {
@@ -1265,85 +1245,80 @@ void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked(
       gpr_log(GPR_ERROR,
               "[xds_client %p] ADS response invalid for resource type %s "
               "version %s, will NACK: nonce=%s error=%s",
-              xds_client, type_url.c_str(), version.c_str(),
+              xds_client(), type_url.c_str(), version.c_str(),
               state.nonce.c_str(), grpc_error_string(parse_error));
-      ads_calld->SendMessageLocked(type_url);
+      SendMessageLocked(type_url);
     } else {
-      ads_calld->seen_response_ = true;
+      seen_response_ = true;
       // Accept the ADS response according to the type_url.
       if (type_url == XdsApi::kLdsTypeUrl) {
-        ads_calld->AcceptLdsUpdate(std::move(lds_update));
+        AcceptLdsUpdate(std::move(lds_update));
       } else if (type_url == XdsApi::kRdsTypeUrl) {
-        ads_calld->AcceptRdsUpdate(std::move(rds_update));
+        AcceptRdsUpdate(std::move(rds_update));
       } else if (type_url == XdsApi::kCdsTypeUrl) {
-        ads_calld->AcceptCdsUpdate(std::move(cds_update_map));
+        AcceptCdsUpdate(std::move(cds_update_map));
       } else if (type_url == XdsApi::kEdsTypeUrl) {
-        ads_calld->AcceptEdsUpdate(std::move(eds_update_map));
+        AcceptEdsUpdate(std::move(eds_update_map));
       }
       state.version = std::move(version);
       // ACK the update.
-      ads_calld->SendMessageLocked(type_url);
+      SendMessageLocked(type_url);
       // Start load reporting if needed.
-      auto& lrs_call = ads_calld->chand()->lrs_calld_;
+      auto& lrs_call = chand()->lrs_calld_;
       if (lrs_call != nullptr) {
         LrsCallState* lrs_calld = lrs_call->calld();
         if (lrs_calld != nullptr) lrs_calld->MaybeStartReportingLocked();
       }
     }
   }
-  if (xds_client->shutting_down_) {
-    ads_calld->Unref(DEBUG_LOCATION,
-                     "ADS+OnResponseReceivedLocked+xds_shutdown");
+  if (xds_client()->shutting_down_) {
+    Unref(DEBUG_LOCATION, "ADS+OnResponseReceivedLocked+xds_shutdown");
     return;
   }
   // Keep listening for updates.
   grpc_op op;
   memset(&op, 0, sizeof(op));
   op.op = GRPC_OP_RECV_MESSAGE;
-  op.data.recv_message.recv_message = &ads_calld->recv_message_payload_;
+  op.data.recv_message.recv_message = &recv_message_payload_;
   op.flags = 0;
   op.reserved = nullptr;
-  GPR_ASSERT(ads_calld->call_ != nullptr);
+  GPR_ASSERT(call_ != nullptr);
   // Reuse the "ADS+OnResponseReceivedLocked" ref taken in ctor.
-  GRPC_CLOSURE_INIT(&ads_calld->on_response_received_, OnResponseReceived,
-                    ads_calld, grpc_schedule_on_exec_ctx);
-  const grpc_call_error call_error = grpc_call_start_batch_and_execute(
-      ads_calld->call_, &op, 1, &ads_calld->on_response_received_);
+  const grpc_call_error call_error =
+      grpc_call_start_batch_and_execute(call_, &op, 1, &on_response_received_);
   GPR_ASSERT(GRPC_CALL_OK == call_error);
 }
 
 void XdsClient::ChannelState::AdsCallState::OnStatusReceived(
     void* arg, grpc_error* error) {
   AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
-  ads_calld->xds_client()->combiner_->Run(
-      GRPC_CLOSURE_INIT(&ads_calld->on_status_received_, OnStatusReceivedLocked,
-                        ads_calld, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  ads_calld->xds_client()->work_serializer_->Run(
+      [ads_calld, error]() { ads_calld->OnStatusReceivedLocked(error); },
+      DEBUG_LOCATION);
 }
 
 void XdsClient::ChannelState::AdsCallState::OnStatusReceivedLocked(
-    void* arg, grpc_error* error) {
-  AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
-  ChannelState* chand = ads_calld->chand();
-  XdsClient* xds_client = ads_calld->xds_client();
+    grpc_error* error) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
-    char* status_details = grpc_slice_to_c_string(ads_calld->status_details_);
+    char* status_details = grpc_slice_to_c_string(status_details_);
     gpr_log(GPR_INFO,
             "[xds_client %p] ADS call status received. Status = %d, details "
             "= '%s', (chand: %p, ads_calld: %p, call: %p), error '%s'",
-            xds_client, ads_calld->status_code_, status_details, chand,
-            ads_calld, ads_calld->call_, grpc_error_string(error));
+            xds_client(), status_code_, status_details, chand(), this, call_,
+            grpc_error_string(error));
     gpr_free(status_details);
   }
   // Ignore status from a stale call.
-  if (ads_calld->IsCurrentCallOnChannel()) {
+  if (IsCurrentCallOnChannel()) {
     // Try to restart the call.
-    ads_calld->parent_->OnCallFinishedLocked();
+    parent_->OnCallFinishedLocked();
     // Send error to all watchers.
-    xds_client->NotifyOnError(
+    xds_client()->NotifyOnError(
         GRPC_ERROR_CREATE_FROM_STATIC_STRING("xds call failed"));
   }
-  ads_calld->Unref(DEBUG_LOCATION, "ADS+OnStatusReceivedLocked");
+  Unref(DEBUG_LOCATION, "ADS+OnStatusReceivedLocked");
+  GRPC_ERROR_UNREF(error);
 }
 
 bool XdsClient::ChannelState::AdsCallState::IsCurrentCallOnChannel() const {
@@ -1353,26 +1328,19 @@ bool XdsClient::ChannelState::AdsCallState::IsCurrentCallOnChannel() const {
   return this == chand()->ads_calld_->calld();
 }
 
-std::set<StringView>
-XdsClient::ChannelState::AdsCallState::ClusterNamesForRequest() {
-  std::set<StringView> cluster_names;
-  for (auto& p : state_map_[XdsApi::kCdsTypeUrl].subscribed_resources) {
-    cluster_names.insert(p.first);
-    OrphanablePtr<ResourceState>& state = p.second;
-    state->Start(Ref());
-  }
-  return cluster_names;
-}
-
-std::set<StringView>
-XdsClient::ChannelState::AdsCallState::EdsServiceNamesForRequest() {
-  std::set<StringView> eds_names;
-  for (auto& p : state_map_[XdsApi::kEdsTypeUrl].subscribed_resources) {
-    eds_names.insert(p.first);
-    OrphanablePtr<ResourceState>& state = p.second;
-    state->Start(Ref());
+std::set<absl::string_view>
+XdsClient::ChannelState::AdsCallState::ResourceNamesForRequest(
+    const std::string& type_url) {
+  std::set<absl::string_view> resource_names;
+  auto it = state_map_.find(type_url);
+  if (it != state_map_.end()) {
+    for (auto& p : it->second.subscribed_resources) {
+      resource_names.insert(p.first);
+      OrphanablePtr<ResourceState>& state = p.second;
+      state->Start(Ref());
+    }
   }
-  return eds_names;
+  return resource_names;
 }
 
 //
@@ -1388,8 +1356,6 @@ void XdsClient::ChannelState::LrsCallState::Reporter::Orphan() {
 void XdsClient::ChannelState::LrsCallState::Reporter::
     ScheduleNextReportLocked() {
   const grpc_millis next_report_time = ExecCtx::Get()->Now() + report_interval_;
-  GRPC_CLOSURE_INIT(&on_next_report_timer_, OnNextReportTimer, this,
-                    grpc_schedule_on_exec_ctx);
   grpc_timer_init(&next_report_timer_, next_report_time,
                   &on_next_report_timer_);
   next_report_timer_callback_pending_ = true;
@@ -1398,21 +1364,21 @@ void XdsClient::ChannelState::LrsCallState::Reporter::
 void XdsClient::ChannelState::LrsCallState::Reporter::OnNextReportTimer(
     void* arg, grpc_error* error) {
   Reporter* self = static_cast<Reporter*>(arg);
-  self->xds_client()->combiner_->Run(
-      GRPC_CLOSURE_INIT(&self->on_next_report_timer_, OnNextReportTimerLocked,
-                        self, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  self->xds_client()->work_serializer_->Run(
+      [self, error]() { self->OnNextReportTimerLocked(error); },
+      DEBUG_LOCATION);
 }
 
 void XdsClient::ChannelState::LrsCallState::Reporter::OnNextReportTimerLocked(
-    void* arg, grpc_error* error) {
-  Reporter* self = static_cast<Reporter*>(arg);
-  self->next_report_timer_callback_pending_ = false;
-  if (error != GRPC_ERROR_NONE || !self->IsCurrentReporterOnCall()) {
-    self->Unref(DEBUG_LOCATION, "Reporter+timer");
-    return;
+    grpc_error* error) {
+  next_report_timer_callback_pending_ = false;
+  if (error != GRPC_ERROR_NONE || !IsCurrentReporterOnCall()) {
+    Unref(DEBUG_LOCATION, "Reporter+timer");
+  } else {
+    SendReportLocked();
   }
-  self->SendReportLocked();
+  GRPC_ERROR_UNREF(error);
 }
 
 namespace {
@@ -1435,8 +1401,8 @@ bool LoadReportCountersAreZero(const XdsApi::ClusterLoadReportMap& snapshot) {
 
 void XdsClient::ChannelState::LrsCallState::Reporter::SendReportLocked() {
   // Construct snapshot from all reported stats.
-  XdsApi::ClusterLoadReportMap snapshot =
-      xds_client()->BuildLoadReportSnapshot(parent_->cluster_names_);
+  XdsApi::ClusterLoadReportMap snapshot = xds_client()->BuildLoadReportSnapshot(
+      parent_->send_all_clusters_, parent_->cluster_names_);
   // Skip client load report if the counters were all zero in the last
   // report and they are still zero in this one.
   const bool old_val = last_report_counters_were_zero_;
@@ -1456,8 +1422,6 @@ void XdsClient::ChannelState::LrsCallState::Reporter::SendReportLocked() {
   memset(&op, 0, sizeof(op));
   op.op = GRPC_OP_SEND_MESSAGE;
   op.data.send_message.send_message = parent_->send_message_payload_;
-  GRPC_CLOSURE_INIT(&on_report_done_, OnReportDone, this,
-                    grpc_schedule_on_exec_ctx);
   grpc_call_error call_error = grpc_call_start_batch_and_execute(
       parent_->call_, &op, 1, &on_report_done_);
   if (GPR_UNLIKELY(call_error != GRPC_CALL_OK)) {
@@ -1471,33 +1435,32 @@ void XdsClient::ChannelState::LrsCallState::Reporter::SendReportLocked() {
 void XdsClient::ChannelState::LrsCallState::Reporter::OnReportDone(
     void* arg, grpc_error* error) {
   Reporter* self = static_cast<Reporter*>(arg);
-  self->xds_client()->combiner_->Run(
-      GRPC_CLOSURE_INIT(&self->on_report_done_, OnReportDoneLocked, self,
-                        nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  self->xds_client()->work_serializer_->Run(
+      [self, error]() { self->OnReportDoneLocked(error); }, DEBUG_LOCATION);
 }
 
 void XdsClient::ChannelState::LrsCallState::Reporter::OnReportDoneLocked(
-    void* arg, grpc_error* error) {
-  Reporter* self = static_cast<Reporter*>(arg);
-  grpc_byte_buffer_destroy(self->parent_->send_message_payload_);
-  self->parent_->send_message_payload_ = nullptr;
+    grpc_error* error) {
+  grpc_byte_buffer_destroy(parent_->send_message_payload_);
+  parent_->send_message_payload_ = nullptr;
   // If there are no more registered stats to report, cancel the call.
-  if (self->xds_client()->load_report_map_.empty()) {
-    self->parent_->chand()->StopLrsCall();
-    self->Unref(DEBUG_LOCATION, "Reporter+report_done+no_more_reporters");
+  if (xds_client()->load_report_map_.empty()) {
+    parent_->chand()->StopLrsCall();
+    Unref(DEBUG_LOCATION, "Reporter+report_done+no_more_reporters");
     return;
   }
-  if (error != GRPC_ERROR_NONE || !self->IsCurrentReporterOnCall()) {
+  if (error != GRPC_ERROR_NONE || !IsCurrentReporterOnCall()) {
     // If this reporter is no longer the current one on the call, the reason
     // might be that it was orphaned for a new one due to config update.
-    if (!self->IsCurrentReporterOnCall()) {
-      self->parent_->MaybeStartReportingLocked();
+    if (!IsCurrentReporterOnCall()) {
+      parent_->MaybeStartReportingLocked();
     }
-    self->Unref(DEBUG_LOCATION, "Reporter+report_done");
-    return;
+    Unref(DEBUG_LOCATION, "Reporter+report_done");
+  } else {
+    ScheduleNextReportLocked();
   }
-  self->ScheduleNextReportLocked();
+  GRPC_ERROR_UNREF(error);
 }
 
 //
@@ -1643,75 +1606,70 @@ void XdsClient::ChannelState::LrsCallState::MaybeStartReportingLocked() {
 }
 
 void XdsClient::ChannelState::LrsCallState::OnInitialRequestSent(
-    void* arg, grpc_error* error) {
+    void* arg, grpc_error* /*error*/) {
   LrsCallState* lrs_calld = static_cast<LrsCallState*>(arg);
-  lrs_calld->xds_client()->combiner_->Run(
-      GRPC_CLOSURE_INIT(&lrs_calld->on_initial_request_sent_,
-                        OnInitialRequestSentLocked, lrs_calld, nullptr),
-      GRPC_ERROR_REF(error));
+  lrs_calld->xds_client()->work_serializer_->Run(
+      [lrs_calld]() { lrs_calld->OnInitialRequestSentLocked(); },
+      DEBUG_LOCATION);
 }
 
-void XdsClient::ChannelState::LrsCallState::OnInitialRequestSentLocked(
-    void* arg, grpc_error* /*error*/) {
-  LrsCallState* lrs_calld = static_cast<LrsCallState*>(arg);
+void XdsClient::ChannelState::LrsCallState::OnInitialRequestSentLocked() {
   // Clear the send_message_payload_.
-  grpc_byte_buffer_destroy(lrs_calld->send_message_payload_);
-  lrs_calld->send_message_payload_ = nullptr;
-  lrs_calld->MaybeStartReportingLocked();
-  lrs_calld->Unref(DEBUG_LOCATION, "LRS+OnInitialRequestSentLocked");
+  grpc_byte_buffer_destroy(send_message_payload_);
+  send_message_payload_ = nullptr;
+  MaybeStartReportingLocked();
+  Unref(DEBUG_LOCATION, "LRS+OnInitialRequestSentLocked");
 }
 
 void XdsClient::ChannelState::LrsCallState::OnResponseReceived(
-    void* arg, grpc_error* error) {
+    void* arg, grpc_error* /*error*/) {
   LrsCallState* lrs_calld = static_cast<LrsCallState*>(arg);
-  lrs_calld->xds_client()->combiner_->Run(
-      GRPC_CLOSURE_INIT(&lrs_calld->on_response_received_,
-                        OnResponseReceivedLocked, lrs_calld, nullptr),
-      GRPC_ERROR_REF(error));
+  lrs_calld->xds_client()->work_serializer_->Run(
+      [lrs_calld]() { lrs_calld->OnResponseReceivedLocked(); }, DEBUG_LOCATION);
 }
 
-void XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked(
-    void* arg, grpc_error* /*error*/) {
-  LrsCallState* lrs_calld = static_cast<LrsCallState*>(arg);
-  XdsClient* xds_client = lrs_calld->xds_client();
+void XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked() {
   // Empty payload means the call was cancelled.
-  if (!lrs_calld->IsCurrentCallOnChannel() ||
-      lrs_calld->recv_message_payload_ == nullptr) {
-    lrs_calld->Unref(DEBUG_LOCATION, "LRS+OnResponseReceivedLocked");
+  if (!IsCurrentCallOnChannel() || recv_message_payload_ == nullptr) {
+    Unref(DEBUG_LOCATION, "LRS+OnResponseReceivedLocked");
     return;
   }
   // Read the response.
   grpc_byte_buffer_reader bbr;
-  grpc_byte_buffer_reader_init(&bbr, lrs_calld->recv_message_payload_);
+  grpc_byte_buffer_reader_init(&bbr, recv_message_payload_);
   grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
   grpc_byte_buffer_reader_destroy(&bbr);
-  grpc_byte_buffer_destroy(lrs_calld->recv_message_payload_);
-  lrs_calld->recv_message_payload_ = nullptr;
+  grpc_byte_buffer_destroy(recv_message_payload_);
+  recv_message_payload_ = nullptr;
   // This anonymous lambda is a hack to avoid the usage of goto.
   [&]() {
     // Parse the response.
+    bool send_all_clusters = false;
     std::set<std::string> new_cluster_names;
     grpc_millis new_load_reporting_interval;
-    grpc_error* parse_error = xds_client->api_.ParseLrsResponse(
-        response_slice, &new_cluster_names, &new_load_reporting_interval);
+    grpc_error* parse_error = xds_client()->api_.ParseLrsResponse(
+        response_slice, &send_all_clusters, &new_cluster_names,
+        &new_load_reporting_interval);
     if (parse_error != GRPC_ERROR_NONE) {
       gpr_log(GPR_ERROR,
               "[xds_client %p] LRS response parsing failed. error=%s",
-              xds_client, grpc_error_string(parse_error));
+              xds_client(), grpc_error_string(parse_error));
       GRPC_ERROR_UNREF(parse_error);
       return;
     }
-    lrs_calld->seen_response_ = true;
+    seen_response_ = true;
     if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
-      gpr_log(GPR_INFO,
-              "[xds_client %p] LRS response received, %" PRIuPTR
-              " cluster names, load_report_interval=%" PRId64 "ms",
-              xds_client, new_cluster_names.size(),
-              new_load_reporting_interval);
+      gpr_log(
+          GPR_INFO,
+          "[xds_client %p] LRS response received, %" PRIuPTR
+          " cluster names, send_all_clusters=%d, load_report_interval=%" PRId64
+          "ms",
+          xds_client(), new_cluster_names.size(), send_all_clusters,
+          new_load_reporting_interval);
       size_t i = 0;
       for (const auto& name : new_cluster_names) {
         gpr_log(GPR_INFO, "[xds_client %p] cluster_name %" PRIuPTR ": %s",
-                xds_client, i++, name.c_str());
+                xds_client(), i++, name.c_str());
       }
     }
     if (new_load_reporting_interval <
@@ -1722,81 +1680,78 @@ void XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked(
         gpr_log(GPR_INFO,
                 "[xds_client %p] Increased load_report_interval to minimum "
                 "value %dms",
-                xds_client, GRPC_XDS_MIN_CLIENT_LOAD_REPORTING_INTERVAL_MS);
+                xds_client(), GRPC_XDS_MIN_CLIENT_LOAD_REPORTING_INTERVAL_MS);
       }
     }
     // Ignore identical update.
-    if (lrs_calld->cluster_names_ == new_cluster_names &&
-        lrs_calld->load_reporting_interval_ == new_load_reporting_interval) {
+    if (send_all_clusters == send_all_clusters_ &&
+        cluster_names_ == new_cluster_names &&
+        load_reporting_interval_ == new_load_reporting_interval) {
       if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
         gpr_log(GPR_INFO,
                 "[xds_client %p] Incoming LRS response identical to current, "
                 "ignoring.",
-                xds_client);
+                xds_client());
       }
       return;
     }
     // Stop current load reporting (if any) to adopt the new config.
-    lrs_calld->reporter_.reset();
+    reporter_.reset();
     // Record the new config.
-    lrs_calld->cluster_names_ = std::move(new_cluster_names);
-    lrs_calld->load_reporting_interval_ = new_load_reporting_interval;
+    send_all_clusters_ = send_all_clusters;
+    cluster_names_ = std::move(new_cluster_names);
+    load_reporting_interval_ = new_load_reporting_interval;
     // Try starting sending load report.
-    lrs_calld->MaybeStartReportingLocked();
+    MaybeStartReportingLocked();
   }();
   grpc_slice_unref_internal(response_slice);
-  if (xds_client->shutting_down_) {
-    lrs_calld->Unref(DEBUG_LOCATION,
-                     "LRS+OnResponseReceivedLocked+xds_shutdown");
+  if (xds_client()->shutting_down_) {
+    Unref(DEBUG_LOCATION, "LRS+OnResponseReceivedLocked+xds_shutdown");
     return;
   }
   // Keep listening for LRS config updates.
   grpc_op op;
   memset(&op, 0, sizeof(op));
   op.op = GRPC_OP_RECV_MESSAGE;
-  op.data.recv_message.recv_message = &lrs_calld->recv_message_payload_;
+  op.data.recv_message.recv_message = &recv_message_payload_;
   op.flags = 0;
   op.reserved = nullptr;
-  GPR_ASSERT(lrs_calld->call_ != nullptr);
+  GPR_ASSERT(call_ != nullptr);
   // Reuse the "OnResponseReceivedLocked" ref taken in ctor.
-  GRPC_CLOSURE_INIT(&lrs_calld->on_response_received_, OnResponseReceived,
-                    lrs_calld, grpc_schedule_on_exec_ctx);
-  const grpc_call_error call_error = grpc_call_start_batch_and_execute(
-      lrs_calld->call_, &op, 1, &lrs_calld->on_response_received_);
+  const grpc_call_error call_error =
+      grpc_call_start_batch_and_execute(call_, &op, 1, &on_response_received_);
   GPR_ASSERT(GRPC_CALL_OK == call_error);
 }
 
 void XdsClient::ChannelState::LrsCallState::OnStatusReceived(
     void* arg, grpc_error* error) {
   LrsCallState* lrs_calld = static_cast<LrsCallState*>(arg);
-  lrs_calld->xds_client()->combiner_->Run(
-      GRPC_CLOSURE_INIT(&lrs_calld->on_status_received_, OnStatusReceivedLocked,
-                        lrs_calld, nullptr),
-      GRPC_ERROR_REF(error));
+  GRPC_ERROR_REF(error);  // ref owned by lambda
+  lrs_calld->xds_client()->work_serializer_->Run(
+      [lrs_calld, error]() { lrs_calld->OnStatusReceivedLocked(error); },
+      DEBUG_LOCATION);
 }
 
 void XdsClient::ChannelState::LrsCallState::OnStatusReceivedLocked(
-    void* arg, grpc_error* error) {
-  LrsCallState* lrs_calld = static_cast<LrsCallState*>(arg);
-  XdsClient* xds_client = lrs_calld->xds_client();
-  ChannelState* chand = lrs_calld->chand();
-  GPR_ASSERT(lrs_calld->call_ != nullptr);
+    grpc_error* error) {
+  GPR_ASSERT(call_ != nullptr);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
-    char* status_details = grpc_slice_to_c_string(lrs_calld->status_details_);
+    char* status_details = grpc_slice_to_c_string(status_details_);
     gpr_log(GPR_INFO,
             "[xds_client %p] LRS call status received. Status = %d, details "
             "= '%s', (chand: %p, calld: %p, call: %p), error '%s'",
-            xds_client, lrs_calld->status_code_, status_details, chand,
-            lrs_calld, lrs_calld->call_, grpc_error_string(error));
+            xds_client(), status_code_, status_details, chand(), this, call_,
+            grpc_error_string(error));
     gpr_free(status_details);
   }
   // Ignore status from a stale call.
-  if (lrs_calld->IsCurrentCallOnChannel()) {
-    GPR_ASSERT(!xds_client->shutting_down_);
+  if (IsCurrentCallOnChannel()) {
+    GPR_ASSERT(!xds_client()->shutting_down_);
     // Try to restart the call.
-    lrs_calld->parent_->OnCallFinishedLocked();
+    parent_->OnCallFinishedLocked();
   }
-  lrs_calld->Unref(DEBUG_LOCATION, "LRS+OnStatusReceivedLocked");
+  Unref(DEBUG_LOCATION, "LRS+OnStatusReceivedLocked");
+  GRPC_ERROR_UNREF(error);
 }
 
 bool XdsClient::ChannelState::LrsCallState::IsCurrentCallOnChannel() const {
@@ -1818,21 +1773,16 @@ grpc_millis GetRequestTimeout(const grpc_channel_args& args) {
       {15000, 0, INT_MAX});
 }
 
-bool GetXdsRoutingEnabled(const grpc_channel_args& args) {
-  return grpc_channel_args_find_bool(&args, GRPC_ARG_XDS_ROUTING_ENABLED,
-                                     false);
-}
-
 }  // namespace
 
-XdsClient::XdsClient(Combiner* combiner, grpc_pollset_set* interested_parties,
-                     StringView server_name,
+XdsClient::XdsClient(std::shared_ptr<WorkSerializer> work_serializer,
+                     grpc_pollset_set* interested_parties,
+                     absl::string_view server_name,
                      std::unique_ptr<ServiceConfigWatcherInterface> watcher,
                      const grpc_channel_args& channel_args, grpc_error** error)
     : InternallyRefCounted<XdsClient>(&grpc_xds_client_trace),
       request_timeout_(GetRequestTimeout(channel_args)),
-      xds_routing_enabled_(GetXdsRoutingEnabled(channel_args)),
-      combiner_(GRPC_COMBINER_REF(combiner, "xds_client")),
+      work_serializer_(std::move(work_serializer)),
       interested_parties_(interested_parties),
       bootstrap_(
           XdsBootstrap::ReadFromFile(this, &grpc_xds_client_trace, error)),
@@ -1871,7 +1821,6 @@ XdsClient::~XdsClient() {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
     gpr_log(GPR_INFO, "[xds_client %p] destroying xds client", this);
   }
-  GRPC_COMBINER_UNREF(combiner_, "xds_client");
 }
 
 void XdsClient::Orphan() {
@@ -1894,7 +1843,8 @@ void XdsClient::Orphan() {
 }
 
 void XdsClient::WatchClusterData(
-    StringView cluster_name, std::unique_ptr<ClusterWatcherInterface> watcher) {
+    absl::string_view cluster_name,
+    std::unique_ptr<ClusterWatcherInterface> watcher) {
   std::string cluster_name_str = std::string(cluster_name);
   ClusterState& cluster_state = cluster_map_[cluster_name_str];
   ClusterWatcherInterface* w = watcher.get();
@@ -1904,14 +1854,14 @@ void XdsClient::WatchClusterData(
   if (cluster_state.update.has_value()) {
     if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
       gpr_log(GPR_INFO, "[xds_client %p] returning cached cluster data for %s",
-              this, StringViewToCString(cluster_name).get());
+              this, cluster_name_str.c_str());
     }
     w->OnClusterChanged(cluster_state.update.value());
   }
   chand_->Subscribe(XdsApi::kCdsTypeUrl, cluster_name_str);
 }
 
-void XdsClient::CancelClusterDataWatch(StringView cluster_name,
+void XdsClient::CancelClusterDataWatch(absl::string_view cluster_name,
                                        ClusterWatcherInterface* watcher,
                                        bool delay_unsubscription) {
   if (shutting_down_) return;
@@ -1929,7 +1879,7 @@ void XdsClient::CancelClusterDataWatch(StringView cluster_name,
 }
 
 void XdsClient::WatchEndpointData(
-    StringView eds_service_name,
+    absl::string_view eds_service_name,
     std::unique_ptr<EndpointWatcherInterface> watcher) {
   std::string eds_service_name_str = std::string(eds_service_name);
   EndpointState& endpoint_state = endpoint_map_[eds_service_name_str];
@@ -1940,14 +1890,14 @@ void XdsClient::WatchEndpointData(
   if (endpoint_state.update.has_value()) {
     if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
       gpr_log(GPR_INFO, "[xds_client %p] returning cached endpoint data for %s",
-              this, StringViewToCString(eds_service_name).get());
+              this, eds_service_name_str.c_str());
     }
     w->OnEndpointChanged(endpoint_state.update.value());
   }
   chand_->Subscribe(XdsApi::kEdsTypeUrl, eds_service_name_str);
 }
 
-void XdsClient::CancelEndpointDataWatch(StringView eds_service_name,
+void XdsClient::CancelEndpointDataWatch(absl::string_view eds_service_name,
                                         EndpointWatcherInterface* watcher,
                                         bool delay_unsubscription) {
   if (shutting_down_) return;
@@ -1965,13 +1915,13 @@ void XdsClient::CancelEndpointDataWatch(StringView eds_service_name,
 }
 
 RefCountedPtr<XdsClusterDropStats> XdsClient::AddClusterDropStats(
-    StringView lrs_server, StringView cluster_name,
-    StringView eds_service_name) {
+    absl::string_view lrs_server, absl::string_view cluster_name,
+    absl::string_view eds_service_name) {
   // TODO(roth): When we add support for direct federation, use the
   // server name specified in lrs_server.
   auto key =
       std::make_pair(std::string(cluster_name), std::string(eds_service_name));
-  // We jump through some hoops here to make sure that the StringViews
+  // We jump through some hoops here to make sure that the absl::string_views
   // stored in the XdsClusterDropStats object point to the strings
   // in the load_report_map_ key, so that they have the same lifetime.
   auto it = load_report_map_
@@ -1986,8 +1936,9 @@ RefCountedPtr<XdsClusterDropStats> XdsClient::AddClusterDropStats(
 }
 
 void XdsClient::RemoveClusterDropStats(
-    StringView /*lrs_server*/, StringView cluster_name,
-    StringView eds_service_name, XdsClusterDropStats* cluster_drop_stats) {
+    absl::string_view /*lrs_server*/, absl::string_view cluster_name,
+    absl::string_view eds_service_name,
+    XdsClusterDropStats* cluster_drop_stats) {
   auto load_report_it = load_report_map_.find(
       std::make_pair(std::string(cluster_name), std::string(eds_service_name)));
   if (load_report_it == load_report_map_.end()) return;
@@ -2006,13 +1957,14 @@ void XdsClient::RemoveClusterDropStats(
 }
 
 RefCountedPtr<XdsClusterLocalityStats> XdsClient::AddClusterLocalityStats(
-    StringView lrs_server, StringView cluster_name, StringView eds_service_name,
+    absl::string_view lrs_server, absl::string_view cluster_name,
+    absl::string_view eds_service_name,
     RefCountedPtr<XdsLocalityName> locality) {
   // TODO(roth): When we add support for direct federation, use the
   // server name specified in lrs_server.
   auto key =
       std::make_pair(std::string(cluster_name), std::string(eds_service_name));
-  // We jump through some hoops here to make sure that the StringViews
+  // We jump through some hoops here to make sure that the absl::string_views
   // stored in the XdsClusterLocalityStats object point to the strings
   // in the load_report_map_ key, so that they have the same lifetime.
   auto it = load_report_map_
@@ -2029,8 +1981,9 @@ RefCountedPtr<XdsClusterLocalityStats> XdsClient::AddClusterLocalityStats(
 }
 
 void XdsClient::RemoveClusterLocalityStats(
-    StringView /*lrs_server*/, StringView cluster_name,
-    StringView eds_service_name, const RefCountedPtr<XdsLocalityName>& locality,
+    absl::string_view /*lrs_server*/, absl::string_view cluster_name,
+    absl::string_view eds_service_name,
+    const RefCountedPtr<XdsLocalityName>& locality,
     XdsClusterLocalityStats* cluster_locality_stats) {
   auto load_report_it = load_report_map_.find(
       std::make_pair(std::string(cluster_name), std::string(eds_service_name)));
@@ -2061,16 +2014,16 @@ namespace {
 std::string CreateServiceConfigActionCluster(const std::string& cluster_name) {
   return absl::StrFormat(
       "      \"cds:%s\":{\n"
-      "        \"child_policy\":[ {\n"
+      "        \"childPolicy\":[ {\n"
       "          \"cds_experimental\":{\n"
       "            \"cluster\": \"%s\"\n"
       "          }\n"
       "        } ]\n"
       "       }",
-      cluster_name.c_str(), cluster_name.c_str());
+      cluster_name, cluster_name);
 }
 
-std::string CreateServiceConfigRoute(const std::string& cluster_name,
+std::string CreateServiceConfigRoute(const std::string& action_name,
                                      const std::string& service,
                                      const std::string& method) {
   return absl::StrFormat(
@@ -2079,39 +2032,203 @@ std::string CreateServiceConfigRoute(const std::string& cluster_name,
       "           \"service\": \"%s\",\n"
       "           \"method\": \"%s\"\n"
       "        },\n"
-      "        \"action\": \"cds:%s\"\n"
+      "        \"action\": \"%s\"\n"
       "      }",
-      service.c_str(), method.c_str(), cluster_name.c_str());
+      service, method, action_name);
+}
+
+// Create the service config for one weighted cluster.
+std::string CreateServiceConfigActionWeightedCluster(
+    const std::string& name,
+    const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>& clusters) {
+  std::vector<std::string> config_parts;
+  config_parts.push_back(
+      absl::StrFormat("      \"weighted:%s\":{\n"
+                      "        \"childPolicy\":[ {\n"
+                      "          \"weighted_target_experimental\":{\n"
+                      "            \"targets\":{\n",
+                      name));
+  std::vector<std::string> weighted_targets;
+  weighted_targets.reserve(clusters.size());
+  for (const auto& cluster_weight : clusters) {
+    weighted_targets.push_back(absl::StrFormat(
+        "              \"%s\":{\n"
+        "                \"weight\":%d,\n"
+        "                \"childPolicy\":[ {\n"
+        "                  \"cds_experimental\":{\n"
+        "                    \"cluster\": \"%s\"\n"
+        "                  }\n"
+        "                } ]\n"
+        "               }",
+        cluster_weight.name, cluster_weight.weight, cluster_weight.name));
+  }
+  config_parts.push_back(absl::StrJoin(weighted_targets, ",\n"));
+  config_parts.push_back(
+      "            }\n"
+      "          }\n"
+      "        } ]\n"
+      "       }");
+  return absl::StrJoin(config_parts, "");
 }
+
+struct WeightedClustersKeys {
+  std::string cluster_names_key;
+  std::string cluster_weights_key;
+};
+
+// Returns the cluster names and weights key or the cluster names only key.
+WeightedClustersKeys GetWeightedClustersKey(
+    const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>&
+        weighted_clusters) {
+  std::set<std::string> cluster_names;
+  std::set<std::string> cluster_weights;
+  for (const auto& cluster_weight : weighted_clusters) {
+    cluster_names.emplace(absl::StrFormat("%s", cluster_weight.name));
+    cluster_weights.emplace(
+        absl::StrFormat("%s_%d", cluster_weight.name, cluster_weight.weight));
+  }
+  return {absl::StrJoin(cluster_names, "_"),
+          absl::StrJoin(cluster_weights, "_")};
+}
+
 }  // namespace
 
+std::string XdsClient::WeightedClustersActionName(
+    const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>&
+        weighted_clusters) {
+  WeightedClustersKeys keys = GetWeightedClustersKey(weighted_clusters);
+  auto cluster_names_map_it =
+      weighted_cluster_index_map_.find(keys.cluster_names_key);
+  GPR_ASSERT(cluster_names_map_it != weighted_cluster_index_map_.end());
+  const auto& cluster_weights_map =
+      cluster_names_map_it->second.cluster_weights_map;
+  auto cluster_weights_map_it =
+      cluster_weights_map.find(keys.cluster_weights_key);
+  GPR_ASSERT(cluster_weights_map_it != cluster_weights_map.end());
+  return absl::StrFormat("%s_%d", keys.cluster_names_key,
+                         cluster_weights_map_it->second);
+}
+
+void XdsClient::UpdateWeightedClusterIndexMap(
+    const XdsApi::RdsUpdate& rds_update) {
+  // Construct a list of unique WeightedCluster
+  // actions which we need to process: to find action names
+  std::map<std::string /* cluster_weights_key */,
+           std::string /* cluster_names_key */>
+      actions_to_process;
+  for (const auto& route : rds_update.routes) {
+    if (!route.weighted_clusters.empty()) {
+      WeightedClustersKeys keys =
+          GetWeightedClustersKey(route.weighted_clusters);
+      auto action_it = actions_to_process.find(keys.cluster_weights_key);
+      if (action_it == actions_to_process.end()) {
+        actions_to_process[std::move(keys.cluster_weights_key)] =
+            std::move(keys.cluster_names_key);
+      }
+    }
+  }
+  // First pass of all unique WeightedCluster actions: if the exact same
+  // weighted target policy (same clusters and weights) appears in the old map,
+  // then that old action name is taken again and should be moved to the new
+  // map; any other action names from the old set of actions are candidates for
+  // reuse.
+  XdsClient::WeightedClusterIndexMap new_weighted_cluster_index_map;
+  for (auto action_it = actions_to_process.begin();
+       action_it != actions_to_process.end();) {
+    const std::string& cluster_names_key = action_it->second;
+    const std::string& cluster_weights_key = action_it->first;
+    auto old_cluster_names_map_it =
+        weighted_cluster_index_map_.find(cluster_names_key);
+    if (old_cluster_names_map_it != weighted_cluster_index_map_.end()) {
+      // Add cluster_names_key to the new map and copy next_index.
+      auto& new_cluster_names_info =
+          new_weighted_cluster_index_map[cluster_names_key];
+      new_cluster_names_info.next_index =
+          old_cluster_names_map_it->second.next_index;
+      // Lookup cluster_weights_key in old map.
+      auto& old_cluster_weights_map =
+          old_cluster_names_map_it->second.cluster_weights_map;
+      auto old_cluster_weights_map_it =
+          old_cluster_weights_map.find(cluster_weights_key);
+      if (old_cluster_weights_map_it != old_cluster_weights_map.end()) {
+        // same policy found, move from old map to new map.
+        new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
+            old_cluster_weights_map_it->second;
+        old_cluster_weights_map.erase(old_cluster_weights_map_it);
+        // This action has been added to new map, so no need to process it
+        // again.
+        action_it = actions_to_process.erase(action_it);
+        continue;
+      }
+    }
+    ++action_it;
+  }
+  // Second pass of all remaining unique WeightedCluster actions: if clusters
+  // for a new action are the same as an old unused action, reuse the name.  If
+  // clusters differ, use a brand new name.
+  for (const auto& action : actions_to_process) {
+    const std::string& cluster_names_key = action.second;
+    const std::string& cluster_weights_key = action.first;
+    auto& new_cluster_names_info =
+        new_weighted_cluster_index_map[cluster_names_key];
+    auto& old_cluster_weights_map =
+        weighted_cluster_index_map_[cluster_names_key].cluster_weights_map;
+    auto old_cluster_weights_it = old_cluster_weights_map.begin();
+    if (old_cluster_weights_it != old_cluster_weights_map.end()) {
+      // There is something to reuse: this action uses the same set
+      // of clusters as a previous action and that action name is not
+      // already taken.
+      new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
+          old_cluster_weights_it->second;
+      // Remove the name from being able to reuse again.
+      old_cluster_weights_map.erase(old_cluster_weights_it);
+    } else {
+      // There is nothing to reuse, take the next index to use and
+      // increment.
+      new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
+          new_cluster_names_info.next_index++;
+    }
+  }
+  weighted_cluster_index_map_ = std::move(new_weighted_cluster_index_map);
+}
+
 grpc_error* XdsClient::CreateServiceConfig(
     const XdsApi::RdsUpdate& rds_update,
-    RefCountedPtr<ServiceConfig>* service_config) const {
+    RefCountedPtr<ServiceConfig>* service_config) {
+  UpdateWeightedClusterIndexMap(rds_update);
+  std::vector<std::string> actions_vector;
+  std::vector<std::string> route_table;
+  std::set<std::string> actions_set;
+  for (const auto& route : rds_update.routes) {
+    const std::string action_name =
+        route.weighted_clusters.empty()
+            ? route.cluster_name
+            : WeightedClustersActionName(route.weighted_clusters);
+    if (actions_set.find(action_name) == actions_set.end()) {
+      actions_set.emplace(action_name);
+      actions_vector.push_back(
+          route.weighted_clusters.empty()
+              ? CreateServiceConfigActionCluster(action_name)
+              : CreateServiceConfigActionWeightedCluster(
+                    action_name, route.weighted_clusters));
+    }
+    route_table.push_back(CreateServiceConfigRoute(
+        absl::StrFormat("%s:%s",
+                        route.weighted_clusters.empty() ? "cds" : "weighted",
+                        action_name),
+        route.service, route.method));
+  }
   std::vector<std::string> config_parts;
   config_parts.push_back(
       "{\n"
       "  \"loadBalancingConfig\":[\n"
       "    { \"xds_routing_experimental\":{\n"
       "      \"actions\":{\n");
-  std::vector<std::string> actions_vector;
-  for (size_t i = 0; i < rds_update.routes.size(); ++i) {
-    auto route = rds_update.routes[i];
-    actions_vector.push_back(
-        CreateServiceConfigActionCluster(route.cluster_name.c_str()));
-  }
   config_parts.push_back(absl::StrJoin(actions_vector, ",\n"));
   config_parts.push_back(
       "    },\n"
       "      \"routes\":[\n");
-  std::vector<std::string> routes_vector;
-  for (size_t i = 0; i < rds_update.routes.size(); ++i) {
-    auto route_info = rds_update.routes[i];
-    routes_vector.push_back(CreateServiceConfigRoute(
-        route_info.cluster_name.c_str(), route_info.service.c_str(),
-        route_info.method.c_str()));
-  }
-  config_parts.push_back(absl::StrJoin(routes_vector, ",\n"));
+  config_parts.push_back(absl::StrJoin(route_table, ",\n"));
   config_parts.push_back(
       "    ]\n"
       "    } }\n"
@@ -2124,7 +2241,7 @@ grpc_error* XdsClient::CreateServiceConfig(
 }
 
 XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshot(
-    const std::set<std::string>& clusters) {
+    bool send_all_clusters, const std::set<std::string>& clusters) {
   XdsApi::ClusterLoadReportMap snapshot_map;
   for (auto load_report_it = load_report_map_.begin();
        load_report_it != load_report_map_.end();) {
@@ -2139,7 +2256,7 @@ XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshot(
     // asking for the data in the future, we don't incorrectly include
     // data from previous reporting intervals in that future report.
     const bool record_stats =
-        clusters.find(cluster_key.first) != clusters.end();
+        send_all_clusters || clusters.find(cluster_key.first) != clusters.end();
     XdsApi::ClusterLoadReport snapshot;
     // Aggregate drop stats.
     snapshot.dropped_requests = std::move(load_report.deleted_drop_stats);
@@ -2241,4 +2358,10 @@ RefCountedPtr<XdsClient> XdsClient::GetFromChannelArgs(
   return nullptr;
 }
 
+grpc_channel_args* XdsClient::RemoveFromChannelArgs(
+    const grpc_channel_args& args) {
+  const char* arg_name = GRPC_ARG_XDS_CLIENT;
+  return grpc_channel_args_copy_and_remove(&args, &arg_name, 1);
+}
+
 }  // namespace grpc_core
index c79c169..34e921f 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <set>
 
+#include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
 
 #include "src/core/ext/filters/client_channel/service_config.h"
@@ -32,8 +33,7 @@
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/gprpp/string_view.h"
-#include "src/core/lib/iomgr/combiner.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 
 namespace grpc_core {
 
@@ -50,6 +50,8 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
         RefCountedPtr<ServiceConfig> service_config) = 0;
 
     virtual void OnError(grpc_error* error) = 0;
+
+    virtual void OnResourceDoesNotExist() = 0;
   };
 
   // Cluster data watcher interface.  Implemented by callers.
@@ -60,6 +62,8 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
     virtual void OnClusterChanged(XdsApi::CdsUpdate cluster_data) = 0;
 
     virtual void OnError(grpc_error* error) = 0;
+
+    virtual void OnResourceDoesNotExist() = 0;
   };
 
   // Endpoint data watcher interface.  Implemented by callers.
@@ -70,12 +74,14 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
     virtual void OnEndpointChanged(XdsApi::EdsUpdate update) = 0;
 
     virtual void OnError(grpc_error* error) = 0;
+
+    virtual void OnResourceDoesNotExist() = 0;
   };
 
   // If *error is not GRPC_ERROR_NONE after construction, then there was
   // an error initializing the client.
-  XdsClient(Combiner* combiner, grpc_pollset_set* interested_parties,
-            StringView server_name,
+  XdsClient(std::shared_ptr<WorkSerializer> work_serializer,
+            grpc_pollset_set* interested_parties, absl::string_view server_name,
             std::unique_ptr<ServiceConfigWatcherInterface> watcher,
             const grpc_channel_args& channel_args, grpc_error** error);
   ~XdsClient();
@@ -89,9 +95,9 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
   // pointer must not be used for any other purpose.)
   // If the caller is going to start a new watch after cancelling the
   // old one, it should set delay_unsubscription to true.
-  void WatchClusterData(StringView cluster_name,
+  void WatchClusterData(absl::string_view cluster_name,
                         std::unique_ptr<ClusterWatcherInterface> watcher);
-  void CancelClusterDataWatch(StringView cluster_name,
+  void CancelClusterDataWatch(absl::string_view cluster_name,
                               ClusterWatcherInterface* watcher,
                               bool delay_unsubscription = false);
 
@@ -102,29 +108,30 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
   // pointer must not be used for any other purpose.)
   // If the caller is going to start a new watch after cancelling the
   // old one, it should set delay_unsubscription to true.
-  void WatchEndpointData(StringView eds_service_name,
+  void WatchEndpointData(absl::string_view eds_service_name,
                          std::unique_ptr<EndpointWatcherInterface> watcher);
-  void CancelEndpointDataWatch(StringView eds_service_name,
+  void CancelEndpointDataWatch(absl::string_view eds_service_name,
                                EndpointWatcherInterface* watcher,
                                bool delay_unsubscription = false);
 
   // Adds and removes drop stats for cluster_name and eds_service_name.
   RefCountedPtr<XdsClusterDropStats> AddClusterDropStats(
-      StringView lrs_server, StringView cluster_name,
-      StringView eds_service_name);
-  void RemoveClusterDropStats(StringView /*lrs_server*/,
-                              StringView cluster_name,
-                              StringView eds_service_name,
+      absl::string_view lrs_server, absl::string_view cluster_name,
+      absl::string_view eds_service_name);
+  void RemoveClusterDropStats(absl::string_view /*lrs_server*/,
+                              absl::string_view cluster_name,
+                              absl::string_view eds_service_name,
                               XdsClusterDropStats* cluster_drop_stats);
 
   // Adds and removes locality stats for cluster_name and eds_service_name
   // for the specified locality.
   RefCountedPtr<XdsClusterLocalityStats> AddClusterLocalityStats(
-      StringView lrs_server, StringView cluster_name,
-      StringView eds_service_name, RefCountedPtr<XdsLocalityName> locality);
+      absl::string_view lrs_server, absl::string_view cluster_name,
+      absl::string_view eds_service_name,
+      RefCountedPtr<XdsLocalityName> locality);
   void RemoveClusterLocalityStats(
-      StringView /*lrs_server*/, StringView cluster_name,
-      StringView eds_service_name,
+      absl::string_view /*lrs_server*/, absl::string_view cluster_name,
+      absl::string_view eds_service_name,
       const RefCountedPtr<XdsLocalityName>& locality,
       XdsClusterLocalityStats* cluster_locality_stats);
 
@@ -135,6 +142,8 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
   grpc_arg MakeChannelArg() const;
   static RefCountedPtr<XdsClient> GetFromChannelArgs(
       const grpc_channel_args& args);
+  static grpc_channel_args* RemoveFromChannelArgs(
+      const grpc_channel_args& args);
 
  private:
   // Contains a channel to the xds server and all the data related to the
@@ -225,12 +234,22 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
   // Sends an error notification to all watchers.
   void NotifyOnError(grpc_error* error);
 
-  grpc_error* CreateServiceConfig(
-      const XdsApi::RdsUpdate& rds_update,
-      RefCountedPtr<ServiceConfig>* service_config) const;
+  // Returns the weighted_clusters action name to use from
+  // weighted_cluster_index_map_ for a WeightedClusters route action.
+  std::string WeightedClustersActionName(
+      const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>&
+          weighted_clusters);
+
+  // Updates weighted_cluster_index_map_ that will
+  // determine the names of the WeightedCluster actions for the current update.
+  void UpdateWeightedClusterIndexMap(const XdsApi::RdsUpdate& rds_update);
+
+  // Create the service config generated by the RdsUpdate.
+  grpc_error* CreateServiceConfig(const XdsApi::RdsUpdate& rds_update,
+                                  RefCountedPtr<ServiceConfig>* service_config);
 
   XdsApi::ClusterLoadReportMap BuildLoadReportSnapshot(
-      const std::set<std::string>& clusters);
+      bool send_all_clusters, const std::set<std::string>& clusters);
 
   // Channel arg vtable functions.
   static void* ChannelArgCopy(void* p);
@@ -241,9 +260,7 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
 
   const grpc_millis request_timeout_;
 
-  const bool xds_routing_enabled_;
-
-  Combiner* combiner_;
+  std::shared_ptr<WorkSerializer> work_serializer_;
   grpc_pollset_set* interested_parties_;
 
   std::unique_ptr<XdsBootstrap> bootstrap_;
@@ -268,6 +285,22 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
       LoadReportState>
       load_report_map_;
 
+  // 2-level map to store WeightedCluster action names.
+  // Top level map is keyed by cluster names without weight like a_b_c; bottom
+  // level map is keyed by cluster names + weights like a10_b50_c40.
+  struct ClusterNamesInfo {
+    uint64_t next_index = 0;
+    std::map<std::string /*cluster names + weights*/,
+             uint64_t /*policy index number*/>
+        cluster_weights_map;
+  };
+  using WeightedClusterIndexMap =
+      std::map<std::string /*cluster names*/, ClusterNamesInfo>;
+
+  // Cache of action names for WeightedCluster targets in the current
+  // service config.
+  WeightedClusterIndexMap weighted_cluster_index_map_;
+
   bool shutting_down_ = false;
 };
 
index cf11560..1cfac0a 100644 (file)
@@ -34,9 +34,9 @@ namespace grpc_core {
 //
 
 XdsClusterDropStats::XdsClusterDropStats(RefCountedPtr<XdsClient> xds_client,
-                                         StringView lrs_server_name,
-                                         StringView cluster_name,
-                                         StringView eds_service_name)
+                                         absl::string_view lrs_server_name,
+                                         absl::string_view cluster_name,
+                                         absl::string_view eds_service_name)
     : xds_client_(std::move(xds_client)),
       lrs_server_name_(lrs_server_name),
       cluster_name_(cluster_name),
@@ -64,8 +64,8 @@ void XdsClusterDropStats::AddCallDropped(const std::string& category) {
 //
 
 XdsClusterLocalityStats::XdsClusterLocalityStats(
-    RefCountedPtr<XdsClient> xds_client, StringView lrs_server_name,
-    StringView cluster_name, StringView eds_service_name,
+    RefCountedPtr<XdsClient> xds_client, absl::string_view lrs_server_name,
+    absl::string_view cluster_name, absl::string_view eds_service_name,
     RefCountedPtr<XdsLocalityName> name)
     : xds_client_(std::move(xds_client)),
       lrs_server_name_(lrs_server_name),
index e0dd29d..2dab43c 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
+#include <map>
+
+#include "absl/strings/string_view.h"
+
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/gprpp/atomic.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
-#include "src/core/lib/gprpp/map.h"
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/sync.h"
@@ -100,8 +102,9 @@ class XdsClusterDropStats : public RefCounted<XdsClusterDropStats> {
   using DroppedRequestsMap = std::map<std::string /* category */, uint64_t>;
 
   XdsClusterDropStats(RefCountedPtr<XdsClient> xds_client,
-                      StringView lrs_server_name, StringView cluster_name,
-                      StringView eds_service_name);
+                      absl::string_view lrs_server_name,
+                      absl::string_view cluster_name,
+                      absl::string_view eds_service_name);
   ~XdsClusterDropStats();
 
   // Returns a snapshot of this instance and resets all the counters.
@@ -111,9 +114,9 @@ class XdsClusterDropStats : public RefCounted<XdsClusterDropStats> {
 
  private:
   RefCountedPtr<XdsClient> xds_client_;
-  StringView lrs_server_name_;
-  StringView cluster_name_;
-  StringView eds_service_name_;
+  absl::string_view lrs_server_name_;
+  absl::string_view cluster_name_;
+  absl::string_view eds_service_name_;
   // Protects dropped_requests_. A mutex is necessary because the length of
   // dropped_requests_ can be accessed by both the picker (from data plane
   // mutex) and the load reporting thread (from the control plane combiner).
@@ -171,8 +174,9 @@ class XdsClusterLocalityStats : public RefCounted<XdsClusterLocalityStats> {
   };
 
   XdsClusterLocalityStats(RefCountedPtr<XdsClient> xds_client,
-                          StringView lrs_server_name, StringView cluster_name,
-                          StringView eds_service_name,
+                          absl::string_view lrs_server_name,
+                          absl::string_view cluster_name,
+                          absl::string_view eds_service_name,
                           RefCountedPtr<XdsLocalityName> name);
   ~XdsClusterLocalityStats();
 
@@ -184,9 +188,9 @@ class XdsClusterLocalityStats : public RefCounted<XdsClusterLocalityStats> {
 
  private:
   RefCountedPtr<XdsClient> xds_client_;
-  StringView lrs_server_name_;
-  StringView cluster_name_;
-  StringView eds_service_name_;
+  absl::string_view lrs_server_name_;
+  absl::string_view cluster_name_;
+  absl::string_view eds_service_name_;
   RefCountedPtr<XdsLocalityName> name_;
 
   Atomic<uint64_t> total_successful_requests_{0};
@@ -196,8 +200,8 @@ class XdsClusterLocalityStats : public RefCounted<XdsClusterLocalityStats> {
 
   // Protects backend_metrics_. A mutex is necessary because the length of
   // backend_metrics_ can be accessed by both the callback intercepting the
-  // call's recv_trailing_metadata (not from the control plane combiner) and
-  // the load reporting thread (from the control plane combiner).
+  // call's recv_trailing_metadata (not from the control plane work serializer)
+  // and the load reporting thread (from the control plane work serializer).
   Mutex backend_metrics_mu_;
   std::map<std::string, BackendMetric> backend_metrics_;
 };
index d690d6f..ef773b3 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
+#include <stdint.h>
+#include <string.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
-#include <stdint.h>
-#include <string.h>
+
 #include "src/core/ext/filters/http/client/http_client_filter.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/manual_constructor.h"
@@ -31,6 +39,7 @@
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/transport/static_metadata.h"
+#include "src/core/lib/transport/status_conversion.h"
 #include "src/core/lib/transport/transport_impl.h"
 
 #define EXPECTED_CONTENT_TYPE "application/grpc"
@@ -120,7 +129,8 @@ static grpc_error* client_filter_incoming_metadata(grpc_metadata_batch* b) {
                   GRPC_ERROR_CREATE_FROM_STATIC_STRING(
                       "Received http2 :status header with non-200 OK status"),
                   GRPC_ERROR_STR_VALUE, grpc_slice_from_copied_string(val)),
-              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED),
+              GRPC_ERROR_INT_GRPC_STATUS,
+              grpc_http2_status_to_grpc_status(atoi(val))),
           GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_copied_string(msg));
       gpr_free(val);
       gpr_free(msg);
@@ -518,50 +528,36 @@ static size_t max_payload_size_from_args(const grpc_channel_args* args) {
 
 static grpc_core::ManagedMemorySlice user_agent_from_args(
     const grpc_channel_args* args, const char* transport_name) {
-  gpr_strvec v;
-  size_t i;
-  int is_first = 1;
-  char* tmp;
+  std::vector<std::string> user_agent_fields;
 
-  gpr_strvec_init(&v);
-
-  for (i = 0; args && i < args->num_args; i++) {
+  for (size_t i = 0; args && i < args->num_args; i++) {
     if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) {
       if (args->args[i].type != GRPC_ARG_STRING) {
         gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
                 GRPC_ARG_PRIMARY_USER_AGENT_STRING);
       } else {
-        if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
-        is_first = 0;
-        gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
+        user_agent_fields.push_back(args->args[i].value.string);
       }
     }
   }
 
-  gpr_asprintf(&tmp, "%sgrpc-c/%s (%s; %s)", is_first ? "" : " ",
-               grpc_version_string(), GPR_PLATFORM_STRING, transport_name);
-  is_first = 0;
-  gpr_strvec_add(&v, tmp);
+  user_agent_fields.push_back(
+      absl::StrFormat("grpc-c/%s (%s; %s)", grpc_version_string(),
+                      GPR_PLATFORM_STRING, transport_name));
 
-  for (i = 0; args && i < args->num_args; i++) {
+  for (size_t i = 0; args && i < args->num_args; i++) {
     if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) {
       if (args->args[i].type != GRPC_ARG_STRING) {
         gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
                 GRPC_ARG_SECONDARY_USER_AGENT_STRING);
       } else {
-        if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
-        is_first = 0;
-        gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
+        user_agent_fields.push_back(args->args[i].value.string);
       }
     }
   }
 
-  tmp = gpr_strvec_flatten(&v, nullptr);
-  gpr_strvec_destroy(&v);
-  grpc_core::ManagedMemorySlice result(tmp);
-  gpr_free(tmp);
-
-  return result;
+  std::string user_agent_string = absl::StrJoin(user_agent_fields, " ");
+  return grpc_core::ManagedMemorySlice(user_agent_string.c_str());
 }
 
 /* Constructor for channel_data */
index fd71c2f..2c3cae6 100644 (file)
@@ -53,13 +53,13 @@ void client_authority_start_transport_stream_op_batch(
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   // Handle send_initial_metadata.
-  auto* initial_metadata =
-      batch->payload->send_initial_metadata.send_initial_metadata;
   // If the initial metadata doesn't already contain :authority, add it.
   if (batch->send_initial_metadata &&
-      initial_metadata->idx.named.authority == nullptr) {
+      batch->payload->send_initial_metadata.send_initial_metadata->idx.named
+              .authority == nullptr) {
     grpc_error* error = grpc_metadata_batch_add_head(
-        initial_metadata, &calld->authority_storage,
+        batch->payload->send_initial_metadata.send_initial_metadata,
+        &calld->authority_storage,
         GRPC_MDELEM_REF(chand->default_authority_mdelem), GRPC_BATCH_AUTHORITY);
     if (error != GRPC_ERROR_NONE) {
       grpc_transport_stream_op_batch_finish_with_failure(batch, error,
index 4094ffa..2fedc7f 100644 (file)
 #include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/transport/transport_impl.h"
 
-typedef struct {
+struct optional_filter {
   const grpc_channel_filter* filter;
   const char* control_channel_arg;
-} optional_filter;
+};
 
 static optional_filter compress_filter = {
     &grpc_message_compress_filter, GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION};
index 75f97d7..d2ef547 100644 (file)
@@ -27,6 +27,7 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/filters/client_channel/service_config_call_data.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack_builder.h"
 #include "src/core/lib/gpr/string.h"
@@ -44,7 +45,7 @@ namespace {
 size_t g_message_size_parser_index;
 }  // namespace
 
-std::unique_ptr<ServiceConfig::ParsedConfig>
+std::unique_ptr<ServiceConfigParser::ParsedConfig>
 MessageSizeParser::ParsePerMethodParams(const Json& json, grpc_error** error) {
   GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
   std::vector<grpc_error*> error_list;
@@ -91,8 +92,8 @@ MessageSizeParser::ParsePerMethodParams(const Json& json, grpc_error** error) {
 }
 
 void MessageSizeParser::Register() {
-  g_message_size_parser_index =
-      ServiceConfig::RegisterParser(absl::make_unique<MessageSizeParser>());
+  g_message_size_parser_index = ServiceConfigParser::RegisterParser(
+      absl::make_unique<MessageSizeParser>());
 }
 
 size_t MessageSizeParser::ParserIndex() { return g_message_size_parser_index; }
@@ -118,9 +119,9 @@ struct call_data {
     // apply the max request size to the send limit and the max response
     // size to the receive limit.
     const grpc_core::MessageSizeParsedConfig* limits = nullptr;
-    grpc_core::ServiceConfig::CallData* svc_cfg_call_data = nullptr;
+    grpc_core::ServiceConfigCallData* svc_cfg_call_data = nullptr;
     if (args.context != nullptr) {
-      svc_cfg_call_data = static_cast<grpc_core::ServiceConfig::CallData*>(
+      svc_cfg_call_data = static_cast<grpc_core::ServiceConfigCallData*>(
           args.context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
     }
     if (svc_cfg_call_data != nullptr) {
@@ -187,12 +188,8 @@ static void recv_message_ready(void* user_data, grpc_error* error) {
     grpc_error* new_error = grpc_error_set_int(
         GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string),
         GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED);
+    error = grpc_error_add_child(GRPC_ERROR_REF(error), new_error);
     GRPC_ERROR_UNREF(calld->error);
-    if (error == GRPC_ERROR_NONE) {
-      error = new_error;
-    } else {
-      error = grpc_error_add_child(error, new_error);
-    }
     calld->error = GRPC_ERROR_REF(error);
     gpr_free(message_string);
   } else {
index 58c1fac..132d7b2 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
-#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/filters/client_channel/service_config_parser.h"
 #include "src/core/lib/channel/channel_stack.h"
 
 extern const grpc_channel_filter grpc_message_size_filter;
 
 namespace grpc_core {
 
-class MessageSizeParsedConfig : public ServiceConfig::ParsedConfig {
+class MessageSizeParsedConfig : public ServiceConfigParser::ParsedConfig {
  public:
   struct message_size_limits {
     int max_send_size;
@@ -44,9 +44,9 @@ class MessageSizeParsedConfig : public ServiceConfig::ParsedConfig {
   message_size_limits limits_;
 };
 
-class MessageSizeParser : public ServiceConfig::Parser {
+class MessageSizeParser : public ServiceConfigParser::Parser {
  public:
-  std::unique_ptr<ServiceConfig::ParsedConfig> ParsePerMethodParams(
+  std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
       const Json& json, grpc_error** error) override;
 
   static void Register();
index 83e898f..446a214 100644 (file)
@@ -47,7 +47,7 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/server.h"
 
-typedef struct {
+struct server_state {
   grpc_server* server;
   grpc_tcp_server* tcp_server;
   grpc_channel_args* args;
@@ -58,9 +58,9 @@ typedef struct {
   grpc_core::HandshakeManager* pending_handshake_mgrs;
   grpc_core::RefCountedPtr<grpc_core::channelz::ListenSocketNode>
       channelz_listen_socket;
-} server_state;
+};
 
-typedef struct {
+struct server_connection_state {
   gpr_refcount refs;
   server_state* svr_state;
   grpc_pollset* accepting_pollset;
@@ -73,7 +73,7 @@ typedef struct {
   grpc_closure on_timeout;
   grpc_closure on_receive_settings;
   grpc_pollset_set* interested_parties;
-} server_connection_state;
+};
 
 static void server_connection_state_unref(
     server_connection_state* connection_state) {
index c816aba..ba39bbd 100644 (file)
 static const char alphabet[] =
     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
-typedef struct {
+struct b64_huff_sym {
   uint16_t bits;
   uint8_t length;
-} b64_huff_sym;
-
+};
 static const b64_huff_sym huff_alphabet[64] = {
     {0x21, 6}, {0x5d, 7}, {0x5e, 7},   {0x5f, 7}, {0x60, 7}, {0x61, 7},
     {0x62, 7}, {0x63, 7}, {0x64, 7},   {0x65, 7}, {0x66, 7}, {0x67, 7},
@@ -136,12 +135,11 @@ grpc_slice grpc_chttp2_huffman_compress(const grpc_slice& input) {
   return output;
 }
 
-typedef struct {
+struct huff_out {
   uint32_t temp;
   uint32_t temp_length;
   uint8_t* out;
-} huff_out;
-
+};
 static void enc_flush_some(huff_out* out) {
   while (out->temp_length > 8) {
     out->temp_length -= 8;
index cc03a40..5c96910 100644 (file)
@@ -1356,10 +1356,8 @@ static void perform_stream_op_locked(void* stream_op,
   s->context = op->payload->context;
   s->traced = op->is_traced;
   if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
-    char* str = grpc_transport_stream_op_batch_string(op);
-    gpr_log(GPR_INFO, "perform_stream_op_locked: %s; on_complete = %p", str,
-            op->on_complete);
-    gpr_free(str);
+    gpr_log(GPR_INFO, "perform_stream_op_locked: %s; on_complete = %p",
+            grpc_transport_stream_op_batch_string(op).c_str(), op->on_complete);
     if (op->send_initial_metadata) {
       log_metadata(op_payload->send_initial_metadata.send_initial_metadata,
                    s->id, t->is_client, true);
@@ -1654,9 +1652,8 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
   }
 
   if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
-    char* str = grpc_transport_stream_op_batch_string(op);
-    gpr_log(GPR_INFO, "perform_stream_op[s=%p]: %s", s, str);
-    gpr_free(str);
+    gpr_log(GPR_INFO, "perform_stream_op[s=%p]: %s", s,
+            grpc_transport_stream_op_batch_string(op).c_str());
   }
 
   GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op");
@@ -1845,9 +1842,8 @@ static void perform_transport_op_locked(void* stream_op,
 static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) {
   grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(gt);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
-    char* msg = grpc_transport_op_string(op);
-    gpr_log(GPR_INFO, "perform_transport_op[t=%p]: %s", t, msg);
-    gpr_free(msg);
+    gpr_log(GPR_INFO, "perform_transport_op[t=%p]: %s", t,
+            grpc_transport_op_string(op).c_str());
   }
   op->handler_private.extra_arg = gt;
   GRPC_CHTTP2_REF_TRANSPORT(t, "transport_op");
@@ -2401,10 +2397,10 @@ static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
   grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API);
 }
 
-typedef struct {
+struct cancel_stream_cb_args {
   grpc_error* error;
   grpc_chttp2_transport* t;
-} cancel_stream_cb_args;
+};
 
 static void cancel_stream_cb(void* user_data, uint32_t /*key*/, void* stream) {
   cancel_stream_cb_args* args = static_cast<cancel_stream_cb_args*>(user_data);
@@ -2485,7 +2481,8 @@ static grpc_error* try_http_parsing(grpc_chttp2_transport* t) {
         grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
                                "Trying to connect an http1.x server"),
                            GRPC_ERROR_INT_HTTP_STATUS, response.status),
-        GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
+        GRPC_ERROR_INT_GRPC_STATUS,
+        grpc_http2_status_to_grpc_status(response.status));
   }
   GRPC_ERROR_UNREF(parse_error);
 
index 6f65bb2..df6274d 100644 (file)
@@ -37,15 +37,14 @@ typedef enum {
   GRPC_CHTTP2_GOAWAY_DEBUG
 } grpc_chttp2_goaway_parse_state;
 
-typedef struct {
+struct grpc_chttp2_goaway_parser {
   grpc_chttp2_goaway_parse_state state;
   uint32_t last_stream_id;
   uint32_t error_code;
   char* debug_data;
   uint32_t debug_length;
   uint32_t debug_pos;
-} grpc_chttp2_goaway_parser;
-
+};
 void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser* p);
 void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser* p);
 grpc_error* grpc_chttp2_goaway_parser_begin_frame(
index 915d023..e356bf4 100644 (file)
 #include <grpc/slice.h>
 #include "src/core/ext/transport/chttp2/transport/frame.h"
 
-typedef struct {
+struct grpc_chttp2_ping_parser {
   uint8_t byte;
   uint8_t is_ack;
   uint64_t opaque_8bytes;
-} grpc_chttp2_ping_parser;
-
+};
 grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes);
 
 grpc_error* grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser* parser,
index d61e623..e324ee2 100644 (file)
 #include "src/core/ext/transport/chttp2/transport/frame.h"
 #include "src/core/lib/transport/transport.h"
 
-typedef struct {
+struct grpc_chttp2_rst_stream_parser {
   uint8_t byte;
   uint8_t reason_bytes[4];
-} grpc_chttp2_rst_stream_parser;
-
+};
 grpc_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code,
                                          grpc_transport_one_way_stats* stats);
 
index 8a3ff04..1814714 100644 (file)
@@ -34,15 +34,14 @@ typedef enum {
   GRPC_CHTTP2_SPS_VAL3
 } grpc_chttp2_settings_parse_state;
 
-typedef struct {
+struct grpc_chttp2_settings_parser {
   grpc_chttp2_settings_parse_state state;
   uint32_t* target_settings;
   uint8_t is_ack;
   uint16_t id;
   uint32_t value;
   uint32_t incoming_settings[GRPC_CHTTP2_NUM_SETTINGS];
-} grpc_chttp2_settings_parser;
-
+};
 /* Create a settings frame by diffing old & new, and updating old to be new */
 grpc_slice grpc_chttp2_settings_create(uint32_t* old, const uint32_t* newval,
                                        uint32_t force_mask, size_t count);
index f6721a5..340445d 100644 (file)
 #include "src/core/ext/transport/chttp2/transport/frame.h"
 #include "src/core/lib/transport/transport.h"
 
-typedef struct {
+struct grpc_chttp2_window_update_parser {
   uint8_t byte;
   uint8_t is_connection_update;
   uint32_t amount;
-} grpc_chttp2_window_update_parser;
-
+};
 grpc_slice grpc_chttp2_window_update_create(
     uint32_t id, uint32_t window_delta, grpc_transport_one_way_stats* stats);
 
index 16a4695..4ceaec2 100644 (file)
@@ -259,7 +259,7 @@ static bool CanAddToHashtable(grpc_chttp2_hpack_compressor* hpack_compressor,
 }
 } /* namespace */
 
-typedef struct {
+struct framer_state {
   int is_first_frame;
   /* number of bytes in 'output' when we started the frame - used to calculate
      frame length */
@@ -277,8 +277,8 @@ typedef struct {
   /* maximum size of a frame */
   size_t max_frame_size;
   bool use_true_binary_metadata;
-} framer_state;
-
+  bool is_end_of_stream;
+};
 /* fills p (which is expected to be kDataFrameHeaderSize bytes long)
  * with a data frame header */
 static void fill_header(uint8_t* p, uint8_t type, uint32_t id, size_t len,
@@ -315,17 +315,29 @@ static size_t current_frame_size(framer_state* st) {
 }
 
 /* finish a frame - fill in the previously reserved header */
-static void finish_frame(framer_state* st, int is_header_boundary,
-                         int is_last_in_stream) {
+static void finish_frame(framer_state* st, int is_header_boundary) {
   uint8_t type = 0xff;
-  type = st->is_first_frame ? GRPC_CHTTP2_FRAME_HEADER
-                            : GRPC_CHTTP2_FRAME_CONTINUATION;
-  fill_header(
-      GRPC_SLICE_START_PTR(st->output->slices[st->header_idx]), type,
-      st->stream_id, current_frame_size(st),
-      static_cast<uint8_t>(
-          (is_last_in_stream ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0) |
-          (is_header_boundary ? GRPC_CHTTP2_DATA_FLAG_END_HEADERS : 0)));
+  type =
+      static_cast<uint8_t>(st->is_first_frame ? GRPC_CHTTP2_FRAME_HEADER
+                                              : GRPC_CHTTP2_FRAME_CONTINUATION);
+  uint8_t flags = 0xff;
+  /* per the HTTP/2 spec:
+       A HEADERS frame carries the END_STREAM flag that signals the end of a
+       stream. However, a HEADERS frame with the END_STREAM flag set can be
+       followed by CONTINUATION frames on the same stream. Logically, the
+       CONTINUATION frames are part of the HEADERS frame.
+     Thus, we add the END_STREAM flag to the HEADER frame (the first frame). */
+  flags = static_cast<uint8_t>(st->is_first_frame && st->is_end_of_stream
+                                   ? GRPC_CHTTP2_DATA_FLAG_END_STREAM
+                                   : 0);
+  /* per the HTTP/2 spec:
+       A HEADERS frame without the END_HEADERS flag set MUST be followed by
+       a CONTINUATION frame for the same stream.
+     Thus, we add the END_HEADER flag to the last frame. */
+  flags |= static_cast<uint8_t>(
+      is_header_boundary ? GRPC_CHTTP2_DATA_FLAG_END_HEADERS : 0);
+  fill_header(GRPC_SLICE_START_PTR(st->output->slices[st->header_idx]), type,
+              st->stream_id, current_frame_size(st), flags);
   st->stats->framing_bytes += kDataFrameHeaderSize;
   st->is_first_frame = 0;
 }
@@ -347,7 +359,7 @@ static void ensure_space(framer_state* st, size_t need_bytes) {
   if (GPR_LIKELY(current_frame_size(st) + need_bytes <= st->max_frame_size)) {
     return;
   }
-  finish_frame(st, 0, 0);
+  finish_frame(st, 0);
   begin_frame(st);
 }
 
@@ -362,7 +374,7 @@ static void add_header_data(framer_state* st, grpc_slice slice) {
   } else {
     st->stats->header_bytes += remaining;
     grpc_slice_buffer_add(st->output, grpc_slice_split_head(&slice, remaining));
-    finish_frame(st, 0, 0);
+    finish_frame(st, 0);
     begin_frame(st);
     add_header_data(st, slice);
   }
@@ -841,6 +853,7 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor* c,
   st.stats = options->stats;
   st.max_frame_size = options->max_frame_size;
   st.use_true_binary_metadata = options->use_true_binary_metadata;
+  st.is_end_of_stream = options->is_eof;
 
   /* Encode a metadata batch; store the returned values, representing
      a metadata element that needs to be unreffed back into the metadata
@@ -883,5 +896,5 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor* c,
     deadline_enc(c, deadline, &st);
   }
 
-  finish_frame(&st, 1, options->is_eof);
+  finish_frame(&st, 1);
 }
index dc371fa..5093f80 100644 (file)
@@ -90,14 +90,13 @@ void grpc_chttp2_hpack_compressor_set_max_table_size(
 void grpc_chttp2_hpack_compressor_set_max_usable_size(
     grpc_chttp2_hpack_compressor* c, uint32_t max_table_size);
 
-typedef struct {
+struct grpc_encode_header_options {
   uint32_t stream_id;
   bool is_eof;
   bool use_true_binary_metadata;
   size_t max_frame_size;
   grpc_transport_one_way_stats* stats;
-} grpc_encode_header_options;
-
+};
 void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor* c,
                                grpc_mdelem** extra_headers,
                                size_t extra_headers_size,
index eb90568..1b859c4 100644 (file)
@@ -32,7 +32,7 @@ typedef struct grpc_chttp2_hpack_parser grpc_chttp2_hpack_parser;
 typedef grpc_error* (*grpc_chttp2_hpack_parser_state)(
     grpc_chttp2_hpack_parser* p, const uint8_t* beg, const uint8_t* end);
 
-typedef struct {
+struct grpc_chttp2_hpack_parser_string {
   bool copied;
   struct {
     grpc_slice referenced;
@@ -42,8 +42,7 @@ typedef struct {
       uint32_t capacity;
     } copied;
   } data;
-} grpc_chttp2_hpack_parser_string;
-
+};
 struct grpc_chttp2_hpack_parser {
   /* user specified callback for each header output */
   grpc_error* (*on_header)(void* user_data, grpc_mdelem md);
index 5a6c739..34c3dce 100644 (file)
@@ -138,10 +138,10 @@ inline uintptr_t grpc_chttp2_get_static_hpack_table_index(grpc_mdelem md) {
 
 /* Find a key/value pair in the table... returns the index in the table of the
    most similar entry, or 0 if the value was not found */
-typedef struct {
+struct grpc_chttp2_hptbl_find_result {
   uint32_t index;
   int has_value;
-} grpc_chttp2_hptbl_find_result;
+};
 grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
     const grpc_chttp2_hptbl* tbl, grpc_mdelem md);
 
index 07ce062..3e8ead6 100644 (file)
@@ -26,7 +26,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 
-typedef enum {
+enum grpc_chttp2_setting_id {
   GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE = 0,               /* wire id 1 */
   GRPC_CHTTP2_SETTINGS_ENABLE_PUSH = 1,                     /* wire id 2 */
   GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 2,          /* wire id 3 */
@@ -34,7 +34,7 @@ typedef enum {
   GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE = 4,                  /* wire id 5 */
   GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 5,            /* wire id 6 */
   GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA = 6, /* wire id 65027 */
-} grpc_chttp2_setting_id;
+};
 
 #define GRPC_CHTTP2_NUM_SETTINGS 7
 
@@ -47,15 +47,14 @@ typedef enum {
   GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE
 } grpc_chttp2_invalid_value_behavior;
 
-typedef struct {
+struct grpc_chttp2_setting_parameters {
   const char* name;
   uint32_t default_value;
   uint32_t min_value;
   uint32_t max_value;
   grpc_chttp2_invalid_value_behavior invalid_value_behavior;
   uint32_t error_value;
-} grpc_chttp2_setting_parameters;
-
+};
 extern const grpc_chttp2_setting_parameters
     grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS];
 
index 2e2a5da..49feb23 100644 (file)
 
 #define GRPC_CHTTP2_NUM_HUFFSYMS 257
 
-typedef struct {
+struct grpc_chttp2_huffsym {
   unsigned bits;
   unsigned length;
-} grpc_chttp2_huffsym;
-
+};
 extern const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS];
 
 #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HUFFSYMS_H */
index fa3d882..568fac9 100644 (file)
@@ -106,30 +106,26 @@ typedef enum {
 const char* grpc_chttp2_initiate_write_reason_string(
     grpc_chttp2_initiate_write_reason reason);
 
-typedef struct {
+struct grpc_chttp2_ping_queue {
   grpc_closure_list lists[GRPC_CHTTP2_PCL_COUNT] = {};
   uint64_t inflight_id = 0;
-} grpc_chttp2_ping_queue;
-
-typedef struct {
+};
+struct grpc_chttp2_repeated_ping_policy {
   int max_pings_without_data;
   int max_ping_strikes;
   grpc_millis min_sent_ping_interval_without_data;
   grpc_millis min_recv_ping_interval_without_data;
-} grpc_chttp2_repeated_ping_policy;
-
-typedef struct {
+};
+struct grpc_chttp2_repeated_ping_state {
   grpc_millis last_ping_sent_time;
   int pings_before_data_required;
   grpc_timer delayed_ping_timer;
   bool is_delayed_ping_timer_set;
-} grpc_chttp2_repeated_ping_state;
-
-typedef struct {
+};
+struct grpc_chttp2_server_ping_recv_state {
   grpc_millis last_ping_recv_time;
   int ping_strikes;
-} grpc_chttp2_server_ping_recv_state;
-
+};
 /* deframer state for the overall http2 stream of bytes */
 typedef enum {
   /* prefix: one entry per http2 connection prefix byte */
@@ -173,16 +169,14 @@ typedef enum {
   GRPC_DTS_FRAME
 } grpc_chttp2_deframe_transport_state;
 
-typedef struct {
+struct grpc_chttp2_stream_list {
   grpc_chttp2_stream* head;
   grpc_chttp2_stream* tail;
-} grpc_chttp2_stream_list;
-
-typedef struct {
+};
+struct grpc_chttp2_stream_link {
   grpc_chttp2_stream* next;
   grpc_chttp2_stream* prev;
-} grpc_chttp2_stream_link;
-
+};
 /* We keep several sets of connection wide parameters */
 typedef enum {
   /* The settings our peer has asked for (and we have acked) */
@@ -678,15 +672,14 @@ struct grpc_chttp2_stream {
 void grpc_chttp2_initiate_write(grpc_chttp2_transport* t,
                                 grpc_chttp2_initiate_write_reason reason);
 
-typedef struct {
+struct grpc_chttp2_begin_write_result {
   /** are we writing? */
   bool writing;
   /** if writing: was it a complete flush (false) or a partial flush (true) */
   bool partial;
   /** did we queue any completions as part of beginning the write */
   bool early_results_scheduled;
-} grpc_chttp2_begin_write_result;
-
+};
 grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
     grpc_chttp2_transport* t);
 void grpc_chttp2_end_write(grpc_chttp2_transport* t, grpc_error* error);
index 9fb8826..485abd2 100644 (file)
    Lookups are performed with binary search.
    Adds are restricted to strictly higher keys than previously seen (this is
    guaranteed by http2). */
-typedef struct {
+struct grpc_chttp2_stream_map {
   uint32_t* keys;
   void** values;
   size_t count;
   size_t free;
   size_t capacity;
-} grpc_chttp2_stream_map;
-
+};
 void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map* map,
                                  size_t initial_capacity);
 void grpc_chttp2_stream_map_destroy(grpc_chttp2_stream_map* map);
index 98d7f9f..7f664b6 100644 (file)
@@ -57,7 +57,7 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
     if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) ||
         GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace) ||
         GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
-      gpr_log(GPR_INFO, "%s: Ping delayed [%p]: already pinging",
+      gpr_log(GPR_INFO, "%s: Ping delayed [%s]: already pinging",
               t->is_client ? "CLIENT" : "SERVER", t->peer_string);
     }
     return;
@@ -68,7 +68,7 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
     if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) ||
         GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace) ||
         GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
-      gpr_log(GPR_INFO, "%s: Ping delayed [%p]: too many recent pings: %d/%d",
+      gpr_log(GPR_INFO, "%s: Ping delayed [%s]: too many recent pings: %d/%d",
               t->is_client ? "CLIENT" : "SERVER", t->peer_string,
               t->ping_state.pings_before_data_required,
               t->ping_policy.max_pings_without_data);
@@ -81,7 +81,9 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
       (t->keepalive_permit_without_calls == 0 &&
        grpc_chttp2_stream_map_size(&t->stream_map) == 0)
           ? 7200 * GPR_MS_PER_SEC
-          : t->ping_policy.min_sent_ping_interval_without_data;
+          : (t->ping_policy.min_sent_ping_interval_without_data +
+             GPR_MS_PER_SEC); /* A second is added to deal with network delays
+                                 and timing imprecision */
   grpc_millis next_allowed_ping =
       t->ping_state.last_ping_sent_time + next_allowed_ping_interval;
 
@@ -91,7 +93,7 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
         GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace) ||
         GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
       gpr_log(GPR_INFO,
-              "%s: Ping delayed [%p]: not enough time elapsed since last ping. "
+              "%s: Ping delayed [%s]: not enough time elapsed since last ping. "
               " Last ping %f: Next ping %f: Now %f",
               t->is_client ? "CLIENT" : "SERVER", t->peer_string,
               static_cast<double>(t->ping_state.last_ping_sent_time),
index 7b24347..424a37c 100644 (file)
@@ -764,6 +764,7 @@ void op_state_machine_locked(inproc_stream* s, grpc_error* error) {
       // Nothing further will try to receive from this stream, so finish off
       // any outstanding send_message op
       s->send_message_op->payload->send_message.send_message.reset();
+      s->send_message_op->payload->send_message.stream_write_closed = true;
       complete_if_batch_end_locked(
           s, new_err, s->send_message_op,
           "op_state_machine scheduling send-message-on-complete");
@@ -811,6 +812,24 @@ void op_state_machine_locked(inproc_stream* s, grpc_error* error) {
           "op_state_machine %p has trailing md but not yet waiting for it", s);
     }
   }
+  if (!s->t->is_client && s->trailing_md_sent &&
+      (s->recv_trailing_md_op != nullptr)) {
+    // In this case, we don't care to receive the write-close from the client
+    // because we have already sent status and the RPC is over as far as we
+    // are concerned.
+    INPROC_LOG(GPR_INFO, "op_state_machine %p scheduling trailing-md-ready %p",
+               s, new_err);
+    grpc_core::ExecCtx::Run(
+        DEBUG_LOCATION,
+        s->recv_trailing_md_op->payload->recv_trailing_metadata
+            .recv_trailing_metadata_ready,
+        GRPC_ERROR_REF(new_err));
+    complete_if_batch_end_locked(
+        s, new_err, s->recv_trailing_md_op,
+        "op_state_machine scheduling recv-trailing-md-on-complete");
+    s->trailing_md_recvd = true;
+    s->recv_trailing_md_op = nullptr;
+  }
   if (s->trailing_md_recvd && s->recv_message_op) {
     // No further message will come on this stream, so finish off the
     // recv_message_op
index e56cf22..e27f898 100644 (file)
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/api/v2/auth/cert.upb.h"
-#include "envoy/api/v2/core/base.upb.h"
-#include "envoy/api/v2/core/config_source.upb.h"
-#include "envoy/type/matcher/string.upb.h"
-#include "google/protobuf/any.upb.h"
-#include "google/protobuf/duration.upb.h"
-#include "google/protobuf/struct.upb.h"
-#include "google/protobuf/wrappers.upb.h"
-#include "udpa/annotations/sensitive.upb.h"
 #include "udpa/annotations/migrate.upb.h"
-#include "validate/validate.upb.h"
+#include "udpa/annotations/status.upb.h"
+#include "envoy/api/v2/auth/common.upb.h"
+#include "envoy/api/v2/auth/secret.upb.h"
+#include "envoy/api/v2/auth/tls.upb.h"
 
 #include "upb/port_def.inc"
 
-static const upb_msglayout_field envoy_api_v2_auth_TlsParameters__fields[4] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 14, 1},
-  {2, UPB_SIZE(8, 8), 0, 0, 14, 1},
-  {3, UPB_SIZE(16, 16), 0, 0, 9, 3},
-  {4, UPB_SIZE(20, 24), 0, 0, 9, 3},
-};
-
-const upb_msglayout envoy_api_v2_auth_TlsParameters_msginit = {
-  NULL,
-  &envoy_api_v2_auth_TlsParameters__fields[0],
-  UPB_SIZE(24, 32), 4, false,
-};
-
-static const upb_msglayout *const envoy_api_v2_auth_PrivateKeyProvider_submsgs[2] = {
-  &google_protobuf_Any_msginit,
-  &google_protobuf_Struct_msginit,
-};
-
-static const upb_msglayout_field envoy_api_v2_auth_PrivateKeyProvider__fields[3] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 9, 1},
-  {2, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 1, 11, 1},
-  {3, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1},
-};
-
-const upb_msglayout envoy_api_v2_auth_PrivateKeyProvider_msginit = {
-  &envoy_api_v2_auth_PrivateKeyProvider_submsgs[0],
-  &envoy_api_v2_auth_PrivateKeyProvider__fields[0],
-  UPB_SIZE(16, 32), 3, false,
-};
-
-static const upb_msglayout *const envoy_api_v2_auth_TlsCertificate_submsgs[6] = {
-  &envoy_api_v2_auth_PrivateKeyProvider_msginit,
-  &envoy_api_v2_core_DataSource_msginit,
-};
-
-static const upb_msglayout_field envoy_api_v2_auth_TlsCertificate__fields[6] = {
-  {1, UPB_SIZE(0, 0), 0, 1, 11, 1},
-  {2, UPB_SIZE(4, 8), 0, 1, 11, 1},
-  {3, UPB_SIZE(8, 16), 0, 1, 11, 1},
-  {4, UPB_SIZE(12, 24), 0, 1, 11, 1},
-  {5, UPB_SIZE(20, 40), 0, 1, 11, 3},
-  {6, UPB_SIZE(16, 32), 0, 0, 11, 1},
-};
-
-const upb_msglayout envoy_api_v2_auth_TlsCertificate_msginit = {
-  &envoy_api_v2_auth_TlsCertificate_submsgs[0],
-  &envoy_api_v2_auth_TlsCertificate__fields[0],
-  UPB_SIZE(24, 48), 6, false,
-};
-
-static const upb_msglayout *const envoy_api_v2_auth_TlsSessionTicketKeys_submsgs[1] = {
-  &envoy_api_v2_core_DataSource_msginit,
-};
-
-static const upb_msglayout_field envoy_api_v2_auth_TlsSessionTicketKeys__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout envoy_api_v2_auth_TlsSessionTicketKeys_msginit = {
-  &envoy_api_v2_auth_TlsSessionTicketKeys_submsgs[0],
-  &envoy_api_v2_auth_TlsSessionTicketKeys__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const envoy_api_v2_auth_CertificateValidationContext_submsgs[5] = {
-  &envoy_api_v2_core_DataSource_msginit,
-  &envoy_type_matcher_StringMatcher_msginit,
-  &google_protobuf_BoolValue_msginit,
-};
-
-static const upb_msglayout_field envoy_api_v2_auth_CertificateValidationContext__fields[10] = {
-  {1, UPB_SIZE(12, 16), 0, 0, 11, 1},
-  {2, UPB_SIZE(28, 48), 0, 0, 9, 3},
-  {3, UPB_SIZE(32, 56), 0, 0, 9, 3},
-  {4, UPB_SIZE(36, 64), 0, 0, 9, 3},
-  {5, UPB_SIZE(16, 24), 0, 2, 11, 1},
-  {6, UPB_SIZE(20, 32), 0, 2, 11, 1},
-  {7, UPB_SIZE(24, 40), 0, 0, 11, 1},
-  {8, UPB_SIZE(8, 8), 0, 0, 8, 1},
-  {9, UPB_SIZE(40, 72), 0, 1, 11, 3},
-  {10, UPB_SIZE(0, 0), 0, 0, 14, 1},
-};
-
-const upb_msglayout envoy_api_v2_auth_CertificateValidationContext_msginit = {
-  &envoy_api_v2_auth_CertificateValidationContext_submsgs[0],
-  &envoy_api_v2_auth_CertificateValidationContext__fields[0],
-  UPB_SIZE(48, 80), 10, false,
-};
-
-static const upb_msglayout *const envoy_api_v2_auth_CommonTlsContext_submsgs[6] = {
-  &envoy_api_v2_auth_CertificateValidationContext_msginit,
-  &envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit,
-  &envoy_api_v2_auth_SdsSecretConfig_msginit,
-  &envoy_api_v2_auth_TlsCertificate_msginit,
-  &envoy_api_v2_auth_TlsParameters_msginit,
-};
-
-static const upb_msglayout_field envoy_api_v2_auth_CommonTlsContext__fields[7] = {
-  {1, UPB_SIZE(0, 0), 0, 4, 11, 1},
-  {2, UPB_SIZE(4, 8), 0, 3, 11, 3},
-  {3, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 0, 11, 1},
-  {4, UPB_SIZE(8, 16), 0, 0, 9, 3},
-  {6, UPB_SIZE(12, 24), 0, 2, 11, 3},
-  {7, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 2, 11, 1},
-  {8, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 1, 11, 1},
-};
-
-const upb_msglayout envoy_api_v2_auth_CommonTlsContext_msginit = {
-  &envoy_api_v2_auth_CommonTlsContext_submsgs[0],
-  &envoy_api_v2_auth_CommonTlsContext__fields[0],
-  UPB_SIZE(24, 48), 7, false,
-};
-
-static const upb_msglayout *const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_submsgs[2] = {
-  &envoy_api_v2_auth_CertificateValidationContext_msginit,
-  &envoy_api_v2_auth_SdsSecretConfig_msginit,
-};
-
-static const upb_msglayout_field envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext__fields[2] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
-  {2, UPB_SIZE(4, 8), 0, 1, 11, 1},
-};
-
-const upb_msglayout envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit = {
-  &envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_submsgs[0],
-  &envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext__fields[0],
-  UPB_SIZE(8, 16), 2, false,
-};
-
-static const upb_msglayout *const envoy_api_v2_auth_UpstreamTlsContext_submsgs[2] = {
-  &envoy_api_v2_auth_CommonTlsContext_msginit,
-  &google_protobuf_UInt32Value_msginit,
-};
-
-static const upb_msglayout_field envoy_api_v2_auth_UpstreamTlsContext__fields[4] = {
-  {1, UPB_SIZE(12, 24), 0, 0, 11, 1},
-  {2, UPB_SIZE(4, 8), 0, 0, 9, 1},
-  {3, UPB_SIZE(0, 0), 0, 0, 8, 1},
-  {4, UPB_SIZE(16, 32), 0, 1, 11, 1},
-};
-
-const upb_msglayout envoy_api_v2_auth_UpstreamTlsContext_msginit = {
-  &envoy_api_v2_auth_UpstreamTlsContext_submsgs[0],
-  &envoy_api_v2_auth_UpstreamTlsContext__fields[0],
-  UPB_SIZE(24, 48), 4, false,
-};
-
-static const upb_msglayout *const envoy_api_v2_auth_DownstreamTlsContext_submsgs[6] = {
-  &envoy_api_v2_auth_CommonTlsContext_msginit,
-  &envoy_api_v2_auth_SdsSecretConfig_msginit,
-  &envoy_api_v2_auth_TlsSessionTicketKeys_msginit,
-  &google_protobuf_BoolValue_msginit,
-  &google_protobuf_Duration_msginit,
-};
-
-static const upb_msglayout_field envoy_api_v2_auth_DownstreamTlsContext__fields[6] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
-  {2, UPB_SIZE(4, 8), 0, 3, 11, 1},
-  {3, UPB_SIZE(8, 16), 0, 3, 11, 1},
-  {4, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 2, 11, 1},
-  {5, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 1, 11, 1},
-  {6, UPB_SIZE(12, 24), 0, 4, 11, 1},
-};
-
-const upb_msglayout envoy_api_v2_auth_DownstreamTlsContext_msginit = {
-  &envoy_api_v2_auth_DownstreamTlsContext_submsgs[0],
-  &envoy_api_v2_auth_DownstreamTlsContext__fields[0],
-  UPB_SIZE(24, 48), 6, false,
-};
-
-static const upb_msglayout *const envoy_api_v2_auth_GenericSecret_submsgs[1] = {
-  &envoy_api_v2_core_DataSource_msginit,
-};
-
-static const upb_msglayout_field envoy_api_v2_auth_GenericSecret__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
-};
-
-const upb_msglayout envoy_api_v2_auth_GenericSecret_msginit = {
-  &envoy_api_v2_auth_GenericSecret_submsgs[0],
-  &envoy_api_v2_auth_GenericSecret__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const envoy_api_v2_auth_SdsSecretConfig_submsgs[1] = {
-  &envoy_api_v2_core_ConfigSource_msginit,
-};
-
-static const upb_msglayout_field envoy_api_v2_auth_SdsSecretConfig__fields[2] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 9, 1},
-  {2, UPB_SIZE(8, 16), 0, 0, 11, 1},
-};
-
-const upb_msglayout envoy_api_v2_auth_SdsSecretConfig_msginit = {
-  &envoy_api_v2_auth_SdsSecretConfig_submsgs[0],
-  &envoy_api_v2_auth_SdsSecretConfig__fields[0],
-  UPB_SIZE(16, 32), 2, false,
-};
-
-static const upb_msglayout *const envoy_api_v2_auth_Secret_submsgs[4] = {
-  &envoy_api_v2_auth_CertificateValidationContext_msginit,
-  &envoy_api_v2_auth_GenericSecret_msginit,
-  &envoy_api_v2_auth_TlsCertificate_msginit,
-  &envoy_api_v2_auth_TlsSessionTicketKeys_msginit,
-};
-
-static const upb_msglayout_field envoy_api_v2_auth_Secret__fields[5] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 9, 1},
-  {2, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 2, 11, 1},
-  {3, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 3, 11, 1},
-  {4, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1},
-  {5, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 1, 11, 1},
-};
-
-const upb_msglayout envoy_api_v2_auth_Secret_msginit = {
-  &envoy_api_v2_auth_Secret_submsgs[0],
-  &envoy_api_v2_auth_Secret__fields[0],
-  UPB_SIZE(16, 32), 5, false,
-};
-
 #include "upb/port_undef.inc"
 
index 397be40..96c8ade 100644 (file)
 #include "upb/decode.h"
 #include "upb/encode.h"
 
+/* Public Imports. */
+#include "envoy/api/v2/auth/common.upb.h"
+#include "envoy/api/v2/auth/secret.upb.h"
+#include "envoy/api/v2/auth/tls.upb.h"
+
 #include "upb/port_def.inc"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-struct envoy_api_v2_auth_TlsParameters;
-struct envoy_api_v2_auth_PrivateKeyProvider;
-struct envoy_api_v2_auth_TlsCertificate;
-struct envoy_api_v2_auth_TlsSessionTicketKeys;
-struct envoy_api_v2_auth_CertificateValidationContext;
-struct envoy_api_v2_auth_CommonTlsContext;
-struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext;
-struct envoy_api_v2_auth_UpstreamTlsContext;
-struct envoy_api_v2_auth_DownstreamTlsContext;
-struct envoy_api_v2_auth_GenericSecret;
-struct envoy_api_v2_auth_SdsSecretConfig;
-struct envoy_api_v2_auth_Secret;
-typedef struct envoy_api_v2_auth_TlsParameters envoy_api_v2_auth_TlsParameters;
-typedef struct envoy_api_v2_auth_PrivateKeyProvider envoy_api_v2_auth_PrivateKeyProvider;
-typedef struct envoy_api_v2_auth_TlsCertificate envoy_api_v2_auth_TlsCertificate;
-typedef struct envoy_api_v2_auth_TlsSessionTicketKeys envoy_api_v2_auth_TlsSessionTicketKeys;
-typedef struct envoy_api_v2_auth_CertificateValidationContext envoy_api_v2_auth_CertificateValidationContext;
-typedef struct envoy_api_v2_auth_CommonTlsContext envoy_api_v2_auth_CommonTlsContext;
-typedef struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext;
-typedef struct envoy_api_v2_auth_UpstreamTlsContext envoy_api_v2_auth_UpstreamTlsContext;
-typedef struct envoy_api_v2_auth_DownstreamTlsContext envoy_api_v2_auth_DownstreamTlsContext;
-typedef struct envoy_api_v2_auth_GenericSecret envoy_api_v2_auth_GenericSecret;
-typedef struct envoy_api_v2_auth_SdsSecretConfig envoy_api_v2_auth_SdsSecretConfig;
-typedef struct envoy_api_v2_auth_Secret envoy_api_v2_auth_Secret;
-extern const upb_msglayout envoy_api_v2_auth_TlsParameters_msginit;
-extern const upb_msglayout envoy_api_v2_auth_PrivateKeyProvider_msginit;
-extern const upb_msglayout envoy_api_v2_auth_TlsCertificate_msginit;
-extern const upb_msglayout envoy_api_v2_auth_TlsSessionTicketKeys_msginit;
-extern const upb_msglayout envoy_api_v2_auth_CertificateValidationContext_msginit;
-extern const upb_msglayout envoy_api_v2_auth_CommonTlsContext_msginit;
-extern const upb_msglayout envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit;
-extern const upb_msglayout envoy_api_v2_auth_UpstreamTlsContext_msginit;
-extern const upb_msglayout envoy_api_v2_auth_DownstreamTlsContext_msginit;
-extern const upb_msglayout envoy_api_v2_auth_GenericSecret_msginit;
-extern const upb_msglayout envoy_api_v2_auth_SdsSecretConfig_msginit;
-extern const upb_msglayout envoy_api_v2_auth_Secret_msginit;
-struct envoy_api_v2_core_ConfigSource;
-struct envoy_api_v2_core_DataSource;
-struct envoy_type_matcher_StringMatcher;
-struct google_protobuf_Any;
-struct google_protobuf_BoolValue;
-struct google_protobuf_Duration;
-struct google_protobuf_Struct;
-struct google_protobuf_UInt32Value;
-extern const upb_msglayout envoy_api_v2_core_ConfigSource_msginit;
-extern const upb_msglayout envoy_api_v2_core_DataSource_msginit;
-extern const upb_msglayout envoy_type_matcher_StringMatcher_msginit;
-extern const upb_msglayout google_protobuf_Any_msginit;
-extern const upb_msglayout google_protobuf_BoolValue_msginit;
-extern const upb_msglayout google_protobuf_Duration_msginit;
-extern const upb_msglayout google_protobuf_Struct_msginit;
-extern const upb_msglayout google_protobuf_UInt32Value_msginit;
-
-typedef enum {
-  envoy_api_v2_auth_CertificateValidationContext_VERIFY_TRUST_CHAIN = 0,
-  envoy_api_v2_auth_CertificateValidationContext_ACCEPT_UNTRUSTED = 1
-} envoy_api_v2_auth_CertificateValidationContext_TrustChainVerification;
-
-typedef enum {
-  envoy_api_v2_auth_TlsParameters_TLS_AUTO = 0,
-  envoy_api_v2_auth_TlsParameters_TLSv1_0 = 1,
-  envoy_api_v2_auth_TlsParameters_TLSv1_1 = 2,
-  envoy_api_v2_auth_TlsParameters_TLSv1_2 = 3,
-  envoy_api_v2_auth_TlsParameters_TLSv1_3 = 4
-} envoy_api_v2_auth_TlsParameters_TlsProtocol;
-
-
-/* envoy.api.v2.auth.TlsParameters */
-
-UPB_INLINE envoy_api_v2_auth_TlsParameters *envoy_api_v2_auth_TlsParameters_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_TlsParameters *)upb_msg_new(&envoy_api_v2_auth_TlsParameters_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_TlsParameters *envoy_api_v2_auth_TlsParameters_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_TlsParameters *ret = envoy_api_v2_auth_TlsParameters_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_TlsParameters_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_TlsParameters_serialize(const envoy_api_v2_auth_TlsParameters *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_TlsParameters_msginit, arena, len);
-}
-
-UPB_INLINE int32_t envoy_api_v2_auth_TlsParameters_tls_minimum_protocol_version(const envoy_api_v2_auth_TlsParameters *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)); }
-UPB_INLINE int32_t envoy_api_v2_auth_TlsParameters_tls_maximum_protocol_version(const envoy_api_v2_auth_TlsParameters *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
-UPB_INLINE upb_strview const* envoy_api_v2_auth_TlsParameters_cipher_suites(const envoy_api_v2_auth_TlsParameters *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(16, 16), len); }
-UPB_INLINE upb_strview const* envoy_api_v2_auth_TlsParameters_ecdh_curves(const envoy_api_v2_auth_TlsParameters *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(20, 24), len); }
-
-UPB_INLINE void envoy_api_v2_auth_TlsParameters_set_tls_minimum_protocol_version(envoy_api_v2_auth_TlsParameters *msg, int32_t value) {
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)) = value;
-}
-UPB_INLINE void envoy_api_v2_auth_TlsParameters_set_tls_maximum_protocol_version(envoy_api_v2_auth_TlsParameters *msg, int32_t value) {
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value;
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_TlsParameters_mutable_cipher_suites(envoy_api_v2_auth_TlsParameters *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 16), len);
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_TlsParameters_resize_cipher_suites(envoy_api_v2_auth_TlsParameters *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(16, 16), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool envoy_api_v2_auth_TlsParameters_add_cipher_suites(envoy_api_v2_auth_TlsParameters *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(16, 16), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_TlsParameters_mutable_ecdh_curves(envoy_api_v2_auth_TlsParameters *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 24), len);
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_TlsParameters_resize_ecdh_curves(envoy_api_v2_auth_TlsParameters *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 24), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool envoy_api_v2_auth_TlsParameters_add_ecdh_curves(envoy_api_v2_auth_TlsParameters *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 24), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
-}
-
-/* envoy.api.v2.auth.PrivateKeyProvider */
-
-UPB_INLINE envoy_api_v2_auth_PrivateKeyProvider *envoy_api_v2_auth_PrivateKeyProvider_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_PrivateKeyProvider *)upb_msg_new(&envoy_api_v2_auth_PrivateKeyProvider_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_PrivateKeyProvider *envoy_api_v2_auth_PrivateKeyProvider_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_PrivateKeyProvider *ret = envoy_api_v2_auth_PrivateKeyProvider_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_PrivateKeyProvider_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_PrivateKeyProvider_serialize(const envoy_api_v2_auth_PrivateKeyProvider *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_PrivateKeyProvider_msginit, arena, len);
-}
-
-typedef enum {
-  envoy_api_v2_auth_PrivateKeyProvider_config_type_config = 2,
-  envoy_api_v2_auth_PrivateKeyProvider_config_type_typed_config = 3,
-  envoy_api_v2_auth_PrivateKeyProvider_config_type_NOT_SET = 0
-} envoy_api_v2_auth_PrivateKeyProvider_config_type_oneofcases;
-UPB_INLINE envoy_api_v2_auth_PrivateKeyProvider_config_type_oneofcases envoy_api_v2_auth_PrivateKeyProvider_config_type_case(const envoy_api_v2_auth_PrivateKeyProvider* msg) { return (envoy_api_v2_auth_PrivateKeyProvider_config_type_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(12, 24)); }
-
-UPB_INLINE upb_strview envoy_api_v2_auth_PrivateKeyProvider_provider_name(const envoy_api_v2_auth_PrivateKeyProvider *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
-UPB_INLINE bool envoy_api_v2_auth_PrivateKeyProvider_has_config(const envoy_api_v2_auth_PrivateKeyProvider *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 2); }
-UPB_INLINE const struct google_protobuf_Struct* envoy_api_v2_auth_PrivateKeyProvider_config(const envoy_api_v2_auth_PrivateKeyProvider *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_Struct*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 2, NULL); }
-UPB_INLINE bool envoy_api_v2_auth_PrivateKeyProvider_has_typed_config(const envoy_api_v2_auth_PrivateKeyProvider *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 3); }
-UPB_INLINE const struct google_protobuf_Any* envoy_api_v2_auth_PrivateKeyProvider_typed_config(const envoy_api_v2_auth_PrivateKeyProvider *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_Any*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 3, NULL); }
-
-UPB_INLINE void envoy_api_v2_auth_PrivateKeyProvider_set_provider_name(envoy_api_v2_auth_PrivateKeyProvider *msg, upb_strview value) {
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
-}
-UPB_INLINE void envoy_api_v2_auth_PrivateKeyProvider_set_config(envoy_api_v2_auth_PrivateKeyProvider *msg, struct google_protobuf_Struct* value) {
-  UPB_WRITE_ONEOF(msg, struct google_protobuf_Struct*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 2);
-}
-UPB_INLINE struct google_protobuf_Struct* envoy_api_v2_auth_PrivateKeyProvider_mutable_config(envoy_api_v2_auth_PrivateKeyProvider *msg, upb_arena *arena) {
-  struct google_protobuf_Struct* sub = (struct google_protobuf_Struct*)envoy_api_v2_auth_PrivateKeyProvider_config(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_Struct*)upb_msg_new(&google_protobuf_Struct_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_PrivateKeyProvider_set_config(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_PrivateKeyProvider_set_typed_config(envoy_api_v2_auth_PrivateKeyProvider *msg, struct google_protobuf_Any* value) {
-  UPB_WRITE_ONEOF(msg, struct google_protobuf_Any*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 3);
-}
-UPB_INLINE struct google_protobuf_Any* envoy_api_v2_auth_PrivateKeyProvider_mutable_typed_config(envoy_api_v2_auth_PrivateKeyProvider *msg, upb_arena *arena) {
-  struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_api_v2_auth_PrivateKeyProvider_typed_config(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_Any*)upb_msg_new(&google_protobuf_Any_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_PrivateKeyProvider_set_typed_config(msg, sub);
-  }
-  return sub;
-}
-
-/* envoy.api.v2.auth.TlsCertificate */
-
-UPB_INLINE envoy_api_v2_auth_TlsCertificate *envoy_api_v2_auth_TlsCertificate_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_TlsCertificate *)upb_msg_new(&envoy_api_v2_auth_TlsCertificate_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_TlsCertificate *envoy_api_v2_auth_TlsCertificate_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_TlsCertificate *ret = envoy_api_v2_auth_TlsCertificate_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_TlsCertificate_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_TlsCertificate_serialize(const envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_TlsCertificate_msginit, arena, len);
-}
-
-UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_certificate_chain(const envoy_api_v2_auth_TlsCertificate *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(0, 0)); }
-UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_private_key(const envoy_api_v2_auth_TlsCertificate *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(4, 8)); }
-UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_password(const envoy_api_v2_auth_TlsCertificate *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(8, 16)); }
-UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_ocsp_staple(const envoy_api_v2_auth_TlsCertificate *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(12, 24)); }
-UPB_INLINE const struct envoy_api_v2_core_DataSource* const* envoy_api_v2_auth_TlsCertificate_signed_certificate_timestamp(const envoy_api_v2_auth_TlsCertificate *msg, size_t *len) { return (const struct envoy_api_v2_core_DataSource* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE const envoy_api_v2_auth_PrivateKeyProvider* envoy_api_v2_auth_TlsCertificate_private_key_provider(const envoy_api_v2_auth_TlsCertificate *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_auth_PrivateKeyProvider*, UPB_SIZE(16, 32)); }
-
-UPB_INLINE void envoy_api_v2_auth_TlsCertificate_set_certificate_chain(envoy_api_v2_auth_TlsCertificate *msg, struct envoy_api_v2_core_DataSource* value) {
-  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(0, 0)) = value;
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_mutable_certificate_chain(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
-  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_TlsCertificate_certificate_chain(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_TlsCertificate_set_certificate_chain(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_TlsCertificate_set_private_key(envoy_api_v2_auth_TlsCertificate *msg, struct envoy_api_v2_core_DataSource* value) {
-  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_mutable_private_key(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
-  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_TlsCertificate_private_key(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_TlsCertificate_set_private_key(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_TlsCertificate_set_password(envoy_api_v2_auth_TlsCertificate *msg, struct envoy_api_v2_core_DataSource* value) {
-  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(8, 16)) = value;
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_mutable_password(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
-  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_TlsCertificate_password(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_TlsCertificate_set_password(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_TlsCertificate_set_ocsp_staple(envoy_api_v2_auth_TlsCertificate *msg, struct envoy_api_v2_core_DataSource* value) {
-  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(12, 24)) = value;
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_mutable_ocsp_staple(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
-  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_TlsCertificate_ocsp_staple(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_TlsCertificate_set_ocsp_staple(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource** envoy_api_v2_auth_TlsCertificate_mutable_signed_certificate_timestamp(envoy_api_v2_auth_TlsCertificate *msg, size_t *len) {
-  return (struct envoy_api_v2_core_DataSource**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource** envoy_api_v2_auth_TlsCertificate_resize_signed_certificate_timestamp(envoy_api_v2_auth_TlsCertificate *msg, size_t len, upb_arena *arena) {
-  return (struct envoy_api_v2_core_DataSource**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_add_signed_certificate_timestamp(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
-  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_TlsCertificate_set_private_key_provider(envoy_api_v2_auth_TlsCertificate *msg, envoy_api_v2_auth_PrivateKeyProvider* value) {
-  UPB_FIELD_AT(msg, envoy_api_v2_auth_PrivateKeyProvider*, UPB_SIZE(16, 32)) = value;
-}
-UPB_INLINE struct envoy_api_v2_auth_PrivateKeyProvider* envoy_api_v2_auth_TlsCertificate_mutable_private_key_provider(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_PrivateKeyProvider* sub = (struct envoy_api_v2_auth_PrivateKeyProvider*)envoy_api_v2_auth_TlsCertificate_private_key_provider(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_PrivateKeyProvider*)upb_msg_new(&envoy_api_v2_auth_PrivateKeyProvider_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_TlsCertificate_set_private_key_provider(msg, sub);
-  }
-  return sub;
-}
-
-/* envoy.api.v2.auth.TlsSessionTicketKeys */
-
-UPB_INLINE envoy_api_v2_auth_TlsSessionTicketKeys *envoy_api_v2_auth_TlsSessionTicketKeys_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_TlsSessionTicketKeys *)upb_msg_new(&envoy_api_v2_auth_TlsSessionTicketKeys_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_TlsSessionTicketKeys *envoy_api_v2_auth_TlsSessionTicketKeys_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_TlsSessionTicketKeys *ret = envoy_api_v2_auth_TlsSessionTicketKeys_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_TlsSessionTicketKeys_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_TlsSessionTicketKeys_serialize(const envoy_api_v2_auth_TlsSessionTicketKeys *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_TlsSessionTicketKeys_msginit, arena, len);
-}
-
-UPB_INLINE const struct envoy_api_v2_core_DataSource* const* envoy_api_v2_auth_TlsSessionTicketKeys_keys(const envoy_api_v2_auth_TlsSessionTicketKeys *msg, size_t *len) { return (const struct envoy_api_v2_core_DataSource* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE struct envoy_api_v2_core_DataSource** envoy_api_v2_auth_TlsSessionTicketKeys_mutable_keys(envoy_api_v2_auth_TlsSessionTicketKeys *msg, size_t *len) {
-  return (struct envoy_api_v2_core_DataSource**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource** envoy_api_v2_auth_TlsSessionTicketKeys_resize_keys(envoy_api_v2_auth_TlsSessionTicketKeys *msg, size_t len, upb_arena *arena) {
-  return (struct envoy_api_v2_core_DataSource**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsSessionTicketKeys_add_keys(envoy_api_v2_auth_TlsSessionTicketKeys *msg, upb_arena *arena) {
-  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* envoy.api.v2.auth.CertificateValidationContext */
-
-UPB_INLINE envoy_api_v2_auth_CertificateValidationContext *envoy_api_v2_auth_CertificateValidationContext_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_CertificateValidationContext *)upb_msg_new(&envoy_api_v2_auth_CertificateValidationContext_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_CertificateValidationContext *envoy_api_v2_auth_CertificateValidationContext_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_CertificateValidationContext *ret = envoy_api_v2_auth_CertificateValidationContext_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_CertificateValidationContext_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_CertificateValidationContext_serialize(const envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_CertificateValidationContext_msginit, arena, len);
-}
-
-UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_CertificateValidationContext_trusted_ca(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(12, 16)); }
-UPB_INLINE upb_strview const* envoy_api_v2_auth_CertificateValidationContext_verify_certificate_hash(const envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 48), len); }
-UPB_INLINE upb_strview const* envoy_api_v2_auth_CertificateValidationContext_verify_certificate_spki(const envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(32, 56), len); }
-UPB_INLINE upb_strview const* envoy_api_v2_auth_CertificateValidationContext_verify_subject_alt_name(const envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 64), len); }
-UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_auth_CertificateValidationContext_require_ocsp_staple(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(16, 24)); }
-UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_auth_CertificateValidationContext_require_signed_certificate_timestamp(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(20, 32)); }
-UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_CertificateValidationContext_crl(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(24, 40)); }
-UPB_INLINE bool envoy_api_v2_auth_CertificateValidationContext_allow_expired_certificate(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(8, 8)); }
-UPB_INLINE const struct envoy_type_matcher_StringMatcher* const* envoy_api_v2_auth_CertificateValidationContext_match_subject_alt_names(const envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) { return (const struct envoy_type_matcher_StringMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(40, 72), len); }
-UPB_INLINE int32_t envoy_api_v2_auth_CertificateValidationContext_trust_chain_verification(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)); }
-
-UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_trusted_ca(envoy_api_v2_auth_CertificateValidationContext *msg, struct envoy_api_v2_core_DataSource* value) {
-  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(12, 16)) = value;
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_CertificateValidationContext_mutable_trusted_ca(envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_CertificateValidationContext_trusted_ca(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_CertificateValidationContext_set_trusted_ca(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_mutable_verify_certificate_hash(envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 48), len);
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_resize_verify_certificate_hash(envoy_api_v2_auth_CertificateValidationContext *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(28, 48), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool envoy_api_v2_auth_CertificateValidationContext_add_verify_certificate_hash(envoy_api_v2_auth_CertificateValidationContext *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(28, 48), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_mutable_verify_certificate_spki(envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 56), len);
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_resize_verify_certificate_spki(envoy_api_v2_auth_CertificateValidationContext *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(32, 56), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool envoy_api_v2_auth_CertificateValidationContext_add_verify_certificate_spki(envoy_api_v2_auth_CertificateValidationContext *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(32, 56), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_mutable_verify_subject_alt_name(envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 64), len);
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_resize_verify_subject_alt_name(envoy_api_v2_auth_CertificateValidationContext *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(36, 64), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool envoy_api_v2_auth_CertificateValidationContext_add_verify_subject_alt_name(envoy_api_v2_auth_CertificateValidationContext *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(36, 64), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
-}
-UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_require_ocsp_staple(envoy_api_v2_auth_CertificateValidationContext *msg, struct google_protobuf_BoolValue* value) {
-  UPB_FIELD_AT(msg, struct google_protobuf_BoolValue*, UPB_SIZE(16, 24)) = value;
-}
-UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_auth_CertificateValidationContext_mutable_require_ocsp_staple(envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena) {
-  struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_api_v2_auth_CertificateValidationContext_require_ocsp_staple(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_BoolValue*)upb_msg_new(&google_protobuf_BoolValue_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_CertificateValidationContext_set_require_ocsp_staple(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_require_signed_certificate_timestamp(envoy_api_v2_auth_CertificateValidationContext *msg, struct google_protobuf_BoolValue* value) {
-  UPB_FIELD_AT(msg, struct google_protobuf_BoolValue*, UPB_SIZE(20, 32)) = value;
-}
-UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_auth_CertificateValidationContext_mutable_require_signed_certificate_timestamp(envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena) {
-  struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_api_v2_auth_CertificateValidationContext_require_signed_certificate_timestamp(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_BoolValue*)upb_msg_new(&google_protobuf_BoolValue_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_CertificateValidationContext_set_require_signed_certificate_timestamp(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_crl(envoy_api_v2_auth_CertificateValidationContext *msg, struct envoy_api_v2_core_DataSource* value) {
-  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(24, 40)) = value;
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_CertificateValidationContext_mutable_crl(envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_CertificateValidationContext_crl(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_CertificateValidationContext_set_crl(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_allow_expired_certificate(envoy_api_v2_auth_CertificateValidationContext *msg, bool value) {
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(8, 8)) = value;
-}
-UPB_INLINE struct envoy_type_matcher_StringMatcher** envoy_api_v2_auth_CertificateValidationContext_mutable_match_subject_alt_names(envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) {
-  return (struct envoy_type_matcher_StringMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 72), len);
-}
-UPB_INLINE struct envoy_type_matcher_StringMatcher** envoy_api_v2_auth_CertificateValidationContext_resize_match_subject_alt_names(envoy_api_v2_auth_CertificateValidationContext *msg, size_t len, upb_arena *arena) {
-  return (struct envoy_type_matcher_StringMatcher**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 72), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct envoy_type_matcher_StringMatcher* envoy_api_v2_auth_CertificateValidationContext_add_match_subject_alt_names(envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena) {
-  struct envoy_type_matcher_StringMatcher* sub = (struct envoy_type_matcher_StringMatcher*)upb_msg_new(&envoy_type_matcher_StringMatcher_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(40, 72), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_trust_chain_verification(envoy_api_v2_auth_CertificateValidationContext *msg, int32_t value) {
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)) = value;
-}
-
-/* envoy.api.v2.auth.CommonTlsContext */
-
-UPB_INLINE envoy_api_v2_auth_CommonTlsContext *envoy_api_v2_auth_CommonTlsContext_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_CommonTlsContext *)upb_msg_new(&envoy_api_v2_auth_CommonTlsContext_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_CommonTlsContext *envoy_api_v2_auth_CommonTlsContext_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_CommonTlsContext *ret = envoy_api_v2_auth_CommonTlsContext_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_CommonTlsContext_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_CommonTlsContext_serialize(const envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_CommonTlsContext_msginit, arena, len);
-}
-
-typedef enum {
-  envoy_api_v2_auth_CommonTlsContext_validation_context_type_validation_context = 3,
-  envoy_api_v2_auth_CommonTlsContext_validation_context_type_validation_context_sds_secret_config = 7,
-  envoy_api_v2_auth_CommonTlsContext_validation_context_type_combined_validation_context = 8,
-  envoy_api_v2_auth_CommonTlsContext_validation_context_type_NOT_SET = 0
-} envoy_api_v2_auth_CommonTlsContext_validation_context_type_oneofcases;
-UPB_INLINE envoy_api_v2_auth_CommonTlsContext_validation_context_type_oneofcases envoy_api_v2_auth_CommonTlsContext_validation_context_type_case(const envoy_api_v2_auth_CommonTlsContext* msg) { return (envoy_api_v2_auth_CommonTlsContext_validation_context_type_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(20, 40)); }
-
-UPB_INLINE const envoy_api_v2_auth_TlsParameters* envoy_api_v2_auth_CommonTlsContext_tls_params(const envoy_api_v2_auth_CommonTlsContext *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_auth_TlsParameters*, UPB_SIZE(0, 0)); }
-UPB_INLINE const envoy_api_v2_auth_TlsCertificate* const* envoy_api_v2_auth_CommonTlsContext_tls_certificates(const envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) { return (const envoy_api_v2_auth_TlsCertificate* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-UPB_INLINE bool envoy_api_v2_auth_CommonTlsContext_has_validation_context(const envoy_api_v2_auth_CommonTlsContext *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 3); }
-UPB_INLINE const envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_validation_context(const envoy_api_v2_auth_CommonTlsContext *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 3, NULL); }
-UPB_INLINE upb_strview const* envoy_api_v2_auth_CommonTlsContext_alpn_protocols(const envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); }
-UPB_INLINE const envoy_api_v2_auth_SdsSecretConfig* const* envoy_api_v2_auth_CommonTlsContext_tls_certificate_sds_secret_configs(const envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) { return (const envoy_api_v2_auth_SdsSecretConfig* const*)_upb_array_accessor(msg, UPB_SIZE(12, 24), len); }
-UPB_INLINE bool envoy_api_v2_auth_CommonTlsContext_has_validation_context_sds_secret_config(const envoy_api_v2_auth_CommonTlsContext *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 7); }
-UPB_INLINE const envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_CommonTlsContext_validation_context_sds_secret_config(const envoy_api_v2_auth_CommonTlsContext *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 7, NULL); }
-UPB_INLINE bool envoy_api_v2_auth_CommonTlsContext_has_combined_validation_context(const envoy_api_v2_auth_CommonTlsContext *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 8); }
-UPB_INLINE const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_combined_validation_context(const envoy_api_v2_auth_CommonTlsContext *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 8, NULL); }
-
-UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_set_tls_params(envoy_api_v2_auth_CommonTlsContext *msg, envoy_api_v2_auth_TlsParameters* value) {
-  UPB_FIELD_AT(msg, envoy_api_v2_auth_TlsParameters*, UPB_SIZE(0, 0)) = value;
-}
-UPB_INLINE struct envoy_api_v2_auth_TlsParameters* envoy_api_v2_auth_CommonTlsContext_mutable_tls_params(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_TlsParameters* sub = (struct envoy_api_v2_auth_TlsParameters*)envoy_api_v2_auth_CommonTlsContext_tls_params(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_TlsParameters*)upb_msg_new(&envoy_api_v2_auth_TlsParameters_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_CommonTlsContext_set_tls_params(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE envoy_api_v2_auth_TlsCertificate** envoy_api_v2_auth_CommonTlsContext_mutable_tls_certificates(envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) {
-  return (envoy_api_v2_auth_TlsCertificate**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE envoy_api_v2_auth_TlsCertificate** envoy_api_v2_auth_CommonTlsContext_resize_tls_certificates(envoy_api_v2_auth_CommonTlsContext *msg, size_t len, upb_arena *arena) {
-  return (envoy_api_v2_auth_TlsCertificate**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct envoy_api_v2_auth_TlsCertificate* envoy_api_v2_auth_CommonTlsContext_add_tls_certificates(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_TlsCertificate* sub = (struct envoy_api_v2_auth_TlsCertificate*)upb_msg_new(&envoy_api_v2_auth_TlsCertificate_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_set_validation_context(envoy_api_v2_auth_CommonTlsContext *msg, envoy_api_v2_auth_CertificateValidationContext* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 3);
-}
-UPB_INLINE struct envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_mutable_validation_context(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_CertificateValidationContext* sub = (struct envoy_api_v2_auth_CertificateValidationContext*)envoy_api_v2_auth_CommonTlsContext_validation_context(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_CertificateValidationContext*)upb_msg_new(&envoy_api_v2_auth_CertificateValidationContext_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_CommonTlsContext_set_validation_context(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_CommonTlsContext_mutable_alpn_protocols(envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len);
-}
-UPB_INLINE upb_strview* envoy_api_v2_auth_CommonTlsContext_resize_alpn_protocols(envoy_api_v2_auth_CommonTlsContext *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(8, 16), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool envoy_api_v2_auth_CommonTlsContext_add_alpn_protocols(envoy_api_v2_auth_CommonTlsContext *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(8, 16), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
-}
-UPB_INLINE envoy_api_v2_auth_SdsSecretConfig** envoy_api_v2_auth_CommonTlsContext_mutable_tls_certificate_sds_secret_configs(envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) {
-  return (envoy_api_v2_auth_SdsSecretConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 24), len);
-}
-UPB_INLINE envoy_api_v2_auth_SdsSecretConfig** envoy_api_v2_auth_CommonTlsContext_resize_tls_certificate_sds_secret_configs(envoy_api_v2_auth_CommonTlsContext *msg, size_t len, upb_arena *arena) {
-  return (envoy_api_v2_auth_SdsSecretConfig**)_upb_array_resize_accessor(msg, UPB_SIZE(12, 24), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_CommonTlsContext_add_tls_certificate_sds_secret_configs(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_SdsSecretConfig* sub = (struct envoy_api_v2_auth_SdsSecretConfig*)upb_msg_new(&envoy_api_v2_auth_SdsSecretConfig_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(12, 24), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_set_validation_context_sds_secret_config(envoy_api_v2_auth_CommonTlsContext *msg, envoy_api_v2_auth_SdsSecretConfig* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 7);
-}
-UPB_INLINE struct envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_CommonTlsContext_mutable_validation_context_sds_secret_config(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_SdsSecretConfig* sub = (struct envoy_api_v2_auth_SdsSecretConfig*)envoy_api_v2_auth_CommonTlsContext_validation_context_sds_secret_config(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_SdsSecretConfig*)upb_msg_new(&envoy_api_v2_auth_SdsSecretConfig_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_CommonTlsContext_set_validation_context_sds_secret_config(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_set_combined_validation_context(envoy_api_v2_auth_CommonTlsContext *msg, envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 8);
-}
-UPB_INLINE struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_mutable_combined_validation_context(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext* sub = (struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext*)envoy_api_v2_auth_CommonTlsContext_combined_validation_context(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext*)upb_msg_new(&envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_CommonTlsContext_set_combined_validation_context(msg, sub);
-  }
-  return sub;
-}
-
-/* envoy.api.v2.auth.CommonTlsContext.CombinedCertificateValidationContext */
-
-UPB_INLINE envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *)upb_msg_new(&envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *ret = envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_serialize(const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit, arena, len);
-}
-
-UPB_INLINE const envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_default_validation_context(const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(0, 0)); }
-UPB_INLINE const envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_validation_context_sds_secret_config(const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(4, 8)); }
-
-UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_set_default_validation_context(envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg, envoy_api_v2_auth_CertificateValidationContext* value) {
-  UPB_FIELD_AT(msg, envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(0, 0)) = value;
-}
-UPB_INLINE struct envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_mutable_default_validation_context(envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_CertificateValidationContext* sub = (struct envoy_api_v2_auth_CertificateValidationContext*)envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_default_validation_context(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_CertificateValidationContext*)upb_msg_new(&envoy_api_v2_auth_CertificateValidationContext_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_set_default_validation_context(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_set_validation_context_sds_secret_config(envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg, envoy_api_v2_auth_SdsSecretConfig* value) {
-  UPB_FIELD_AT(msg, envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE struct envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_mutable_validation_context_sds_secret_config(envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_SdsSecretConfig* sub = (struct envoy_api_v2_auth_SdsSecretConfig*)envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_validation_context_sds_secret_config(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_SdsSecretConfig*)upb_msg_new(&envoy_api_v2_auth_SdsSecretConfig_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_set_validation_context_sds_secret_config(msg, sub);
-  }
-  return sub;
-}
-
-/* envoy.api.v2.auth.UpstreamTlsContext */
-
-UPB_INLINE envoy_api_v2_auth_UpstreamTlsContext *envoy_api_v2_auth_UpstreamTlsContext_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_UpstreamTlsContext *)upb_msg_new(&envoy_api_v2_auth_UpstreamTlsContext_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_UpstreamTlsContext *envoy_api_v2_auth_UpstreamTlsContext_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_UpstreamTlsContext *ret = envoy_api_v2_auth_UpstreamTlsContext_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_UpstreamTlsContext_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_UpstreamTlsContext_serialize(const envoy_api_v2_auth_UpstreamTlsContext *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_UpstreamTlsContext_msginit, arena, len);
-}
-
-UPB_INLINE const envoy_api_v2_auth_CommonTlsContext* envoy_api_v2_auth_UpstreamTlsContext_common_tls_context(const envoy_api_v2_auth_UpstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_auth_CommonTlsContext*, UPB_SIZE(12, 24)); }
-UPB_INLINE upb_strview envoy_api_v2_auth_UpstreamTlsContext_sni(const envoy_api_v2_auth_UpstreamTlsContext *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); }
-UPB_INLINE bool envoy_api_v2_auth_UpstreamTlsContext_allow_renegotiation(const envoy_api_v2_auth_UpstreamTlsContext *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)); }
-UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_auth_UpstreamTlsContext_max_session_keys(const envoy_api_v2_auth_UpstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(16, 32)); }
-
-UPB_INLINE void envoy_api_v2_auth_UpstreamTlsContext_set_common_tls_context(envoy_api_v2_auth_UpstreamTlsContext *msg, envoy_api_v2_auth_CommonTlsContext* value) {
-  UPB_FIELD_AT(msg, envoy_api_v2_auth_CommonTlsContext*, UPB_SIZE(12, 24)) = value;
-}
-UPB_INLINE struct envoy_api_v2_auth_CommonTlsContext* envoy_api_v2_auth_UpstreamTlsContext_mutable_common_tls_context(envoy_api_v2_auth_UpstreamTlsContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_CommonTlsContext* sub = (struct envoy_api_v2_auth_CommonTlsContext*)envoy_api_v2_auth_UpstreamTlsContext_common_tls_context(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_CommonTlsContext*)upb_msg_new(&envoy_api_v2_auth_CommonTlsContext_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_UpstreamTlsContext_set_common_tls_context(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_UpstreamTlsContext_set_sni(envoy_api_v2_auth_UpstreamTlsContext *msg, upb_strview value) {
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE void envoy_api_v2_auth_UpstreamTlsContext_set_allow_renegotiation(envoy_api_v2_auth_UpstreamTlsContext *msg, bool value) {
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)) = value;
-}
-UPB_INLINE void envoy_api_v2_auth_UpstreamTlsContext_set_max_session_keys(envoy_api_v2_auth_UpstreamTlsContext *msg, struct google_protobuf_UInt32Value* value) {
-  UPB_FIELD_AT(msg, struct google_protobuf_UInt32Value*, UPB_SIZE(16, 32)) = value;
-}
-UPB_INLINE struct google_protobuf_UInt32Value* envoy_api_v2_auth_UpstreamTlsContext_mutable_max_session_keys(envoy_api_v2_auth_UpstreamTlsContext *msg, upb_arena *arena) {
-  struct google_protobuf_UInt32Value* sub = (struct google_protobuf_UInt32Value*)envoy_api_v2_auth_UpstreamTlsContext_max_session_keys(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_UInt32Value*)upb_msg_new(&google_protobuf_UInt32Value_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_UpstreamTlsContext_set_max_session_keys(msg, sub);
-  }
-  return sub;
-}
-
-/* envoy.api.v2.auth.DownstreamTlsContext */
-
-UPB_INLINE envoy_api_v2_auth_DownstreamTlsContext *envoy_api_v2_auth_DownstreamTlsContext_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_DownstreamTlsContext *)upb_msg_new(&envoy_api_v2_auth_DownstreamTlsContext_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_DownstreamTlsContext *envoy_api_v2_auth_DownstreamTlsContext_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_DownstreamTlsContext *ret = envoy_api_v2_auth_DownstreamTlsContext_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_DownstreamTlsContext_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_DownstreamTlsContext_serialize(const envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_DownstreamTlsContext_msginit, arena, len);
-}
-
-typedef enum {
-  envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_session_ticket_keys = 4,
-  envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_session_ticket_keys_sds_secret_config = 5,
-  envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_NOT_SET = 0
-} envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_oneofcases;
-UPB_INLINE envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_oneofcases envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_case(const envoy_api_v2_auth_DownstreamTlsContext* msg) { return (envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(20, 40)); }
-
-UPB_INLINE const envoy_api_v2_auth_CommonTlsContext* envoy_api_v2_auth_DownstreamTlsContext_common_tls_context(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_auth_CommonTlsContext*, UPB_SIZE(0, 0)); }
-UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_auth_DownstreamTlsContext_require_client_certificate(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(4, 8)); }
-UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_auth_DownstreamTlsContext_require_sni(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(8, 16)); }
-UPB_INLINE bool envoy_api_v2_auth_DownstreamTlsContext_has_session_ticket_keys(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 4); }
-UPB_INLINE const envoy_api_v2_auth_TlsSessionTicketKeys* envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_auth_TlsSessionTicketKeys*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 4, NULL); }
-UPB_INLINE bool envoy_api_v2_auth_DownstreamTlsContext_has_session_ticket_keys_sds_secret_config(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 5); }
-UPB_INLINE const envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_sds_secret_config(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 5, NULL); }
-UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_auth_DownstreamTlsContext_session_timeout(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(12, 24)); }
-
-UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_common_tls_context(envoy_api_v2_auth_DownstreamTlsContext *msg, envoy_api_v2_auth_CommonTlsContext* value) {
-  UPB_FIELD_AT(msg, envoy_api_v2_auth_CommonTlsContext*, UPB_SIZE(0, 0)) = value;
-}
-UPB_INLINE struct envoy_api_v2_auth_CommonTlsContext* envoy_api_v2_auth_DownstreamTlsContext_mutable_common_tls_context(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_CommonTlsContext* sub = (struct envoy_api_v2_auth_CommonTlsContext*)envoy_api_v2_auth_DownstreamTlsContext_common_tls_context(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_CommonTlsContext*)upb_msg_new(&envoy_api_v2_auth_CommonTlsContext_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_DownstreamTlsContext_set_common_tls_context(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_require_client_certificate(envoy_api_v2_auth_DownstreamTlsContext *msg, struct google_protobuf_BoolValue* value) {
-  UPB_FIELD_AT(msg, struct google_protobuf_BoolValue*, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_auth_DownstreamTlsContext_mutable_require_client_certificate(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
-  struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_api_v2_auth_DownstreamTlsContext_require_client_certificate(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_BoolValue*)upb_msg_new(&google_protobuf_BoolValue_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_DownstreamTlsContext_set_require_client_certificate(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_require_sni(envoy_api_v2_auth_DownstreamTlsContext *msg, struct google_protobuf_BoolValue* value) {
-  UPB_FIELD_AT(msg, struct google_protobuf_BoolValue*, UPB_SIZE(8, 16)) = value;
-}
-UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_auth_DownstreamTlsContext_mutable_require_sni(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
-  struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_api_v2_auth_DownstreamTlsContext_require_sni(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_BoolValue*)upb_msg_new(&google_protobuf_BoolValue_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_DownstreamTlsContext_set_require_sni(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_session_ticket_keys(envoy_api_v2_auth_DownstreamTlsContext *msg, envoy_api_v2_auth_TlsSessionTicketKeys* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_auth_TlsSessionTicketKeys*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 4);
-}
-UPB_INLINE struct envoy_api_v2_auth_TlsSessionTicketKeys* envoy_api_v2_auth_DownstreamTlsContext_mutable_session_ticket_keys(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_TlsSessionTicketKeys* sub = (struct envoy_api_v2_auth_TlsSessionTicketKeys*)envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_TlsSessionTicketKeys*)upb_msg_new(&envoy_api_v2_auth_TlsSessionTicketKeys_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_DownstreamTlsContext_set_session_ticket_keys(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_session_ticket_keys_sds_secret_config(envoy_api_v2_auth_DownstreamTlsContext *msg, envoy_api_v2_auth_SdsSecretConfig* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 5);
-}
-UPB_INLINE struct envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_DownstreamTlsContext_mutable_session_ticket_keys_sds_secret_config(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_SdsSecretConfig* sub = (struct envoy_api_v2_auth_SdsSecretConfig*)envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_sds_secret_config(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_SdsSecretConfig*)upb_msg_new(&envoy_api_v2_auth_SdsSecretConfig_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_DownstreamTlsContext_set_session_ticket_keys_sds_secret_config(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_session_timeout(envoy_api_v2_auth_DownstreamTlsContext *msg, struct google_protobuf_Duration* value) {
-  UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(12, 24)) = value;
-}
-UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_auth_DownstreamTlsContext_mutable_session_timeout(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
-  struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_api_v2_auth_DownstreamTlsContext_session_timeout(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_Duration*)upb_msg_new(&google_protobuf_Duration_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_DownstreamTlsContext_set_session_timeout(msg, sub);
-  }
-  return sub;
-}
-
-/* envoy.api.v2.auth.GenericSecret */
-
-UPB_INLINE envoy_api_v2_auth_GenericSecret *envoy_api_v2_auth_GenericSecret_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_GenericSecret *)upb_msg_new(&envoy_api_v2_auth_GenericSecret_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_GenericSecret *envoy_api_v2_auth_GenericSecret_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_GenericSecret *ret = envoy_api_v2_auth_GenericSecret_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_GenericSecret_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_GenericSecret_serialize(const envoy_api_v2_auth_GenericSecret *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_GenericSecret_msginit, arena, len);
-}
-
-UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_GenericSecret_secret(const envoy_api_v2_auth_GenericSecret *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(0, 0)); }
-
-UPB_INLINE void envoy_api_v2_auth_GenericSecret_set_secret(envoy_api_v2_auth_GenericSecret *msg, struct envoy_api_v2_core_DataSource* value) {
-  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(0, 0)) = value;
-}
-UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_GenericSecret_mutable_secret(envoy_api_v2_auth_GenericSecret *msg, upb_arena *arena) {
-  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_GenericSecret_secret(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_GenericSecret_set_secret(msg, sub);
-  }
-  return sub;
-}
-
-/* envoy.api.v2.auth.SdsSecretConfig */
-
-UPB_INLINE envoy_api_v2_auth_SdsSecretConfig *envoy_api_v2_auth_SdsSecretConfig_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_SdsSecretConfig *)upb_msg_new(&envoy_api_v2_auth_SdsSecretConfig_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_SdsSecretConfig *envoy_api_v2_auth_SdsSecretConfig_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_SdsSecretConfig *ret = envoy_api_v2_auth_SdsSecretConfig_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_SdsSecretConfig_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_SdsSecretConfig_serialize(const envoy_api_v2_auth_SdsSecretConfig *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_SdsSecretConfig_msginit, arena, len);
-}
-
-UPB_INLINE upb_strview envoy_api_v2_auth_SdsSecretConfig_name(const envoy_api_v2_auth_SdsSecretConfig *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
-UPB_INLINE const struct envoy_api_v2_core_ConfigSource* envoy_api_v2_auth_SdsSecretConfig_sds_config(const envoy_api_v2_auth_SdsSecretConfig *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_ConfigSource*, UPB_SIZE(8, 16)); }
-
-UPB_INLINE void envoy_api_v2_auth_SdsSecretConfig_set_name(envoy_api_v2_auth_SdsSecretConfig *msg, upb_strview value) {
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
-}
-UPB_INLINE void envoy_api_v2_auth_SdsSecretConfig_set_sds_config(envoy_api_v2_auth_SdsSecretConfig *msg, struct envoy_api_v2_core_ConfigSource* value) {
-  UPB_FIELD_AT(msg, struct envoy_api_v2_core_ConfigSource*, UPB_SIZE(8, 16)) = value;
-}
-UPB_INLINE struct envoy_api_v2_core_ConfigSource* envoy_api_v2_auth_SdsSecretConfig_mutable_sds_config(envoy_api_v2_auth_SdsSecretConfig *msg, upb_arena *arena) {
-  struct envoy_api_v2_core_ConfigSource* sub = (struct envoy_api_v2_core_ConfigSource*)envoy_api_v2_auth_SdsSecretConfig_sds_config(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_core_ConfigSource*)upb_msg_new(&envoy_api_v2_core_ConfigSource_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_SdsSecretConfig_set_sds_config(msg, sub);
-  }
-  return sub;
-}
-
-/* envoy.api.v2.auth.Secret */
-
-UPB_INLINE envoy_api_v2_auth_Secret *envoy_api_v2_auth_Secret_new(upb_arena *arena) {
-  return (envoy_api_v2_auth_Secret *)upb_msg_new(&envoy_api_v2_auth_Secret_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_auth_Secret *envoy_api_v2_auth_Secret_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_auth_Secret *ret = envoy_api_v2_auth_Secret_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_Secret_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_auth_Secret_serialize(const envoy_api_v2_auth_Secret *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_auth_Secret_msginit, arena, len);
-}
-
-typedef enum {
-  envoy_api_v2_auth_Secret_type_tls_certificate = 2,
-  envoy_api_v2_auth_Secret_type_session_ticket_keys = 3,
-  envoy_api_v2_auth_Secret_type_validation_context = 4,
-  envoy_api_v2_auth_Secret_type_generic_secret = 5,
-  envoy_api_v2_auth_Secret_type_NOT_SET = 0
-} envoy_api_v2_auth_Secret_type_oneofcases;
-UPB_INLINE envoy_api_v2_auth_Secret_type_oneofcases envoy_api_v2_auth_Secret_type_case(const envoy_api_v2_auth_Secret* msg) { return (envoy_api_v2_auth_Secret_type_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(12, 24)); }
-
-UPB_INLINE upb_strview envoy_api_v2_auth_Secret_name(const envoy_api_v2_auth_Secret *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
-UPB_INLINE bool envoy_api_v2_auth_Secret_has_tls_certificate(const envoy_api_v2_auth_Secret *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 2); }
-UPB_INLINE const envoy_api_v2_auth_TlsCertificate* envoy_api_v2_auth_Secret_tls_certificate(const envoy_api_v2_auth_Secret *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_auth_TlsCertificate*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 2, NULL); }
-UPB_INLINE bool envoy_api_v2_auth_Secret_has_session_ticket_keys(const envoy_api_v2_auth_Secret *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 3); }
-UPB_INLINE const envoy_api_v2_auth_TlsSessionTicketKeys* envoy_api_v2_auth_Secret_session_ticket_keys(const envoy_api_v2_auth_Secret *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_auth_TlsSessionTicketKeys*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 3, NULL); }
-UPB_INLINE bool envoy_api_v2_auth_Secret_has_validation_context(const envoy_api_v2_auth_Secret *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 4); }
-UPB_INLINE const envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_Secret_validation_context(const envoy_api_v2_auth_Secret *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 4, NULL); }
-UPB_INLINE bool envoy_api_v2_auth_Secret_has_generic_secret(const envoy_api_v2_auth_Secret *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 5); }
-UPB_INLINE const envoy_api_v2_auth_GenericSecret* envoy_api_v2_auth_Secret_generic_secret(const envoy_api_v2_auth_Secret *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_auth_GenericSecret*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 5, NULL); }
-
-UPB_INLINE void envoy_api_v2_auth_Secret_set_name(envoy_api_v2_auth_Secret *msg, upb_strview value) {
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
-}
-UPB_INLINE void envoy_api_v2_auth_Secret_set_tls_certificate(envoy_api_v2_auth_Secret *msg, envoy_api_v2_auth_TlsCertificate* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_auth_TlsCertificate*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 2);
-}
-UPB_INLINE struct envoy_api_v2_auth_TlsCertificate* envoy_api_v2_auth_Secret_mutable_tls_certificate(envoy_api_v2_auth_Secret *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_TlsCertificate* sub = (struct envoy_api_v2_auth_TlsCertificate*)envoy_api_v2_auth_Secret_tls_certificate(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_TlsCertificate*)upb_msg_new(&envoy_api_v2_auth_TlsCertificate_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_Secret_set_tls_certificate(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_Secret_set_session_ticket_keys(envoy_api_v2_auth_Secret *msg, envoy_api_v2_auth_TlsSessionTicketKeys* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_auth_TlsSessionTicketKeys*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 3);
-}
-UPB_INLINE struct envoy_api_v2_auth_TlsSessionTicketKeys* envoy_api_v2_auth_Secret_mutable_session_ticket_keys(envoy_api_v2_auth_Secret *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_TlsSessionTicketKeys* sub = (struct envoy_api_v2_auth_TlsSessionTicketKeys*)envoy_api_v2_auth_Secret_session_ticket_keys(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_TlsSessionTicketKeys*)upb_msg_new(&envoy_api_v2_auth_TlsSessionTicketKeys_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_Secret_set_session_ticket_keys(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_Secret_set_validation_context(envoy_api_v2_auth_Secret *msg, envoy_api_v2_auth_CertificateValidationContext* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 4);
-}
-UPB_INLINE struct envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_Secret_mutable_validation_context(envoy_api_v2_auth_Secret *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_CertificateValidationContext* sub = (struct envoy_api_v2_auth_CertificateValidationContext*)envoy_api_v2_auth_Secret_validation_context(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_CertificateValidationContext*)upb_msg_new(&envoy_api_v2_auth_CertificateValidationContext_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_Secret_set_validation_context(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void envoy_api_v2_auth_Secret_set_generic_secret(envoy_api_v2_auth_Secret *msg, envoy_api_v2_auth_GenericSecret* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_auth_GenericSecret*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 5);
-}
-UPB_INLINE struct envoy_api_v2_auth_GenericSecret* envoy_api_v2_auth_Secret_mutable_generic_secret(envoy_api_v2_auth_Secret *msg, upb_arena *arena) {
-  struct envoy_api_v2_auth_GenericSecret* sub = (struct envoy_api_v2_auth_GenericSecret*)envoy_api_v2_auth_Secret_generic_secret(msg);
-  if (sub == NULL) {
-    sub = (struct envoy_api_v2_auth_GenericSecret*)upb_msg_new(&envoy_api_v2_auth_GenericSecret_msginit, arena);
-    if (!sub) return NULL;
-    envoy_api_v2_auth_Secret_set_generic_secret(msg, sub);
-  }
-  return sub;
-}
 
 #ifdef __cplusplus
 }  /* extern "C" */
diff --git a/src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c b/src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c
new file mode 100644 (file)
index 0000000..9903593
--- /dev/null
@@ -0,0 +1,114 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/auth/common.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg.h"
+#include "envoy/api/v2/auth/common.upb.h"
+#include "envoy/api/v2/core/base.upb.h"
+#include "envoy/type/matcher/string.upb.h"
+#include "google/protobuf/any.upb.h"
+#include "google/protobuf/struct.upb.h"
+#include "google/protobuf/wrappers.upb.h"
+#include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/sensitive.upb.h"
+#include "udpa/annotations/status.upb.h"
+#include "validate/validate.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout_field envoy_api_v2_auth_TlsParameters__fields[4] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 14, 1},
+  {2, UPB_SIZE(8, 8), 0, 0, 14, 1},
+  {3, UPB_SIZE(16, 16), 0, 0, 9, 3},
+  {4, UPB_SIZE(20, 24), 0, 0, 9, 3},
+};
+
+const upb_msglayout envoy_api_v2_auth_TlsParameters_msginit = {
+  NULL,
+  &envoy_api_v2_auth_TlsParameters__fields[0],
+  UPB_SIZE(24, 32), 4, false,
+};
+
+static const upb_msglayout *const envoy_api_v2_auth_PrivateKeyProvider_submsgs[2] = {
+  &google_protobuf_Any_msginit,
+  &google_protobuf_Struct_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_auth_PrivateKeyProvider__fields[3] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 9, 1},
+  {2, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 1, 11, 1},
+  {3, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_auth_PrivateKeyProvider_msginit = {
+  &envoy_api_v2_auth_PrivateKeyProvider_submsgs[0],
+  &envoy_api_v2_auth_PrivateKeyProvider__fields[0],
+  UPB_SIZE(16, 32), 3, false,
+};
+
+static const upb_msglayout *const envoy_api_v2_auth_TlsCertificate_submsgs[6] = {
+  &envoy_api_v2_auth_PrivateKeyProvider_msginit,
+  &envoy_api_v2_core_DataSource_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_auth_TlsCertificate__fields[6] = {
+  {1, UPB_SIZE(0, 0), 0, 1, 11, 1},
+  {2, UPB_SIZE(4, 8), 0, 1, 11, 1},
+  {3, UPB_SIZE(8, 16), 0, 1, 11, 1},
+  {4, UPB_SIZE(12, 24), 0, 1, 11, 1},
+  {5, UPB_SIZE(20, 40), 0, 1, 11, 3},
+  {6, UPB_SIZE(16, 32), 0, 0, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_auth_TlsCertificate_msginit = {
+  &envoy_api_v2_auth_TlsCertificate_submsgs[0],
+  &envoy_api_v2_auth_TlsCertificate__fields[0],
+  UPB_SIZE(24, 48), 6, false,
+};
+
+static const upb_msglayout *const envoy_api_v2_auth_TlsSessionTicketKeys_submsgs[1] = {
+  &envoy_api_v2_core_DataSource_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_auth_TlsSessionTicketKeys__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout envoy_api_v2_auth_TlsSessionTicketKeys_msginit = {
+  &envoy_api_v2_auth_TlsSessionTicketKeys_submsgs[0],
+  &envoy_api_v2_auth_TlsSessionTicketKeys__fields[0],
+  UPB_SIZE(4, 8), 1, false,
+};
+
+static const upb_msglayout *const envoy_api_v2_auth_CertificateValidationContext_submsgs[5] = {
+  &envoy_api_v2_core_DataSource_msginit,
+  &envoy_type_matcher_StringMatcher_msginit,
+  &google_protobuf_BoolValue_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_auth_CertificateValidationContext__fields[10] = {
+  {1, UPB_SIZE(12, 16), 0, 0, 11, 1},
+  {2, UPB_SIZE(28, 48), 0, 0, 9, 3},
+  {3, UPB_SIZE(32, 56), 0, 0, 9, 3},
+  {4, UPB_SIZE(36, 64), 0, 0, 9, 3},
+  {5, UPB_SIZE(16, 24), 0, 2, 11, 1},
+  {6, UPB_SIZE(20, 32), 0, 2, 11, 1},
+  {7, UPB_SIZE(24, 40), 0, 0, 11, 1},
+  {8, UPB_SIZE(8, 8), 0, 0, 8, 1},
+  {9, UPB_SIZE(40, 72), 0, 1, 11, 3},
+  {10, UPB_SIZE(0, 0), 0, 0, 14, 1},
+};
+
+const upb_msglayout envoy_api_v2_auth_CertificateValidationContext_msginit = {
+  &envoy_api_v2_auth_CertificateValidationContext_submsgs[0],
+  &envoy_api_v2_auth_CertificateValidationContext__fields[0],
+  UPB_SIZE(48, 80), 10, false,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h b/src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h
new file mode 100644 (file)
index 0000000..837d198
--- /dev/null
@@ -0,0 +1,418 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/auth/common.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef ENVOY_API_V2_AUTH_COMMON_PROTO_UPB_H_
+#define ENVOY_API_V2_AUTH_COMMON_PROTO_UPB_H_
+
+#include "upb/generated_util.h"
+#include "upb/msg.h"
+#include "upb/decode.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct envoy_api_v2_auth_TlsParameters;
+struct envoy_api_v2_auth_PrivateKeyProvider;
+struct envoy_api_v2_auth_TlsCertificate;
+struct envoy_api_v2_auth_TlsSessionTicketKeys;
+struct envoy_api_v2_auth_CertificateValidationContext;
+typedef struct envoy_api_v2_auth_TlsParameters envoy_api_v2_auth_TlsParameters;
+typedef struct envoy_api_v2_auth_PrivateKeyProvider envoy_api_v2_auth_PrivateKeyProvider;
+typedef struct envoy_api_v2_auth_TlsCertificate envoy_api_v2_auth_TlsCertificate;
+typedef struct envoy_api_v2_auth_TlsSessionTicketKeys envoy_api_v2_auth_TlsSessionTicketKeys;
+typedef struct envoy_api_v2_auth_CertificateValidationContext envoy_api_v2_auth_CertificateValidationContext;
+extern const upb_msglayout envoy_api_v2_auth_TlsParameters_msginit;
+extern const upb_msglayout envoy_api_v2_auth_PrivateKeyProvider_msginit;
+extern const upb_msglayout envoy_api_v2_auth_TlsCertificate_msginit;
+extern const upb_msglayout envoy_api_v2_auth_TlsSessionTicketKeys_msginit;
+extern const upb_msglayout envoy_api_v2_auth_CertificateValidationContext_msginit;
+struct envoy_api_v2_core_DataSource;
+struct envoy_type_matcher_StringMatcher;
+struct google_protobuf_Any;
+struct google_protobuf_BoolValue;
+struct google_protobuf_Struct;
+extern const upb_msglayout envoy_api_v2_core_DataSource_msginit;
+extern const upb_msglayout envoy_type_matcher_StringMatcher_msginit;
+extern const upb_msglayout google_protobuf_Any_msginit;
+extern const upb_msglayout google_protobuf_BoolValue_msginit;
+extern const upb_msglayout google_protobuf_Struct_msginit;
+
+typedef enum {
+  envoy_api_v2_auth_CertificateValidationContext_VERIFY_TRUST_CHAIN = 0,
+  envoy_api_v2_auth_CertificateValidationContext_ACCEPT_UNTRUSTED = 1
+} envoy_api_v2_auth_CertificateValidationContext_TrustChainVerification;
+
+typedef enum {
+  envoy_api_v2_auth_TlsParameters_TLS_AUTO = 0,
+  envoy_api_v2_auth_TlsParameters_TLSv1_0 = 1,
+  envoy_api_v2_auth_TlsParameters_TLSv1_1 = 2,
+  envoy_api_v2_auth_TlsParameters_TLSv1_2 = 3,
+  envoy_api_v2_auth_TlsParameters_TLSv1_3 = 4
+} envoy_api_v2_auth_TlsParameters_TlsProtocol;
+
+
+/* envoy.api.v2.auth.TlsParameters */
+
+UPB_INLINE envoy_api_v2_auth_TlsParameters *envoy_api_v2_auth_TlsParameters_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_TlsParameters *)upb_msg_new(&envoy_api_v2_auth_TlsParameters_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_TlsParameters *envoy_api_v2_auth_TlsParameters_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_TlsParameters *ret = envoy_api_v2_auth_TlsParameters_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_TlsParameters_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_TlsParameters_serialize(const envoy_api_v2_auth_TlsParameters *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_TlsParameters_msginit, arena, len);
+}
+
+UPB_INLINE int32_t envoy_api_v2_auth_TlsParameters_tls_minimum_protocol_version(const envoy_api_v2_auth_TlsParameters *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)); }
+UPB_INLINE int32_t envoy_api_v2_auth_TlsParameters_tls_maximum_protocol_version(const envoy_api_v2_auth_TlsParameters *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
+UPB_INLINE upb_strview const* envoy_api_v2_auth_TlsParameters_cipher_suites(const envoy_api_v2_auth_TlsParameters *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(16, 16), len); }
+UPB_INLINE upb_strview const* envoy_api_v2_auth_TlsParameters_ecdh_curves(const envoy_api_v2_auth_TlsParameters *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(20, 24), len); }
+
+UPB_INLINE void envoy_api_v2_auth_TlsParameters_set_tls_minimum_protocol_version(envoy_api_v2_auth_TlsParameters *msg, int32_t value) {
+  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE void envoy_api_v2_auth_TlsParameters_set_tls_maximum_protocol_version(envoy_api_v2_auth_TlsParameters *msg, int32_t value) {
+  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value;
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_TlsParameters_mutable_cipher_suites(envoy_api_v2_auth_TlsParameters *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 16), len);
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_TlsParameters_resize_cipher_suites(envoy_api_v2_auth_TlsParameters *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(16, 16), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+}
+UPB_INLINE bool envoy_api_v2_auth_TlsParameters_add_cipher_suites(envoy_api_v2_auth_TlsParameters *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor(
+      msg, UPB_SIZE(16, 16), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_TlsParameters_mutable_ecdh_curves(envoy_api_v2_auth_TlsParameters *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 24), len);
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_TlsParameters_resize_ecdh_curves(envoy_api_v2_auth_TlsParameters *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 24), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+}
+UPB_INLINE bool envoy_api_v2_auth_TlsParameters_add_ecdh_curves(envoy_api_v2_auth_TlsParameters *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor(
+      msg, UPB_SIZE(20, 24), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+}
+
+/* envoy.api.v2.auth.PrivateKeyProvider */
+
+UPB_INLINE envoy_api_v2_auth_PrivateKeyProvider *envoy_api_v2_auth_PrivateKeyProvider_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_PrivateKeyProvider *)upb_msg_new(&envoy_api_v2_auth_PrivateKeyProvider_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_PrivateKeyProvider *envoy_api_v2_auth_PrivateKeyProvider_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_PrivateKeyProvider *ret = envoy_api_v2_auth_PrivateKeyProvider_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_PrivateKeyProvider_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_PrivateKeyProvider_serialize(const envoy_api_v2_auth_PrivateKeyProvider *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_PrivateKeyProvider_msginit, arena, len);
+}
+
+typedef enum {
+  envoy_api_v2_auth_PrivateKeyProvider_config_type_config = 2,
+  envoy_api_v2_auth_PrivateKeyProvider_config_type_typed_config = 3,
+  envoy_api_v2_auth_PrivateKeyProvider_config_type_NOT_SET = 0
+} envoy_api_v2_auth_PrivateKeyProvider_config_type_oneofcases;
+UPB_INLINE envoy_api_v2_auth_PrivateKeyProvider_config_type_oneofcases envoy_api_v2_auth_PrivateKeyProvider_config_type_case(const envoy_api_v2_auth_PrivateKeyProvider* msg) { return (envoy_api_v2_auth_PrivateKeyProvider_config_type_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(12, 24)); }
+
+UPB_INLINE upb_strview envoy_api_v2_auth_PrivateKeyProvider_provider_name(const envoy_api_v2_auth_PrivateKeyProvider *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
+UPB_INLINE bool envoy_api_v2_auth_PrivateKeyProvider_has_config(const envoy_api_v2_auth_PrivateKeyProvider *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 2); }
+UPB_INLINE const struct google_protobuf_Struct* envoy_api_v2_auth_PrivateKeyProvider_config(const envoy_api_v2_auth_PrivateKeyProvider *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_Struct*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 2, NULL); }
+UPB_INLINE bool envoy_api_v2_auth_PrivateKeyProvider_has_typed_config(const envoy_api_v2_auth_PrivateKeyProvider *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 3); }
+UPB_INLINE const struct google_protobuf_Any* envoy_api_v2_auth_PrivateKeyProvider_typed_config(const envoy_api_v2_auth_PrivateKeyProvider *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_Any*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 3, NULL); }
+
+UPB_INLINE void envoy_api_v2_auth_PrivateKeyProvider_set_provider_name(envoy_api_v2_auth_PrivateKeyProvider *msg, upb_strview value) {
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE void envoy_api_v2_auth_PrivateKeyProvider_set_config(envoy_api_v2_auth_PrivateKeyProvider *msg, struct google_protobuf_Struct* value) {
+  UPB_WRITE_ONEOF(msg, struct google_protobuf_Struct*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 2);
+}
+UPB_INLINE struct google_protobuf_Struct* envoy_api_v2_auth_PrivateKeyProvider_mutable_config(envoy_api_v2_auth_PrivateKeyProvider *msg, upb_arena *arena) {
+  struct google_protobuf_Struct* sub = (struct google_protobuf_Struct*)envoy_api_v2_auth_PrivateKeyProvider_config(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Struct*)upb_msg_new(&google_protobuf_Struct_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_PrivateKeyProvider_set_config(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_PrivateKeyProvider_set_typed_config(envoy_api_v2_auth_PrivateKeyProvider *msg, struct google_protobuf_Any* value) {
+  UPB_WRITE_ONEOF(msg, struct google_protobuf_Any*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 3);
+}
+UPB_INLINE struct google_protobuf_Any* envoy_api_v2_auth_PrivateKeyProvider_mutable_typed_config(envoy_api_v2_auth_PrivateKeyProvider *msg, upb_arena *arena) {
+  struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_api_v2_auth_PrivateKeyProvider_typed_config(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Any*)upb_msg_new(&google_protobuf_Any_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_PrivateKeyProvider_set_typed_config(msg, sub);
+  }
+  return sub;
+}
+
+/* envoy.api.v2.auth.TlsCertificate */
+
+UPB_INLINE envoy_api_v2_auth_TlsCertificate *envoy_api_v2_auth_TlsCertificate_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_TlsCertificate *)upb_msg_new(&envoy_api_v2_auth_TlsCertificate_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_TlsCertificate *envoy_api_v2_auth_TlsCertificate_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_TlsCertificate *ret = envoy_api_v2_auth_TlsCertificate_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_TlsCertificate_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_TlsCertificate_serialize(const envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_TlsCertificate_msginit, arena, len);
+}
+
+UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_certificate_chain(const envoy_api_v2_auth_TlsCertificate *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(0, 0)); }
+UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_private_key(const envoy_api_v2_auth_TlsCertificate *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(4, 8)); }
+UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_password(const envoy_api_v2_auth_TlsCertificate *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(8, 16)); }
+UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_ocsp_staple(const envoy_api_v2_auth_TlsCertificate *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(12, 24)); }
+UPB_INLINE const struct envoy_api_v2_core_DataSource* const* envoy_api_v2_auth_TlsCertificate_signed_certificate_timestamp(const envoy_api_v2_auth_TlsCertificate *msg, size_t *len) { return (const struct envoy_api_v2_core_DataSource* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
+UPB_INLINE const envoy_api_v2_auth_PrivateKeyProvider* envoy_api_v2_auth_TlsCertificate_private_key_provider(const envoy_api_v2_auth_TlsCertificate *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_auth_PrivateKeyProvider*, UPB_SIZE(16, 32)); }
+
+UPB_INLINE void envoy_api_v2_auth_TlsCertificate_set_certificate_chain(envoy_api_v2_auth_TlsCertificate *msg, struct envoy_api_v2_core_DataSource* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_mutable_certificate_chain(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_TlsCertificate_certificate_chain(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_TlsCertificate_set_certificate_chain(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_TlsCertificate_set_private_key(envoy_api_v2_auth_TlsCertificate *msg, struct envoy_api_v2_core_DataSource* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(4, 8)) = value;
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_mutable_private_key(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_TlsCertificate_private_key(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_TlsCertificate_set_private_key(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_TlsCertificate_set_password(envoy_api_v2_auth_TlsCertificate *msg, struct envoy_api_v2_core_DataSource* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(8, 16)) = value;
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_mutable_password(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_TlsCertificate_password(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_TlsCertificate_set_password(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_TlsCertificate_set_ocsp_staple(envoy_api_v2_auth_TlsCertificate *msg, struct envoy_api_v2_core_DataSource* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(12, 24)) = value;
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_mutable_ocsp_staple(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_TlsCertificate_ocsp_staple(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_TlsCertificate_set_ocsp_staple(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource** envoy_api_v2_auth_TlsCertificate_mutable_signed_certificate_timestamp(envoy_api_v2_auth_TlsCertificate *msg, size_t *len) {
+  return (struct envoy_api_v2_core_DataSource**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource** envoy_api_v2_auth_TlsCertificate_resize_signed_certificate_timestamp(envoy_api_v2_auth_TlsCertificate *msg, size_t len, upb_arena *arena) {
+  return (struct envoy_api_v2_core_DataSource**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsCertificate_add_signed_certificate_timestamp(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
+  bool ok = _upb_array_append_accessor(
+      msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_TlsCertificate_set_private_key_provider(envoy_api_v2_auth_TlsCertificate *msg, envoy_api_v2_auth_PrivateKeyProvider* value) {
+  UPB_FIELD_AT(msg, envoy_api_v2_auth_PrivateKeyProvider*, UPB_SIZE(16, 32)) = value;
+}
+UPB_INLINE struct envoy_api_v2_auth_PrivateKeyProvider* envoy_api_v2_auth_TlsCertificate_mutable_private_key_provider(envoy_api_v2_auth_TlsCertificate *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_PrivateKeyProvider* sub = (struct envoy_api_v2_auth_PrivateKeyProvider*)envoy_api_v2_auth_TlsCertificate_private_key_provider(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_PrivateKeyProvider*)upb_msg_new(&envoy_api_v2_auth_PrivateKeyProvider_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_TlsCertificate_set_private_key_provider(msg, sub);
+  }
+  return sub;
+}
+
+/* envoy.api.v2.auth.TlsSessionTicketKeys */
+
+UPB_INLINE envoy_api_v2_auth_TlsSessionTicketKeys *envoy_api_v2_auth_TlsSessionTicketKeys_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_TlsSessionTicketKeys *)upb_msg_new(&envoy_api_v2_auth_TlsSessionTicketKeys_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_TlsSessionTicketKeys *envoy_api_v2_auth_TlsSessionTicketKeys_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_TlsSessionTicketKeys *ret = envoy_api_v2_auth_TlsSessionTicketKeys_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_TlsSessionTicketKeys_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_TlsSessionTicketKeys_serialize(const envoy_api_v2_auth_TlsSessionTicketKeys *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_TlsSessionTicketKeys_msginit, arena, len);
+}
+
+UPB_INLINE const struct envoy_api_v2_core_DataSource* const* envoy_api_v2_auth_TlsSessionTicketKeys_keys(const envoy_api_v2_auth_TlsSessionTicketKeys *msg, size_t *len) { return (const struct envoy_api_v2_core_DataSource* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE struct envoy_api_v2_core_DataSource** envoy_api_v2_auth_TlsSessionTicketKeys_mutable_keys(envoy_api_v2_auth_TlsSessionTicketKeys *msg, size_t *len) {
+  return (struct envoy_api_v2_core_DataSource**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource** envoy_api_v2_auth_TlsSessionTicketKeys_resize_keys(envoy_api_v2_auth_TlsSessionTicketKeys *msg, size_t len, upb_arena *arena) {
+  return (struct envoy_api_v2_core_DataSource**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_TlsSessionTicketKeys_add_keys(envoy_api_v2_auth_TlsSessionTicketKeys *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
+  bool ok = _upb_array_append_accessor(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* envoy.api.v2.auth.CertificateValidationContext */
+
+UPB_INLINE envoy_api_v2_auth_CertificateValidationContext *envoy_api_v2_auth_CertificateValidationContext_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_CertificateValidationContext *)upb_msg_new(&envoy_api_v2_auth_CertificateValidationContext_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_CertificateValidationContext *envoy_api_v2_auth_CertificateValidationContext_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_CertificateValidationContext *ret = envoy_api_v2_auth_CertificateValidationContext_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_CertificateValidationContext_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_CertificateValidationContext_serialize(const envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_CertificateValidationContext_msginit, arena, len);
+}
+
+UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_CertificateValidationContext_trusted_ca(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(12, 16)); }
+UPB_INLINE upb_strview const* envoy_api_v2_auth_CertificateValidationContext_verify_certificate_hash(const envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 48), len); }
+UPB_INLINE upb_strview const* envoy_api_v2_auth_CertificateValidationContext_verify_certificate_spki(const envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(32, 56), len); }
+UPB_INLINE upb_strview const* envoy_api_v2_auth_CertificateValidationContext_verify_subject_alt_name(const envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 64), len); }
+UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_auth_CertificateValidationContext_require_ocsp_staple(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(16, 24)); }
+UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_auth_CertificateValidationContext_require_signed_certificate_timestamp(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(20, 32)); }
+UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_CertificateValidationContext_crl(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(24, 40)); }
+UPB_INLINE bool envoy_api_v2_auth_CertificateValidationContext_allow_expired_certificate(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(8, 8)); }
+UPB_INLINE const struct envoy_type_matcher_StringMatcher* const* envoy_api_v2_auth_CertificateValidationContext_match_subject_alt_names(const envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) { return (const struct envoy_type_matcher_StringMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(40, 72), len); }
+UPB_INLINE int32_t envoy_api_v2_auth_CertificateValidationContext_trust_chain_verification(const envoy_api_v2_auth_CertificateValidationContext *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)); }
+
+UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_trusted_ca(envoy_api_v2_auth_CertificateValidationContext *msg, struct envoy_api_v2_core_DataSource* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(12, 16)) = value;
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_CertificateValidationContext_mutable_trusted_ca(envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_CertificateValidationContext_trusted_ca(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_CertificateValidationContext_set_trusted_ca(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_mutable_verify_certificate_hash(envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 48), len);
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_resize_verify_certificate_hash(envoy_api_v2_auth_CertificateValidationContext *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(28, 48), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+}
+UPB_INLINE bool envoy_api_v2_auth_CertificateValidationContext_add_verify_certificate_hash(envoy_api_v2_auth_CertificateValidationContext *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor(
+      msg, UPB_SIZE(28, 48), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_mutable_verify_certificate_spki(envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 56), len);
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_resize_verify_certificate_spki(envoy_api_v2_auth_CertificateValidationContext *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(32, 56), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+}
+UPB_INLINE bool envoy_api_v2_auth_CertificateValidationContext_add_verify_certificate_spki(envoy_api_v2_auth_CertificateValidationContext *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor(
+      msg, UPB_SIZE(32, 56), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_mutable_verify_subject_alt_name(envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 64), len);
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_CertificateValidationContext_resize_verify_subject_alt_name(envoy_api_v2_auth_CertificateValidationContext *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(36, 64), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+}
+UPB_INLINE bool envoy_api_v2_auth_CertificateValidationContext_add_verify_subject_alt_name(envoy_api_v2_auth_CertificateValidationContext *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor(
+      msg, UPB_SIZE(36, 64), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+}
+UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_require_ocsp_staple(envoy_api_v2_auth_CertificateValidationContext *msg, struct google_protobuf_BoolValue* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_BoolValue*, UPB_SIZE(16, 24)) = value;
+}
+UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_auth_CertificateValidationContext_mutable_require_ocsp_staple(envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena) {
+  struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_api_v2_auth_CertificateValidationContext_require_ocsp_staple(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_BoolValue*)upb_msg_new(&google_protobuf_BoolValue_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_CertificateValidationContext_set_require_ocsp_staple(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_require_signed_certificate_timestamp(envoy_api_v2_auth_CertificateValidationContext *msg, struct google_protobuf_BoolValue* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_BoolValue*, UPB_SIZE(20, 32)) = value;
+}
+UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_auth_CertificateValidationContext_mutable_require_signed_certificate_timestamp(envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena) {
+  struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_api_v2_auth_CertificateValidationContext_require_signed_certificate_timestamp(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_BoolValue*)upb_msg_new(&google_protobuf_BoolValue_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_CertificateValidationContext_set_require_signed_certificate_timestamp(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_crl(envoy_api_v2_auth_CertificateValidationContext *msg, struct envoy_api_v2_core_DataSource* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(24, 40)) = value;
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_CertificateValidationContext_mutable_crl(envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_CertificateValidationContext_crl(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_CertificateValidationContext_set_crl(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_allow_expired_certificate(envoy_api_v2_auth_CertificateValidationContext *msg, bool value) {
+  UPB_FIELD_AT(msg, bool, UPB_SIZE(8, 8)) = value;
+}
+UPB_INLINE struct envoy_type_matcher_StringMatcher** envoy_api_v2_auth_CertificateValidationContext_mutable_match_subject_alt_names(envoy_api_v2_auth_CertificateValidationContext *msg, size_t *len) {
+  return (struct envoy_type_matcher_StringMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 72), len);
+}
+UPB_INLINE struct envoy_type_matcher_StringMatcher** envoy_api_v2_auth_CertificateValidationContext_resize_match_subject_alt_names(envoy_api_v2_auth_CertificateValidationContext *msg, size_t len, upb_arena *arena) {
+  return (struct envoy_type_matcher_StringMatcher**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 72), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+}
+UPB_INLINE struct envoy_type_matcher_StringMatcher* envoy_api_v2_auth_CertificateValidationContext_add_match_subject_alt_names(envoy_api_v2_auth_CertificateValidationContext *msg, upb_arena *arena) {
+  struct envoy_type_matcher_StringMatcher* sub = (struct envoy_type_matcher_StringMatcher*)upb_msg_new(&envoy_type_matcher_StringMatcher_msginit, arena);
+  bool ok = _upb_array_append_accessor(
+      msg, UPB_SIZE(40, 72), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_CertificateValidationContext_set_trust_chain_verification(envoy_api_v2_auth_CertificateValidationContext *msg, int32_t value) {
+  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)) = value;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* ENVOY_API_V2_AUTH_COMMON_PROTO_UPB_H_ */
diff --git a/src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c b/src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c
new file mode 100644 (file)
index 0000000..d34d225
--- /dev/null
@@ -0,0 +1,72 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/auth/secret.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg.h"
+#include "envoy/api/v2/auth/secret.upb.h"
+#include "envoy/api/v2/auth/common.upb.h"
+#include "envoy/api/v2/core/base.upb.h"
+#include "envoy/api/v2/core/config_source.upb.h"
+#include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/sensitive.upb.h"
+#include "udpa/annotations/status.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout *const envoy_api_v2_auth_GenericSecret_submsgs[1] = {
+  &envoy_api_v2_core_DataSource_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_auth_GenericSecret__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_auth_GenericSecret_msginit = {
+  &envoy_api_v2_auth_GenericSecret_submsgs[0],
+  &envoy_api_v2_auth_GenericSecret__fields[0],
+  UPB_SIZE(4, 8), 1, false,
+};
+
+static const upb_msglayout *const envoy_api_v2_auth_SdsSecretConfig_submsgs[1] = {
+  &envoy_api_v2_core_ConfigSource_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_auth_SdsSecretConfig__fields[2] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 9, 1},
+  {2, UPB_SIZE(8, 16), 0, 0, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_auth_SdsSecretConfig_msginit = {
+  &envoy_api_v2_auth_SdsSecretConfig_submsgs[0],
+  &envoy_api_v2_auth_SdsSecretConfig__fields[0],
+  UPB_SIZE(16, 32), 2, false,
+};
+
+static const upb_msglayout *const envoy_api_v2_auth_Secret_submsgs[4] = {
+  &envoy_api_v2_auth_CertificateValidationContext_msginit,
+  &envoy_api_v2_auth_GenericSecret_msginit,
+  &envoy_api_v2_auth_TlsCertificate_msginit,
+  &envoy_api_v2_auth_TlsSessionTicketKeys_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_auth_Secret__fields[5] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 9, 1},
+  {2, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 2, 11, 1},
+  {3, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 3, 11, 1},
+  {4, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1},
+  {5, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 1, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_auth_Secret_msginit = {
+  &envoy_api_v2_auth_Secret_submsgs[0],
+  &envoy_api_v2_auth_Secret__fields[0],
+  UPB_SIZE(16, 32), 5, false,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h b/src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h
new file mode 100644 (file)
index 0000000..cf3c782
--- /dev/null
@@ -0,0 +1,197 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/auth/secret.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef ENVOY_API_V2_AUTH_SECRET_PROTO_UPB_H_
+#define ENVOY_API_V2_AUTH_SECRET_PROTO_UPB_H_
+
+#include "upb/generated_util.h"
+#include "upb/msg.h"
+#include "upb/decode.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct envoy_api_v2_auth_GenericSecret;
+struct envoy_api_v2_auth_SdsSecretConfig;
+struct envoy_api_v2_auth_Secret;
+typedef struct envoy_api_v2_auth_GenericSecret envoy_api_v2_auth_GenericSecret;
+typedef struct envoy_api_v2_auth_SdsSecretConfig envoy_api_v2_auth_SdsSecretConfig;
+typedef struct envoy_api_v2_auth_Secret envoy_api_v2_auth_Secret;
+extern const upb_msglayout envoy_api_v2_auth_GenericSecret_msginit;
+extern const upb_msglayout envoy_api_v2_auth_SdsSecretConfig_msginit;
+extern const upb_msglayout envoy_api_v2_auth_Secret_msginit;
+struct envoy_api_v2_auth_CertificateValidationContext;
+struct envoy_api_v2_auth_TlsCertificate;
+struct envoy_api_v2_auth_TlsSessionTicketKeys;
+struct envoy_api_v2_core_ConfigSource;
+struct envoy_api_v2_core_DataSource;
+extern const upb_msglayout envoy_api_v2_auth_CertificateValidationContext_msginit;
+extern const upb_msglayout envoy_api_v2_auth_TlsCertificate_msginit;
+extern const upb_msglayout envoy_api_v2_auth_TlsSessionTicketKeys_msginit;
+extern const upb_msglayout envoy_api_v2_core_ConfigSource_msginit;
+extern const upb_msglayout envoy_api_v2_core_DataSource_msginit;
+
+
+/* envoy.api.v2.auth.GenericSecret */
+
+UPB_INLINE envoy_api_v2_auth_GenericSecret *envoy_api_v2_auth_GenericSecret_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_GenericSecret *)upb_msg_new(&envoy_api_v2_auth_GenericSecret_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_GenericSecret *envoy_api_v2_auth_GenericSecret_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_GenericSecret *ret = envoy_api_v2_auth_GenericSecret_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_GenericSecret_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_GenericSecret_serialize(const envoy_api_v2_auth_GenericSecret *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_GenericSecret_msginit, arena, len);
+}
+
+UPB_INLINE const struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_GenericSecret_secret(const envoy_api_v2_auth_GenericSecret *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_DataSource*, UPB_SIZE(0, 0)); }
+
+UPB_INLINE void envoy_api_v2_auth_GenericSecret_set_secret(envoy_api_v2_auth_GenericSecret *msg, struct envoy_api_v2_core_DataSource* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_core_DataSource*, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE struct envoy_api_v2_core_DataSource* envoy_api_v2_auth_GenericSecret_mutable_secret(envoy_api_v2_auth_GenericSecret *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_DataSource* sub = (struct envoy_api_v2_core_DataSource*)envoy_api_v2_auth_GenericSecret_secret(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_DataSource*)upb_msg_new(&envoy_api_v2_core_DataSource_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_GenericSecret_set_secret(msg, sub);
+  }
+  return sub;
+}
+
+/* envoy.api.v2.auth.SdsSecretConfig */
+
+UPB_INLINE envoy_api_v2_auth_SdsSecretConfig *envoy_api_v2_auth_SdsSecretConfig_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_SdsSecretConfig *)upb_msg_new(&envoy_api_v2_auth_SdsSecretConfig_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_SdsSecretConfig *envoy_api_v2_auth_SdsSecretConfig_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_SdsSecretConfig *ret = envoy_api_v2_auth_SdsSecretConfig_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_SdsSecretConfig_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_SdsSecretConfig_serialize(const envoy_api_v2_auth_SdsSecretConfig *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_SdsSecretConfig_msginit, arena, len);
+}
+
+UPB_INLINE upb_strview envoy_api_v2_auth_SdsSecretConfig_name(const envoy_api_v2_auth_SdsSecretConfig *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
+UPB_INLINE const struct envoy_api_v2_core_ConfigSource* envoy_api_v2_auth_SdsSecretConfig_sds_config(const envoy_api_v2_auth_SdsSecretConfig *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_ConfigSource*, UPB_SIZE(8, 16)); }
+
+UPB_INLINE void envoy_api_v2_auth_SdsSecretConfig_set_name(envoy_api_v2_auth_SdsSecretConfig *msg, upb_strview value) {
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE void envoy_api_v2_auth_SdsSecretConfig_set_sds_config(envoy_api_v2_auth_SdsSecretConfig *msg, struct envoy_api_v2_core_ConfigSource* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_core_ConfigSource*, UPB_SIZE(8, 16)) = value;
+}
+UPB_INLINE struct envoy_api_v2_core_ConfigSource* envoy_api_v2_auth_SdsSecretConfig_mutable_sds_config(envoy_api_v2_auth_SdsSecretConfig *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_ConfigSource* sub = (struct envoy_api_v2_core_ConfigSource*)envoy_api_v2_auth_SdsSecretConfig_sds_config(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_ConfigSource*)upb_msg_new(&envoy_api_v2_core_ConfigSource_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_SdsSecretConfig_set_sds_config(msg, sub);
+  }
+  return sub;
+}
+
+/* envoy.api.v2.auth.Secret */
+
+UPB_INLINE envoy_api_v2_auth_Secret *envoy_api_v2_auth_Secret_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_Secret *)upb_msg_new(&envoy_api_v2_auth_Secret_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_Secret *envoy_api_v2_auth_Secret_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_Secret *ret = envoy_api_v2_auth_Secret_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_Secret_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_Secret_serialize(const envoy_api_v2_auth_Secret *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_Secret_msginit, arena, len);
+}
+
+typedef enum {
+  envoy_api_v2_auth_Secret_type_tls_certificate = 2,
+  envoy_api_v2_auth_Secret_type_session_ticket_keys = 3,
+  envoy_api_v2_auth_Secret_type_validation_context = 4,
+  envoy_api_v2_auth_Secret_type_generic_secret = 5,
+  envoy_api_v2_auth_Secret_type_NOT_SET = 0
+} envoy_api_v2_auth_Secret_type_oneofcases;
+UPB_INLINE envoy_api_v2_auth_Secret_type_oneofcases envoy_api_v2_auth_Secret_type_case(const envoy_api_v2_auth_Secret* msg) { return (envoy_api_v2_auth_Secret_type_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(12, 24)); }
+
+UPB_INLINE upb_strview envoy_api_v2_auth_Secret_name(const envoy_api_v2_auth_Secret *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
+UPB_INLINE bool envoy_api_v2_auth_Secret_has_tls_certificate(const envoy_api_v2_auth_Secret *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 2); }
+UPB_INLINE const struct envoy_api_v2_auth_TlsCertificate* envoy_api_v2_auth_Secret_tls_certificate(const envoy_api_v2_auth_Secret *msg) { return UPB_READ_ONEOF(msg, const struct envoy_api_v2_auth_TlsCertificate*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 2, NULL); }
+UPB_INLINE bool envoy_api_v2_auth_Secret_has_session_ticket_keys(const envoy_api_v2_auth_Secret *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 3); }
+UPB_INLINE const struct envoy_api_v2_auth_TlsSessionTicketKeys* envoy_api_v2_auth_Secret_session_ticket_keys(const envoy_api_v2_auth_Secret *msg) { return UPB_READ_ONEOF(msg, const struct envoy_api_v2_auth_TlsSessionTicketKeys*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 3, NULL); }
+UPB_INLINE bool envoy_api_v2_auth_Secret_has_validation_context(const envoy_api_v2_auth_Secret *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 4); }
+UPB_INLINE const struct envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_Secret_validation_context(const envoy_api_v2_auth_Secret *msg) { return UPB_READ_ONEOF(msg, const struct envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 4, NULL); }
+UPB_INLINE bool envoy_api_v2_auth_Secret_has_generic_secret(const envoy_api_v2_auth_Secret *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 5); }
+UPB_INLINE const envoy_api_v2_auth_GenericSecret* envoy_api_v2_auth_Secret_generic_secret(const envoy_api_v2_auth_Secret *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_auth_GenericSecret*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 5, NULL); }
+
+UPB_INLINE void envoy_api_v2_auth_Secret_set_name(envoy_api_v2_auth_Secret *msg, upb_strview value) {
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE void envoy_api_v2_auth_Secret_set_tls_certificate(envoy_api_v2_auth_Secret *msg, struct envoy_api_v2_auth_TlsCertificate* value) {
+  UPB_WRITE_ONEOF(msg, struct envoy_api_v2_auth_TlsCertificate*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 2);
+}
+UPB_INLINE struct envoy_api_v2_auth_TlsCertificate* envoy_api_v2_auth_Secret_mutable_tls_certificate(envoy_api_v2_auth_Secret *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_TlsCertificate* sub = (struct envoy_api_v2_auth_TlsCertificate*)envoy_api_v2_auth_Secret_tls_certificate(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_TlsCertificate*)upb_msg_new(&envoy_api_v2_auth_TlsCertificate_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_Secret_set_tls_certificate(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_Secret_set_session_ticket_keys(envoy_api_v2_auth_Secret *msg, struct envoy_api_v2_auth_TlsSessionTicketKeys* value) {
+  UPB_WRITE_ONEOF(msg, struct envoy_api_v2_auth_TlsSessionTicketKeys*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 3);
+}
+UPB_INLINE struct envoy_api_v2_auth_TlsSessionTicketKeys* envoy_api_v2_auth_Secret_mutable_session_ticket_keys(envoy_api_v2_auth_Secret *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_TlsSessionTicketKeys* sub = (struct envoy_api_v2_auth_TlsSessionTicketKeys*)envoy_api_v2_auth_Secret_session_ticket_keys(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_TlsSessionTicketKeys*)upb_msg_new(&envoy_api_v2_auth_TlsSessionTicketKeys_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_Secret_set_session_ticket_keys(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_Secret_set_validation_context(envoy_api_v2_auth_Secret *msg, struct envoy_api_v2_auth_CertificateValidationContext* value) {
+  UPB_WRITE_ONEOF(msg, struct envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 4);
+}
+UPB_INLINE struct envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_Secret_mutable_validation_context(envoy_api_v2_auth_Secret *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_CertificateValidationContext* sub = (struct envoy_api_v2_auth_CertificateValidationContext*)envoy_api_v2_auth_Secret_validation_context(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_CertificateValidationContext*)upb_msg_new(&envoy_api_v2_auth_CertificateValidationContext_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_Secret_set_validation_context(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_Secret_set_generic_secret(envoy_api_v2_auth_Secret *msg, envoy_api_v2_auth_GenericSecret* value) {
+  UPB_WRITE_ONEOF(msg, envoy_api_v2_auth_GenericSecret*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 5);
+}
+UPB_INLINE struct envoy_api_v2_auth_GenericSecret* envoy_api_v2_auth_Secret_mutable_generic_secret(envoy_api_v2_auth_Secret *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_GenericSecret* sub = (struct envoy_api_v2_auth_GenericSecret*)envoy_api_v2_auth_Secret_generic_secret(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_GenericSecret*)upb_msg_new(&envoy_api_v2_auth_GenericSecret_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_Secret_set_generic_secret(msg, sub);
+  }
+  return sub;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* ENVOY_API_V2_AUTH_SECRET_PROTO_UPB_H_ */
diff --git a/src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c b/src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c
new file mode 100644 (file)
index 0000000..67cc149
--- /dev/null
@@ -0,0 +1,105 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/auth/tls.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg.h"
+#include "envoy/api/v2/auth/tls.upb.h"
+#include "envoy/api/v2/auth/common.upb.h"
+#include "envoy/api/v2/auth/secret.upb.h"
+#include "google/protobuf/duration.upb.h"
+#include "google/protobuf/wrappers.upb.h"
+#include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
+#include "validate/validate.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout *const envoy_api_v2_auth_UpstreamTlsContext_submsgs[2] = {
+  &envoy_api_v2_auth_CommonTlsContext_msginit,
+  &google_protobuf_UInt32Value_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_auth_UpstreamTlsContext__fields[4] = {
+  {1, UPB_SIZE(12, 24), 0, 0, 11, 1},
+  {2, UPB_SIZE(4, 8), 0, 0, 9, 1},
+  {3, UPB_SIZE(0, 0), 0, 0, 8, 1},
+  {4, UPB_SIZE(16, 32), 0, 1, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_auth_UpstreamTlsContext_msginit = {
+  &envoy_api_v2_auth_UpstreamTlsContext_submsgs[0],
+  &envoy_api_v2_auth_UpstreamTlsContext__fields[0],
+  UPB_SIZE(24, 48), 4, false,
+};
+
+static const upb_msglayout *const envoy_api_v2_auth_DownstreamTlsContext_submsgs[6] = {
+  &envoy_api_v2_auth_CommonTlsContext_msginit,
+  &envoy_api_v2_auth_SdsSecretConfig_msginit,
+  &envoy_api_v2_auth_TlsSessionTicketKeys_msginit,
+  &google_protobuf_BoolValue_msginit,
+  &google_protobuf_Duration_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_auth_DownstreamTlsContext__fields[7] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
+  {2, UPB_SIZE(4, 8), 0, 3, 11, 1},
+  {3, UPB_SIZE(8, 16), 0, 3, 11, 1},
+  {4, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 2, 11, 1},
+  {5, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 1, 11, 1},
+  {6, UPB_SIZE(12, 24), 0, 4, 11, 1},
+  {7, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 0, 8, 1},
+};
+
+const upb_msglayout envoy_api_v2_auth_DownstreamTlsContext_msginit = {
+  &envoy_api_v2_auth_DownstreamTlsContext_submsgs[0],
+  &envoy_api_v2_auth_DownstreamTlsContext__fields[0],
+  UPB_SIZE(24, 48), 7, false,
+};
+
+static const upb_msglayout *const envoy_api_v2_auth_CommonTlsContext_submsgs[6] = {
+  &envoy_api_v2_auth_CertificateValidationContext_msginit,
+  &envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit,
+  &envoy_api_v2_auth_SdsSecretConfig_msginit,
+  &envoy_api_v2_auth_TlsCertificate_msginit,
+  &envoy_api_v2_auth_TlsParameters_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_auth_CommonTlsContext__fields[7] = {
+  {1, UPB_SIZE(0, 0), 0, 4, 11, 1},
+  {2, UPB_SIZE(4, 8), 0, 3, 11, 3},
+  {3, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 0, 11, 1},
+  {4, UPB_SIZE(8, 16), 0, 0, 9, 3},
+  {6, UPB_SIZE(12, 24), 0, 2, 11, 3},
+  {7, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 2, 11, 1},
+  {8, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 1, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_auth_CommonTlsContext_msginit = {
+  &envoy_api_v2_auth_CommonTlsContext_submsgs[0],
+  &envoy_api_v2_auth_CommonTlsContext__fields[0],
+  UPB_SIZE(24, 48), 7, false,
+};
+
+static const upb_msglayout *const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_submsgs[2] = {
+  &envoy_api_v2_auth_CertificateValidationContext_msginit,
+  &envoy_api_v2_auth_SdsSecretConfig_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext__fields[2] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
+  {2, UPB_SIZE(4, 8), 0, 1, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit = {
+  &envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_submsgs[0],
+  &envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext__fields[0],
+  UPB_SIZE(8, 16), 2, false,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h b/src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h
new file mode 100644 (file)
index 0000000..4875017
--- /dev/null
@@ -0,0 +1,378 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/auth/tls.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef ENVOY_API_V2_AUTH_TLS_PROTO_UPB_H_
+#define ENVOY_API_V2_AUTH_TLS_PROTO_UPB_H_
+
+#include "upb/generated_util.h"
+#include "upb/msg.h"
+#include "upb/decode.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct envoy_api_v2_auth_UpstreamTlsContext;
+struct envoy_api_v2_auth_DownstreamTlsContext;
+struct envoy_api_v2_auth_CommonTlsContext;
+struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext;
+typedef struct envoy_api_v2_auth_UpstreamTlsContext envoy_api_v2_auth_UpstreamTlsContext;
+typedef struct envoy_api_v2_auth_DownstreamTlsContext envoy_api_v2_auth_DownstreamTlsContext;
+typedef struct envoy_api_v2_auth_CommonTlsContext envoy_api_v2_auth_CommonTlsContext;
+typedef struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext;
+extern const upb_msglayout envoy_api_v2_auth_UpstreamTlsContext_msginit;
+extern const upb_msglayout envoy_api_v2_auth_DownstreamTlsContext_msginit;
+extern const upb_msglayout envoy_api_v2_auth_CommonTlsContext_msginit;
+extern const upb_msglayout envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit;
+struct envoy_api_v2_auth_CertificateValidationContext;
+struct envoy_api_v2_auth_SdsSecretConfig;
+struct envoy_api_v2_auth_TlsCertificate;
+struct envoy_api_v2_auth_TlsParameters;
+struct envoy_api_v2_auth_TlsSessionTicketKeys;
+struct google_protobuf_BoolValue;
+struct google_protobuf_Duration;
+struct google_protobuf_UInt32Value;
+extern const upb_msglayout envoy_api_v2_auth_CertificateValidationContext_msginit;
+extern const upb_msglayout envoy_api_v2_auth_SdsSecretConfig_msginit;
+extern const upb_msglayout envoy_api_v2_auth_TlsCertificate_msginit;
+extern const upb_msglayout envoy_api_v2_auth_TlsParameters_msginit;
+extern const upb_msglayout envoy_api_v2_auth_TlsSessionTicketKeys_msginit;
+extern const upb_msglayout google_protobuf_BoolValue_msginit;
+extern const upb_msglayout google_protobuf_Duration_msginit;
+extern const upb_msglayout google_protobuf_UInt32Value_msginit;
+
+
+/* envoy.api.v2.auth.UpstreamTlsContext */
+
+UPB_INLINE envoy_api_v2_auth_UpstreamTlsContext *envoy_api_v2_auth_UpstreamTlsContext_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_UpstreamTlsContext *)upb_msg_new(&envoy_api_v2_auth_UpstreamTlsContext_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_UpstreamTlsContext *envoy_api_v2_auth_UpstreamTlsContext_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_UpstreamTlsContext *ret = envoy_api_v2_auth_UpstreamTlsContext_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_UpstreamTlsContext_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_UpstreamTlsContext_serialize(const envoy_api_v2_auth_UpstreamTlsContext *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_UpstreamTlsContext_msginit, arena, len);
+}
+
+UPB_INLINE const envoy_api_v2_auth_CommonTlsContext* envoy_api_v2_auth_UpstreamTlsContext_common_tls_context(const envoy_api_v2_auth_UpstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_auth_CommonTlsContext*, UPB_SIZE(12, 24)); }
+UPB_INLINE upb_strview envoy_api_v2_auth_UpstreamTlsContext_sni(const envoy_api_v2_auth_UpstreamTlsContext *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); }
+UPB_INLINE bool envoy_api_v2_auth_UpstreamTlsContext_allow_renegotiation(const envoy_api_v2_auth_UpstreamTlsContext *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)); }
+UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_auth_UpstreamTlsContext_max_session_keys(const envoy_api_v2_auth_UpstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(16, 32)); }
+
+UPB_INLINE void envoy_api_v2_auth_UpstreamTlsContext_set_common_tls_context(envoy_api_v2_auth_UpstreamTlsContext *msg, envoy_api_v2_auth_CommonTlsContext* value) {
+  UPB_FIELD_AT(msg, envoy_api_v2_auth_CommonTlsContext*, UPB_SIZE(12, 24)) = value;
+}
+UPB_INLINE struct envoy_api_v2_auth_CommonTlsContext* envoy_api_v2_auth_UpstreamTlsContext_mutable_common_tls_context(envoy_api_v2_auth_UpstreamTlsContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_CommonTlsContext* sub = (struct envoy_api_v2_auth_CommonTlsContext*)envoy_api_v2_auth_UpstreamTlsContext_common_tls_context(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_CommonTlsContext*)upb_msg_new(&envoy_api_v2_auth_CommonTlsContext_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_UpstreamTlsContext_set_common_tls_context(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_UpstreamTlsContext_set_sni(envoy_api_v2_auth_UpstreamTlsContext *msg, upb_strview value) {
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
+}
+UPB_INLINE void envoy_api_v2_auth_UpstreamTlsContext_set_allow_renegotiation(envoy_api_v2_auth_UpstreamTlsContext *msg, bool value) {
+  UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE void envoy_api_v2_auth_UpstreamTlsContext_set_max_session_keys(envoy_api_v2_auth_UpstreamTlsContext *msg, struct google_protobuf_UInt32Value* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_UInt32Value*, UPB_SIZE(16, 32)) = value;
+}
+UPB_INLINE struct google_protobuf_UInt32Value* envoy_api_v2_auth_UpstreamTlsContext_mutable_max_session_keys(envoy_api_v2_auth_UpstreamTlsContext *msg, upb_arena *arena) {
+  struct google_protobuf_UInt32Value* sub = (struct google_protobuf_UInt32Value*)envoy_api_v2_auth_UpstreamTlsContext_max_session_keys(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_UInt32Value*)upb_msg_new(&google_protobuf_UInt32Value_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_UpstreamTlsContext_set_max_session_keys(msg, sub);
+  }
+  return sub;
+}
+
+/* envoy.api.v2.auth.DownstreamTlsContext */
+
+UPB_INLINE envoy_api_v2_auth_DownstreamTlsContext *envoy_api_v2_auth_DownstreamTlsContext_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_DownstreamTlsContext *)upb_msg_new(&envoy_api_v2_auth_DownstreamTlsContext_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_DownstreamTlsContext *envoy_api_v2_auth_DownstreamTlsContext_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_DownstreamTlsContext *ret = envoy_api_v2_auth_DownstreamTlsContext_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_DownstreamTlsContext_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_DownstreamTlsContext_serialize(const envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_DownstreamTlsContext_msginit, arena, len);
+}
+
+typedef enum {
+  envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_session_ticket_keys = 4,
+  envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_session_ticket_keys_sds_secret_config = 5,
+  envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_disable_stateless_session_resumption = 7,
+  envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_NOT_SET = 0
+} envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_oneofcases;
+UPB_INLINE envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_oneofcases envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_case(const envoy_api_v2_auth_DownstreamTlsContext* msg) { return (envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_type_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(20, 40)); }
+
+UPB_INLINE const envoy_api_v2_auth_CommonTlsContext* envoy_api_v2_auth_DownstreamTlsContext_common_tls_context(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_auth_CommonTlsContext*, UPB_SIZE(0, 0)); }
+UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_auth_DownstreamTlsContext_require_client_certificate(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(4, 8)); }
+UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_auth_DownstreamTlsContext_require_sni(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(8, 16)); }
+UPB_INLINE bool envoy_api_v2_auth_DownstreamTlsContext_has_session_ticket_keys(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 4); }
+UPB_INLINE const struct envoy_api_v2_auth_TlsSessionTicketKeys* envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_READ_ONEOF(msg, const struct envoy_api_v2_auth_TlsSessionTicketKeys*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 4, NULL); }
+UPB_INLINE bool envoy_api_v2_auth_DownstreamTlsContext_has_session_ticket_keys_sds_secret_config(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 5); }
+UPB_INLINE const struct envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_sds_secret_config(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_READ_ONEOF(msg, const struct envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 5, NULL); }
+UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_auth_DownstreamTlsContext_session_timeout(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(12, 24)); }
+UPB_INLINE bool envoy_api_v2_auth_DownstreamTlsContext_has_disable_stateless_session_resumption(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 7); }
+UPB_INLINE bool envoy_api_v2_auth_DownstreamTlsContext_disable_stateless_session_resumption(const envoy_api_v2_auth_DownstreamTlsContext *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 7, false); }
+
+UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_common_tls_context(envoy_api_v2_auth_DownstreamTlsContext *msg, envoy_api_v2_auth_CommonTlsContext* value) {
+  UPB_FIELD_AT(msg, envoy_api_v2_auth_CommonTlsContext*, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE struct envoy_api_v2_auth_CommonTlsContext* envoy_api_v2_auth_DownstreamTlsContext_mutable_common_tls_context(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_CommonTlsContext* sub = (struct envoy_api_v2_auth_CommonTlsContext*)envoy_api_v2_auth_DownstreamTlsContext_common_tls_context(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_CommonTlsContext*)upb_msg_new(&envoy_api_v2_auth_CommonTlsContext_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_DownstreamTlsContext_set_common_tls_context(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_require_client_certificate(envoy_api_v2_auth_DownstreamTlsContext *msg, struct google_protobuf_BoolValue* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_BoolValue*, UPB_SIZE(4, 8)) = value;
+}
+UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_auth_DownstreamTlsContext_mutable_require_client_certificate(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
+  struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_api_v2_auth_DownstreamTlsContext_require_client_certificate(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_BoolValue*)upb_msg_new(&google_protobuf_BoolValue_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_DownstreamTlsContext_set_require_client_certificate(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_require_sni(envoy_api_v2_auth_DownstreamTlsContext *msg, struct google_protobuf_BoolValue* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_BoolValue*, UPB_SIZE(8, 16)) = value;
+}
+UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_auth_DownstreamTlsContext_mutable_require_sni(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
+  struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_api_v2_auth_DownstreamTlsContext_require_sni(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_BoolValue*)upb_msg_new(&google_protobuf_BoolValue_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_DownstreamTlsContext_set_require_sni(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_session_ticket_keys(envoy_api_v2_auth_DownstreamTlsContext *msg, struct envoy_api_v2_auth_TlsSessionTicketKeys* value) {
+  UPB_WRITE_ONEOF(msg, struct envoy_api_v2_auth_TlsSessionTicketKeys*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 4);
+}
+UPB_INLINE struct envoy_api_v2_auth_TlsSessionTicketKeys* envoy_api_v2_auth_DownstreamTlsContext_mutable_session_ticket_keys(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_TlsSessionTicketKeys* sub = (struct envoy_api_v2_auth_TlsSessionTicketKeys*)envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_TlsSessionTicketKeys*)upb_msg_new(&envoy_api_v2_auth_TlsSessionTicketKeys_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_DownstreamTlsContext_set_session_ticket_keys(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_session_ticket_keys_sds_secret_config(envoy_api_v2_auth_DownstreamTlsContext *msg, struct envoy_api_v2_auth_SdsSecretConfig* value) {
+  UPB_WRITE_ONEOF(msg, struct envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 5);
+}
+UPB_INLINE struct envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_DownstreamTlsContext_mutable_session_ticket_keys_sds_secret_config(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_SdsSecretConfig* sub = (struct envoy_api_v2_auth_SdsSecretConfig*)envoy_api_v2_auth_DownstreamTlsContext_session_ticket_keys_sds_secret_config(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_SdsSecretConfig*)upb_msg_new(&envoy_api_v2_auth_SdsSecretConfig_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_DownstreamTlsContext_set_session_ticket_keys_sds_secret_config(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_session_timeout(envoy_api_v2_auth_DownstreamTlsContext *msg, struct google_protobuf_Duration* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(12, 24)) = value;
+}
+UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_auth_DownstreamTlsContext_mutable_session_timeout(envoy_api_v2_auth_DownstreamTlsContext *msg, upb_arena *arena) {
+  struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_api_v2_auth_DownstreamTlsContext_session_timeout(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Duration*)upb_msg_new(&google_protobuf_Duration_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_DownstreamTlsContext_set_session_timeout(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_DownstreamTlsContext_set_disable_stateless_session_resumption(envoy_api_v2_auth_DownstreamTlsContext *msg, bool value) {
+  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 7);
+}
+
+/* envoy.api.v2.auth.CommonTlsContext */
+
+UPB_INLINE envoy_api_v2_auth_CommonTlsContext *envoy_api_v2_auth_CommonTlsContext_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_CommonTlsContext *)upb_msg_new(&envoy_api_v2_auth_CommonTlsContext_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_CommonTlsContext *envoy_api_v2_auth_CommonTlsContext_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_CommonTlsContext *ret = envoy_api_v2_auth_CommonTlsContext_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_CommonTlsContext_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_CommonTlsContext_serialize(const envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_CommonTlsContext_msginit, arena, len);
+}
+
+typedef enum {
+  envoy_api_v2_auth_CommonTlsContext_validation_context_type_validation_context = 3,
+  envoy_api_v2_auth_CommonTlsContext_validation_context_type_validation_context_sds_secret_config = 7,
+  envoy_api_v2_auth_CommonTlsContext_validation_context_type_combined_validation_context = 8,
+  envoy_api_v2_auth_CommonTlsContext_validation_context_type_NOT_SET = 0
+} envoy_api_v2_auth_CommonTlsContext_validation_context_type_oneofcases;
+UPB_INLINE envoy_api_v2_auth_CommonTlsContext_validation_context_type_oneofcases envoy_api_v2_auth_CommonTlsContext_validation_context_type_case(const envoy_api_v2_auth_CommonTlsContext* msg) { return (envoy_api_v2_auth_CommonTlsContext_validation_context_type_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(20, 40)); }
+
+UPB_INLINE const struct envoy_api_v2_auth_TlsParameters* envoy_api_v2_auth_CommonTlsContext_tls_params(const envoy_api_v2_auth_CommonTlsContext *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_auth_TlsParameters*, UPB_SIZE(0, 0)); }
+UPB_INLINE const struct envoy_api_v2_auth_TlsCertificate* const* envoy_api_v2_auth_CommonTlsContext_tls_certificates(const envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) { return (const struct envoy_api_v2_auth_TlsCertificate* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
+UPB_INLINE bool envoy_api_v2_auth_CommonTlsContext_has_validation_context(const envoy_api_v2_auth_CommonTlsContext *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 3); }
+UPB_INLINE const struct envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_validation_context(const envoy_api_v2_auth_CommonTlsContext *msg) { return UPB_READ_ONEOF(msg, const struct envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 3, NULL); }
+UPB_INLINE upb_strview const* envoy_api_v2_auth_CommonTlsContext_alpn_protocols(const envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); }
+UPB_INLINE const struct envoy_api_v2_auth_SdsSecretConfig* const* envoy_api_v2_auth_CommonTlsContext_tls_certificate_sds_secret_configs(const envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) { return (const struct envoy_api_v2_auth_SdsSecretConfig* const*)_upb_array_accessor(msg, UPB_SIZE(12, 24), len); }
+UPB_INLINE bool envoy_api_v2_auth_CommonTlsContext_has_validation_context_sds_secret_config(const envoy_api_v2_auth_CommonTlsContext *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 7); }
+UPB_INLINE const struct envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_CommonTlsContext_validation_context_sds_secret_config(const envoy_api_v2_auth_CommonTlsContext *msg) { return UPB_READ_ONEOF(msg, const struct envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 7, NULL); }
+UPB_INLINE bool envoy_api_v2_auth_CommonTlsContext_has_combined_validation_context(const envoy_api_v2_auth_CommonTlsContext *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 8); }
+UPB_INLINE const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_combined_validation_context(const envoy_api_v2_auth_CommonTlsContext *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 8, NULL); }
+
+UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_set_tls_params(envoy_api_v2_auth_CommonTlsContext *msg, struct envoy_api_v2_auth_TlsParameters* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_auth_TlsParameters*, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE struct envoy_api_v2_auth_TlsParameters* envoy_api_v2_auth_CommonTlsContext_mutable_tls_params(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_TlsParameters* sub = (struct envoy_api_v2_auth_TlsParameters*)envoy_api_v2_auth_CommonTlsContext_tls_params(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_TlsParameters*)upb_msg_new(&envoy_api_v2_auth_TlsParameters_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_CommonTlsContext_set_tls_params(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE struct envoy_api_v2_auth_TlsCertificate** envoy_api_v2_auth_CommonTlsContext_mutable_tls_certificates(envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) {
+  return (struct envoy_api_v2_auth_TlsCertificate**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE struct envoy_api_v2_auth_TlsCertificate** envoy_api_v2_auth_CommonTlsContext_resize_tls_certificates(envoy_api_v2_auth_CommonTlsContext *msg, size_t len, upb_arena *arena) {
+  return (struct envoy_api_v2_auth_TlsCertificate**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+}
+UPB_INLINE struct envoy_api_v2_auth_TlsCertificate* envoy_api_v2_auth_CommonTlsContext_add_tls_certificates(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_TlsCertificate* sub = (struct envoy_api_v2_auth_TlsCertificate*)upb_msg_new(&envoy_api_v2_auth_TlsCertificate_msginit, arena);
+  bool ok = _upb_array_append_accessor(
+      msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_set_validation_context(envoy_api_v2_auth_CommonTlsContext *msg, struct envoy_api_v2_auth_CertificateValidationContext* value) {
+  UPB_WRITE_ONEOF(msg, struct envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 3);
+}
+UPB_INLINE struct envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_mutable_validation_context(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_CertificateValidationContext* sub = (struct envoy_api_v2_auth_CertificateValidationContext*)envoy_api_v2_auth_CommonTlsContext_validation_context(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_CertificateValidationContext*)upb_msg_new(&envoy_api_v2_auth_CertificateValidationContext_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_CommonTlsContext_set_validation_context(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_CommonTlsContext_mutable_alpn_protocols(envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len);
+}
+UPB_INLINE upb_strview* envoy_api_v2_auth_CommonTlsContext_resize_alpn_protocols(envoy_api_v2_auth_CommonTlsContext *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(8, 16), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+}
+UPB_INLINE bool envoy_api_v2_auth_CommonTlsContext_add_alpn_protocols(envoy_api_v2_auth_CommonTlsContext *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor(
+      msg, UPB_SIZE(8, 16), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+}
+UPB_INLINE struct envoy_api_v2_auth_SdsSecretConfig** envoy_api_v2_auth_CommonTlsContext_mutable_tls_certificate_sds_secret_configs(envoy_api_v2_auth_CommonTlsContext *msg, size_t *len) {
+  return (struct envoy_api_v2_auth_SdsSecretConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 24), len);
+}
+UPB_INLINE struct envoy_api_v2_auth_SdsSecretConfig** envoy_api_v2_auth_CommonTlsContext_resize_tls_certificate_sds_secret_configs(envoy_api_v2_auth_CommonTlsContext *msg, size_t len, upb_arena *arena) {
+  return (struct envoy_api_v2_auth_SdsSecretConfig**)_upb_array_resize_accessor(msg, UPB_SIZE(12, 24), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+}
+UPB_INLINE struct envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_CommonTlsContext_add_tls_certificate_sds_secret_configs(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_SdsSecretConfig* sub = (struct envoy_api_v2_auth_SdsSecretConfig*)upb_msg_new(&envoy_api_v2_auth_SdsSecretConfig_msginit, arena);
+  bool ok = _upb_array_append_accessor(
+      msg, UPB_SIZE(12, 24), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_set_validation_context_sds_secret_config(envoy_api_v2_auth_CommonTlsContext *msg, struct envoy_api_v2_auth_SdsSecretConfig* value) {
+  UPB_WRITE_ONEOF(msg, struct envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 7);
+}
+UPB_INLINE struct envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_CommonTlsContext_mutable_validation_context_sds_secret_config(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_SdsSecretConfig* sub = (struct envoy_api_v2_auth_SdsSecretConfig*)envoy_api_v2_auth_CommonTlsContext_validation_context_sds_secret_config(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_SdsSecretConfig*)upb_msg_new(&envoy_api_v2_auth_SdsSecretConfig_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_CommonTlsContext_set_validation_context_sds_secret_config(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_set_combined_validation_context(envoy_api_v2_auth_CommonTlsContext *msg, envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext* value) {
+  UPB_WRITE_ONEOF(msg, envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 8);
+}
+UPB_INLINE struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_mutable_combined_validation_context(envoy_api_v2_auth_CommonTlsContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext* sub = (struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext*)envoy_api_v2_auth_CommonTlsContext_combined_validation_context(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext*)upb_msg_new(&envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_CommonTlsContext_set_combined_validation_context(msg, sub);
+  }
+  return sub;
+}
+
+/* envoy.api.v2.auth.CommonTlsContext.CombinedCertificateValidationContext */
+
+UPB_INLINE envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_new(upb_arena *arena) {
+  return (envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *)upb_msg_new(&envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *ret = envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_serialize(const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_msginit, arena, len);
+}
+
+UPB_INLINE const struct envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_default_validation_context(const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(0, 0)); }
+UPB_INLINE const struct envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_validation_context_sds_secret_config(const envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(4, 8)); }
+
+UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_set_default_validation_context(envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg, struct envoy_api_v2_auth_CertificateValidationContext* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_auth_CertificateValidationContext*, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE struct envoy_api_v2_auth_CertificateValidationContext* envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_mutable_default_validation_context(envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_CertificateValidationContext* sub = (struct envoy_api_v2_auth_CertificateValidationContext*)envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_default_validation_context(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_CertificateValidationContext*)upb_msg_new(&envoy_api_v2_auth_CertificateValidationContext_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_set_default_validation_context(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_set_validation_context_sds_secret_config(envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg, struct envoy_api_v2_auth_SdsSecretConfig* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_auth_SdsSecretConfig*, UPB_SIZE(4, 8)) = value;
+}
+UPB_INLINE struct envoy_api_v2_auth_SdsSecretConfig* envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_mutable_validation_context_sds_secret_config(envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext *msg, upb_arena *arena) {
+  struct envoy_api_v2_auth_SdsSecretConfig* sub = (struct envoy_api_v2_auth_SdsSecretConfig*)envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_validation_context_sds_secret_config(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_auth_SdsSecretConfig*)upb_msg_new(&envoy_api_v2_auth_SdsSecretConfig_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext_set_validation_context_sds_secret_config(msg, sub);
+  }
+  return sub;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* ENVOY_API_V2_AUTH_TLS_PROTO_UPB_H_ */
index e420bb4..3f20aa3 100644 (file)
@@ -13,6 +13,7 @@
 #include "google/api/annotations.upb.h"
 #include "envoy/annotations/resource.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "envoy/api/v2/cluster.upb.h"
 
 #include "upb/port_def.inc"
index ca3b351..80607bb 100644 (file)
@@ -9,7 +9,7 @@
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/api/v2/cluster.upb.h"
-#include "envoy/api/v2/auth/cert.upb.h"
+#include "envoy/api/v2/auth/tls.upb.h"
 #include "envoy/api/v2/cluster/circuit_breaker.upb.h"
 #include "envoy/api/v2/cluster/filter.upb.h"
 #include "envoy/api/v2/cluster/outlier_detection.upb.h"
@@ -26,6 +26,7 @@
 #include "google/protobuf/wrappers.upb.h"
 #include "envoy/annotations/deprecation.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
@@ -237,26 +238,28 @@ const upb_msglayout envoy_api_v2_Cluster_OriginalDstLbConfig_msginit = {
   UPB_SIZE(1, 1), 1, false,
 };
 
-static const upb_msglayout *const envoy_api_v2_Cluster_CommonLbConfig_submsgs[4] = {
+static const upb_msglayout *const envoy_api_v2_Cluster_CommonLbConfig_submsgs[5] = {
+  &envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_msginit,
   &envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig_msginit,
   &envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig_msginit,
   &envoy_type_Percent_msginit,
   &google_protobuf_Duration_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_Cluster_CommonLbConfig__fields[6] = {
-  {1, UPB_SIZE(4, 8), 0, 2, 11, 1},
-  {2, UPB_SIZE(12, 24), UPB_SIZE(-17, -33), 1, 11, 1},
-  {3, UPB_SIZE(12, 24), UPB_SIZE(-17, -33), 0, 11, 1},
-  {4, UPB_SIZE(8, 16), 0, 3, 11, 1},
+static const upb_msglayout_field envoy_api_v2_Cluster_CommonLbConfig__fields[7] = {
+  {1, UPB_SIZE(4, 8), 0, 3, 11, 1},
+  {2, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 2, 11, 1},
+  {3, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 1, 11, 1},
+  {4, UPB_SIZE(8, 16), 0, 4, 11, 1},
   {5, UPB_SIZE(0, 0), 0, 0, 8, 1},
   {6, UPB_SIZE(1, 1), 0, 0, 8, 1},
+  {7, UPB_SIZE(12, 24), 0, 0, 11, 1},
 };
 
 const upb_msglayout envoy_api_v2_Cluster_CommonLbConfig_msginit = {
   &envoy_api_v2_Cluster_CommonLbConfig_submsgs[0],
   &envoy_api_v2_Cluster_CommonLbConfig__fields[0],
-  UPB_SIZE(20, 40), 6, false,
+  UPB_SIZE(24, 48), 7, false,
 };
 
 static const upb_msglayout *const envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig_submsgs[2] = {
@@ -282,6 +285,16 @@ const upb_msglayout envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig
   UPB_SIZE(0, 0), 0, false,
 };
 
+static const upb_msglayout_field envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 8, 1},
+};
+
+const upb_msglayout envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_msginit = {
+  NULL,
+  &envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig__fields[0],
+  UPB_SIZE(1, 1), 1, false,
+};
+
 static const upb_msglayout *const envoy_api_v2_Cluster_RefreshRate_submsgs[2] = {
   &google_protobuf_Duration_msginit,
 };
index 28cce1b..fe825c6 100644 (file)
@@ -32,6 +32,7 @@ struct envoy_api_v2_Cluster_OriginalDstLbConfig;
 struct envoy_api_v2_Cluster_CommonLbConfig;
 struct envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig;
 struct envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig;
+struct envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig;
 struct envoy_api_v2_Cluster_RefreshRate;
 struct envoy_api_v2_Cluster_ExtensionProtocolOptionsEntry;
 struct envoy_api_v2_Cluster_TypedExtensionProtocolOptionsEntry;
@@ -51,6 +52,7 @@ typedef struct envoy_api_v2_Cluster_OriginalDstLbConfig envoy_api_v2_Cluster_Ori
 typedef struct envoy_api_v2_Cluster_CommonLbConfig envoy_api_v2_Cluster_CommonLbConfig;
 typedef struct envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig;
 typedef struct envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig;
+typedef struct envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig;
 typedef struct envoy_api_v2_Cluster_RefreshRate envoy_api_v2_Cluster_RefreshRate;
 typedef struct envoy_api_v2_Cluster_ExtensionProtocolOptionsEntry envoy_api_v2_Cluster_ExtensionProtocolOptionsEntry;
 typedef struct envoy_api_v2_Cluster_TypedExtensionProtocolOptionsEntry envoy_api_v2_Cluster_TypedExtensionProtocolOptionsEntry;
@@ -70,6 +72,7 @@ extern const upb_msglayout envoy_api_v2_Cluster_OriginalDstLbConfig_msginit;
 extern const upb_msglayout envoy_api_v2_Cluster_CommonLbConfig_msginit;
 extern const upb_msglayout envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig_msginit;
 extern const upb_msglayout envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig_msginit;
+extern const upb_msglayout envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_msginit;
 extern const upb_msglayout envoy_api_v2_Cluster_RefreshRate_msginit;
 extern const upb_msglayout envoy_api_v2_Cluster_ExtensionProtocolOptionsEntry_msginit;
 extern const upb_msglayout envoy_api_v2_Cluster_TypedExtensionProtocolOptionsEntry_msginit;
@@ -1032,16 +1035,17 @@ typedef enum {
   envoy_api_v2_Cluster_CommonLbConfig_locality_config_specifier_locality_weighted_lb_config = 3,
   envoy_api_v2_Cluster_CommonLbConfig_locality_config_specifier_NOT_SET = 0
 } envoy_api_v2_Cluster_CommonLbConfig_locality_config_specifier_oneofcases;
-UPB_INLINE envoy_api_v2_Cluster_CommonLbConfig_locality_config_specifier_oneofcases envoy_api_v2_Cluster_CommonLbConfig_locality_config_specifier_case(const envoy_api_v2_Cluster_CommonLbConfig* msg) { return (envoy_api_v2_Cluster_CommonLbConfig_locality_config_specifier_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 32)); }
+UPB_INLINE envoy_api_v2_Cluster_CommonLbConfig_locality_config_specifier_oneofcases envoy_api_v2_Cluster_CommonLbConfig_locality_config_specifier_case(const envoy_api_v2_Cluster_CommonLbConfig* msg) { return (envoy_api_v2_Cluster_CommonLbConfig_locality_config_specifier_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(20, 40)); }
 
 UPB_INLINE const struct envoy_type_Percent* envoy_api_v2_Cluster_CommonLbConfig_healthy_panic_threshold(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return UPB_FIELD_AT(msg, const struct envoy_type_Percent*, UPB_SIZE(4, 8)); }
-UPB_INLINE bool envoy_api_v2_Cluster_CommonLbConfig_has_zone_aware_lb_config(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(16, 32), 2); }
-UPB_INLINE const envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig* envoy_api_v2_Cluster_CommonLbConfig_zone_aware_lb_config(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig*, UPB_SIZE(12, 24), UPB_SIZE(16, 32), 2, NULL); }
-UPB_INLINE bool envoy_api_v2_Cluster_CommonLbConfig_has_locality_weighted_lb_config(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(16, 32), 3); }
-UPB_INLINE const envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig* envoy_api_v2_Cluster_CommonLbConfig_locality_weighted_lb_config(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig*, UPB_SIZE(12, 24), UPB_SIZE(16, 32), 3, NULL); }
+UPB_INLINE bool envoy_api_v2_Cluster_CommonLbConfig_has_zone_aware_lb_config(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 2); }
+UPB_INLINE const envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig* envoy_api_v2_Cluster_CommonLbConfig_zone_aware_lb_config(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 2, NULL); }
+UPB_INLINE bool envoy_api_v2_Cluster_CommonLbConfig_has_locality_weighted_lb_config(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(20, 40), 3); }
+UPB_INLINE const envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig* envoy_api_v2_Cluster_CommonLbConfig_locality_weighted_lb_config(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 3, NULL); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_Cluster_CommonLbConfig_update_merge_window(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(8, 16)); }
 UPB_INLINE bool envoy_api_v2_Cluster_CommonLbConfig_ignore_new_hosts_until_first_hc(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)); }
 UPB_INLINE bool envoy_api_v2_Cluster_CommonLbConfig_close_connections_on_host_set_change(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); }
+UPB_INLINE const envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig* envoy_api_v2_Cluster_CommonLbConfig_consistent_hashing_lb_config(const envoy_api_v2_Cluster_CommonLbConfig *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig*, UPB_SIZE(12, 24)); }
 
 UPB_INLINE void envoy_api_v2_Cluster_CommonLbConfig_set_healthy_panic_threshold(envoy_api_v2_Cluster_CommonLbConfig *msg, struct envoy_type_Percent* value) {
   UPB_FIELD_AT(msg, struct envoy_type_Percent*, UPB_SIZE(4, 8)) = value;
@@ -1056,7 +1060,7 @@ UPB_INLINE struct envoy_type_Percent* envoy_api_v2_Cluster_CommonLbConfig_mutabl
   return sub;
 }
 UPB_INLINE void envoy_api_v2_Cluster_CommonLbConfig_set_zone_aware_lb_config(envoy_api_v2_Cluster_CommonLbConfig *msg, envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig*, UPB_SIZE(12, 24), value, UPB_SIZE(16, 32), 2);
+  UPB_WRITE_ONEOF(msg, envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 2);
 }
 UPB_INLINE struct envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig* envoy_api_v2_Cluster_CommonLbConfig_mutable_zone_aware_lb_config(envoy_api_v2_Cluster_CommonLbConfig *msg, upb_arena *arena) {
   struct envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig* sub = (struct envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig*)envoy_api_v2_Cluster_CommonLbConfig_zone_aware_lb_config(msg);
@@ -1068,7 +1072,7 @@ UPB_INLINE struct envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig* envoy_a
   return sub;
 }
 UPB_INLINE void envoy_api_v2_Cluster_CommonLbConfig_set_locality_weighted_lb_config(envoy_api_v2_Cluster_CommonLbConfig *msg, envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig*, UPB_SIZE(12, 24), value, UPB_SIZE(16, 32), 3);
+  UPB_WRITE_ONEOF(msg, envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 3);
 }
 UPB_INLINE struct envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig* envoy_api_v2_Cluster_CommonLbConfig_mutable_locality_weighted_lb_config(envoy_api_v2_Cluster_CommonLbConfig *msg, upb_arena *arena) {
   struct envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig* sub = (struct envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig*)envoy_api_v2_Cluster_CommonLbConfig_locality_weighted_lb_config(msg);
@@ -1097,6 +1101,18 @@ UPB_INLINE void envoy_api_v2_Cluster_CommonLbConfig_set_ignore_new_hosts_until_f
 UPB_INLINE void envoy_api_v2_Cluster_CommonLbConfig_set_close_connections_on_host_set_change(envoy_api_v2_Cluster_CommonLbConfig *msg, bool value) {
   UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value;
 }
+UPB_INLINE void envoy_api_v2_Cluster_CommonLbConfig_set_consistent_hashing_lb_config(envoy_api_v2_Cluster_CommonLbConfig *msg, envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig* value) {
+  UPB_FIELD_AT(msg, envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig*, UPB_SIZE(12, 24)) = value;
+}
+UPB_INLINE struct envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig* envoy_api_v2_Cluster_CommonLbConfig_mutable_consistent_hashing_lb_config(envoy_api_v2_Cluster_CommonLbConfig *msg, upb_arena *arena) {
+  struct envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig* sub = (struct envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig*)envoy_api_v2_Cluster_CommonLbConfig_consistent_hashing_lb_config(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig*)upb_msg_new(&envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_Cluster_CommonLbConfig_set_consistent_hashing_lb_config(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.api.v2.Cluster.CommonLbConfig.ZoneAwareLbConfig */
 
@@ -1160,6 +1176,26 @@ UPB_INLINE char *envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig_se
 
 
 
+/* envoy.api.v2.Cluster.CommonLbConfig.ConsistentHashingLbConfig */
+
+UPB_INLINE envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig *envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_new(upb_arena *arena) {
+  return (envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig *)upb_msg_new(&envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig *envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig *ret = envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_serialize(const envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_msginit, arena, len);
+}
+
+UPB_INLINE bool envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_use_hostname_for_hashing(const envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)); }
+
+UPB_INLINE void envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig_set_use_hostname_for_hashing(envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig *msg, bool value) {
+  UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)) = value;
+}
+
 /* envoy.api.v2.Cluster.RefreshRate */
 
 UPB_INLINE envoy_api_v2_Cluster_RefreshRate *envoy_api_v2_Cluster_RefreshRate_new(upb_arena *arena) {
index 02569a9..85714e2 100644 (file)
@@ -13,6 +13,7 @@
 #include "envoy/type/percent.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index 1cfdbd7..7bfad13 100644 (file)
@@ -11,6 +11,7 @@
 #include "envoy/api/v2/cluster/filter.upb.h"
 #include "google/protobuf/any.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index d62bf5f..b6d6d18 100644 (file)
@@ -12,6 +12,7 @@
 #include "google/protobuf/duration.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index a5b58bf..7e9fae2 100644 (file)
@@ -9,9 +9,10 @@
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/api/v2/core/address.upb.h"
-#include "envoy/api/v2/core/base.upb.h"
+#include "envoy/api/v2/core/socket_option.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
diff --git a/src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c b/src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c
new file mode 100644 (file)
index 0000000..14bb789
--- /dev/null
@@ -0,0 +1,35 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/core/backoff.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg.h"
+#include "envoy/api/v2/core/backoff.upb.h"
+#include "google/protobuf/duration.upb.h"
+#include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
+#include "validate/validate.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout *const envoy_api_v2_core_BackoffStrategy_submsgs[2] = {
+  &google_protobuf_Duration_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_core_BackoffStrategy__fields[2] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
+  {2, UPB_SIZE(4, 8), 0, 0, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_core_BackoffStrategy_msginit = {
+  &envoy_api_v2_core_BackoffStrategy_submsgs[0],
+  &envoy_api_v2_core_BackoffStrategy__fields[0],
+  UPB_SIZE(8, 16), 2, false,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h b/src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h
new file mode 100644 (file)
index 0000000..853f03f
--- /dev/null
@@ -0,0 +1,78 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/core/backoff.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef ENVOY_API_V2_CORE_BACKOFF_PROTO_UPB_H_
+#define ENVOY_API_V2_CORE_BACKOFF_PROTO_UPB_H_
+
+#include "upb/generated_util.h"
+#include "upb/msg.h"
+#include "upb/decode.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct envoy_api_v2_core_BackoffStrategy;
+typedef struct envoy_api_v2_core_BackoffStrategy envoy_api_v2_core_BackoffStrategy;
+extern const upb_msglayout envoy_api_v2_core_BackoffStrategy_msginit;
+struct google_protobuf_Duration;
+extern const upb_msglayout google_protobuf_Duration_msginit;
+
+
+/* envoy.api.v2.core.BackoffStrategy */
+
+UPB_INLINE envoy_api_v2_core_BackoffStrategy *envoy_api_v2_core_BackoffStrategy_new(upb_arena *arena) {
+  return (envoy_api_v2_core_BackoffStrategy *)upb_msg_new(&envoy_api_v2_core_BackoffStrategy_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_core_BackoffStrategy *envoy_api_v2_core_BackoffStrategy_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_core_BackoffStrategy *ret = envoy_api_v2_core_BackoffStrategy_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_core_BackoffStrategy_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_core_BackoffStrategy_serialize(const envoy_api_v2_core_BackoffStrategy *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_core_BackoffStrategy_msginit, arena, len);
+}
+
+UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_BackoffStrategy_base_interval(const envoy_api_v2_core_BackoffStrategy *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(0, 0)); }
+UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_BackoffStrategy_max_interval(const envoy_api_v2_core_BackoffStrategy *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(4, 8)); }
+
+UPB_INLINE void envoy_api_v2_core_BackoffStrategy_set_base_interval(envoy_api_v2_core_BackoffStrategy *msg, struct google_protobuf_Duration* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_core_BackoffStrategy_mutable_base_interval(envoy_api_v2_core_BackoffStrategy *msg, upb_arena *arena) {
+  struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_api_v2_core_BackoffStrategy_base_interval(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Duration*)upb_msg_new(&google_protobuf_Duration_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_core_BackoffStrategy_set_base_interval(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_core_BackoffStrategy_set_max_interval(envoy_api_v2_core_BackoffStrategy *msg, struct google_protobuf_Duration* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(4, 8)) = value;
+}
+UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_core_BackoffStrategy_mutable_max_interval(envoy_api_v2_core_BackoffStrategy *msg, upb_arena *arena) {
+  struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_api_v2_core_BackoffStrategy_max_interval(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Duration*)upb_msg_new(&google_protobuf_Duration_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_core_BackoffStrategy_set_max_interval(msg, sub);
+  }
+  return sub;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* ENVOY_API_V2_CORE_BACKOFF_PROTO_UPB_H_ */
index f6e37a5..886deb3 100644 (file)
@@ -9,14 +9,19 @@
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/api/v2/core/base.upb.h"
+#include "envoy/api/v2/core/address.upb.h"
+#include "envoy/api/v2/core/backoff.upb.h"
 #include "envoy/api/v2/core/http_uri.upb.h"
 #include "envoy/type/percent.upb.h"
 #include "envoy/type/semantic_version.upb.h"
 #include "google/protobuf/any.upb.h"
+#include "google/protobuf/duration.upb.h"
 #include "google/protobuf/struct.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
+#include "envoy/api/v2/core/socket_option.upb.h"
 
 #include "upb/port_def.inc"
 
@@ -66,30 +71,32 @@ const upb_msglayout envoy_api_v2_core_Extension_msginit = {
   UPB_SIZE(32, 64), 5, false,
 };
 
-static const upb_msglayout *const envoy_api_v2_core_Node_submsgs[4] = {
+static const upb_msglayout *const envoy_api_v2_core_Node_submsgs[5] = {
+  &envoy_api_v2_core_Address_msginit,
   &envoy_api_v2_core_BuildVersion_msginit,
   &envoy_api_v2_core_Extension_msginit,
   &envoy_api_v2_core_Locality_msginit,
   &google_protobuf_Struct_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_core_Node__fields[10] = {
+static const upb_msglayout_field envoy_api_v2_core_Node__fields[11] = {
   {1, UPB_SIZE(0, 0), 0, 0, 9, 1},
   {2, UPB_SIZE(8, 16), 0, 0, 9, 1},
-  {3, UPB_SIZE(32, 64), 0, 3, 11, 1},
-  {4, UPB_SIZE(36, 72), 0, 2, 11, 1},
+  {3, UPB_SIZE(32, 64), 0, 4, 11, 1},
+  {4, UPB_SIZE(36, 72), 0, 3, 11, 1},
   {5, UPB_SIZE(16, 32), 0, 0, 9, 1},
   {6, UPB_SIZE(24, 48), 0, 0, 9, 1},
-  {7, UPB_SIZE(48, 96), UPB_SIZE(-57, -113), 0, 9, 1},
-  {8, UPB_SIZE(48, 96), UPB_SIZE(-57, -113), 0, 11, 1},
-  {9, UPB_SIZE(40, 80), 0, 1, 11, 3},
+  {7, UPB_SIZE(52, 104), UPB_SIZE(-61, -121), 0, 9, 1},
+  {8, UPB_SIZE(52, 104), UPB_SIZE(-61, -121), 1, 11, 1},
+  {9, UPB_SIZE(40, 80), 0, 2, 11, 3},
   {10, UPB_SIZE(44, 88), 0, 0, 9, 3},
+  {11, UPB_SIZE(48, 96), 0, 0, 11, 3},
 };
 
 const upb_msglayout envoy_api_v2_core_Node_msginit = {
   &envoy_api_v2_core_Node_submsgs[0],
   &envoy_api_v2_core_Node__fields[0],
-  UPB_SIZE(64, 128), 10, false,
+  UPB_SIZE(64, 128), 11, false,
 };
 
 static const upb_msglayout *const envoy_api_v2_core_Metadata_submsgs[1] = {
@@ -132,6 +139,17 @@ const upb_msglayout envoy_api_v2_core_RuntimeUInt32_msginit = {
   UPB_SIZE(16, 32), 2, false,
 };
 
+static const upb_msglayout_field envoy_api_v2_core_RuntimeDouble__fields[2] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 1, 1},
+  {2, UPB_SIZE(8, 8), 0, 0, 9, 1},
+};
+
+const upb_msglayout envoy_api_v2_core_RuntimeDouble_msginit = {
+  NULL,
+  &envoy_api_v2_core_RuntimeDouble__fields[0],
+  UPB_SIZE(16, 32), 2, false,
+};
+
 static const upb_msglayout *const envoy_api_v2_core_RuntimeFeatureFlag_submsgs[1] = {
   &google_protobuf_BoolValue_msginit,
 };
@@ -200,19 +218,37 @@ const upb_msglayout envoy_api_v2_core_DataSource_msginit = {
   UPB_SIZE(16, 32), 3, false,
 };
 
-static const upb_msglayout *const envoy_api_v2_core_RemoteDataSource_submsgs[1] = {
+static const upb_msglayout *const envoy_api_v2_core_RetryPolicy_submsgs[2] = {
+  &envoy_api_v2_core_BackoffStrategy_msginit,
+  &google_protobuf_UInt32Value_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_core_RetryPolicy__fields[2] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
+  {2, UPB_SIZE(4, 8), 0, 1, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_core_RetryPolicy_msginit = {
+  &envoy_api_v2_core_RetryPolicy_submsgs[0],
+  &envoy_api_v2_core_RetryPolicy__fields[0],
+  UPB_SIZE(8, 16), 2, false,
+};
+
+static const upb_msglayout *const envoy_api_v2_core_RemoteDataSource_submsgs[2] = {
   &envoy_api_v2_core_HttpUri_msginit,
+  &envoy_api_v2_core_RetryPolicy_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_core_RemoteDataSource__fields[2] = {
+static const upb_msglayout_field envoy_api_v2_core_RemoteDataSource__fields[3] = {
   {1, UPB_SIZE(8, 16), 0, 0, 11, 1},
   {2, UPB_SIZE(0, 0), 0, 0, 9, 1},
+  {3, UPB_SIZE(12, 24), 0, 1, 11, 1},
 };
 
 const upb_msglayout envoy_api_v2_core_RemoteDataSource_msginit = {
   &envoy_api_v2_core_RemoteDataSource_submsgs[0],
   &envoy_api_v2_core_RemoteDataSource__fields[0],
-  UPB_SIZE(16, 32), 2, false,
+  UPB_SIZE(16, 32), 3, false,
 };
 
 static const upb_msglayout *const envoy_api_v2_core_AsyncDataSource_submsgs[2] = {
@@ -248,21 +284,6 @@ const upb_msglayout envoy_api_v2_core_TransportSocket_msginit = {
   UPB_SIZE(16, 32), 3, false,
 };
 
-static const upb_msglayout_field envoy_api_v2_core_SocketOption__fields[6] = {
-  {1, UPB_SIZE(24, 24), 0, 0, 9, 1},
-  {2, UPB_SIZE(0, 0), 0, 0, 3, 1},
-  {3, UPB_SIZE(8, 8), 0, 0, 3, 1},
-  {4, UPB_SIZE(32, 40), UPB_SIZE(-41, -57), 0, 3, 1},
-  {5, UPB_SIZE(32, 40), UPB_SIZE(-41, -57), 0, 12, 1},
-  {6, UPB_SIZE(16, 16), 0, 0, 14, 1},
-};
-
-const upb_msglayout envoy_api_v2_core_SocketOption_msginit = {
-  NULL,
-  &envoy_api_v2_core_SocketOption__fields[0],
-  UPB_SIZE(48, 64), 6, false,
-};
-
 static const upb_msglayout *const envoy_api_v2_core_RuntimeFractionalPercent_submsgs[1] = {
   &envoy_type_FractionalPercent_msginit,
 };
index 2d2070b..191c321 100644 (file)
@@ -14,6 +14,9 @@
 #include "upb/decode.h"
 #include "upb/encode.h"
 
+/* Public Imports. */
+#include "envoy/api/v2/core/socket_option.upb.h"
+
 #include "upb/port_def.inc"
 
 #ifdef __cplusplus
@@ -27,15 +30,16 @@ struct envoy_api_v2_core_Node;
 struct envoy_api_v2_core_Metadata;
 struct envoy_api_v2_core_Metadata_FilterMetadataEntry;
 struct envoy_api_v2_core_RuntimeUInt32;
+struct envoy_api_v2_core_RuntimeDouble;
 struct envoy_api_v2_core_RuntimeFeatureFlag;
 struct envoy_api_v2_core_HeaderValue;
 struct envoy_api_v2_core_HeaderValueOption;
 struct envoy_api_v2_core_HeaderMap;
 struct envoy_api_v2_core_DataSource;
+struct envoy_api_v2_core_RetryPolicy;
 struct envoy_api_v2_core_RemoteDataSource;
 struct envoy_api_v2_core_AsyncDataSource;
 struct envoy_api_v2_core_TransportSocket;
-struct envoy_api_v2_core_SocketOption;
 struct envoy_api_v2_core_RuntimeFractionalPercent;
 struct envoy_api_v2_core_ControlPlane;
 typedef struct envoy_api_v2_core_Locality envoy_api_v2_core_Locality;
@@ -45,15 +49,16 @@ typedef struct envoy_api_v2_core_Node envoy_api_v2_core_Node;
 typedef struct envoy_api_v2_core_Metadata envoy_api_v2_core_Metadata;
 typedef struct envoy_api_v2_core_Metadata_FilterMetadataEntry envoy_api_v2_core_Metadata_FilterMetadataEntry;
 typedef struct envoy_api_v2_core_RuntimeUInt32 envoy_api_v2_core_RuntimeUInt32;
+typedef struct envoy_api_v2_core_RuntimeDouble envoy_api_v2_core_RuntimeDouble;
 typedef struct envoy_api_v2_core_RuntimeFeatureFlag envoy_api_v2_core_RuntimeFeatureFlag;
 typedef struct envoy_api_v2_core_HeaderValue envoy_api_v2_core_HeaderValue;
 typedef struct envoy_api_v2_core_HeaderValueOption envoy_api_v2_core_HeaderValueOption;
 typedef struct envoy_api_v2_core_HeaderMap envoy_api_v2_core_HeaderMap;
 typedef struct envoy_api_v2_core_DataSource envoy_api_v2_core_DataSource;
+typedef struct envoy_api_v2_core_RetryPolicy envoy_api_v2_core_RetryPolicy;
 typedef struct envoy_api_v2_core_RemoteDataSource envoy_api_v2_core_RemoteDataSource;
 typedef struct envoy_api_v2_core_AsyncDataSource envoy_api_v2_core_AsyncDataSource;
 typedef struct envoy_api_v2_core_TransportSocket envoy_api_v2_core_TransportSocket;
-typedef struct envoy_api_v2_core_SocketOption envoy_api_v2_core_SocketOption;
 typedef struct envoy_api_v2_core_RuntimeFractionalPercent envoy_api_v2_core_RuntimeFractionalPercent;
 typedef struct envoy_api_v2_core_ControlPlane envoy_api_v2_core_ControlPlane;
 extern const upb_msglayout envoy_api_v2_core_Locality_msginit;
@@ -63,29 +68,36 @@ extern const upb_msglayout envoy_api_v2_core_Node_msginit;
 extern const upb_msglayout envoy_api_v2_core_Metadata_msginit;
 extern const upb_msglayout envoy_api_v2_core_Metadata_FilterMetadataEntry_msginit;
 extern const upb_msglayout envoy_api_v2_core_RuntimeUInt32_msginit;
+extern const upb_msglayout envoy_api_v2_core_RuntimeDouble_msginit;
 extern const upb_msglayout envoy_api_v2_core_RuntimeFeatureFlag_msginit;
 extern const upb_msglayout envoy_api_v2_core_HeaderValue_msginit;
 extern const upb_msglayout envoy_api_v2_core_HeaderValueOption_msginit;
 extern const upb_msglayout envoy_api_v2_core_HeaderMap_msginit;
 extern const upb_msglayout envoy_api_v2_core_DataSource_msginit;
+extern const upb_msglayout envoy_api_v2_core_RetryPolicy_msginit;
 extern const upb_msglayout envoy_api_v2_core_RemoteDataSource_msginit;
 extern const upb_msglayout envoy_api_v2_core_AsyncDataSource_msginit;
 extern const upb_msglayout envoy_api_v2_core_TransportSocket_msginit;
-extern const upb_msglayout envoy_api_v2_core_SocketOption_msginit;
 extern const upb_msglayout envoy_api_v2_core_RuntimeFractionalPercent_msginit;
 extern const upb_msglayout envoy_api_v2_core_ControlPlane_msginit;
+struct envoy_api_v2_core_Address;
+struct envoy_api_v2_core_BackoffStrategy;
 struct envoy_api_v2_core_HttpUri;
 struct envoy_type_FractionalPercent;
 struct envoy_type_SemanticVersion;
 struct google_protobuf_Any;
 struct google_protobuf_BoolValue;
 struct google_protobuf_Struct;
+struct google_protobuf_UInt32Value;
+extern const upb_msglayout envoy_api_v2_core_Address_msginit;
+extern const upb_msglayout envoy_api_v2_core_BackoffStrategy_msginit;
 extern const upb_msglayout envoy_api_v2_core_HttpUri_msginit;
 extern const upb_msglayout envoy_type_FractionalPercent_msginit;
 extern const upb_msglayout envoy_type_SemanticVersion_msginit;
 extern const upb_msglayout google_protobuf_Any_msginit;
 extern const upb_msglayout google_protobuf_BoolValue_msginit;
 extern const upb_msglayout google_protobuf_Struct_msginit;
+extern const upb_msglayout google_protobuf_UInt32Value_msginit;
 
 typedef enum {
   envoy_api_v2_core_METHOD_UNSPECIFIED = 0,
@@ -106,12 +118,6 @@ typedef enum {
 } envoy_api_v2_core_RoutingPriority;
 
 typedef enum {
-  envoy_api_v2_core_SocketOption_STATE_PREBIND = 0,
-  envoy_api_v2_core_SocketOption_STATE_BOUND = 1,
-  envoy_api_v2_core_SocketOption_STATE_LISTENING = 2
-} envoy_api_v2_core_SocketOption_SocketState;
-
-typedef enum {
   envoy_api_v2_core_UNSPECIFIED = 0,
   envoy_api_v2_core_INBOUND = 1,
   envoy_api_v2_core_OUTBOUND = 2
@@ -252,7 +258,7 @@ typedef enum {
   envoy_api_v2_core_Node_user_agent_version_type_user_agent_build_version = 8,
   envoy_api_v2_core_Node_user_agent_version_type_NOT_SET = 0
 } envoy_api_v2_core_Node_user_agent_version_type_oneofcases;
-UPB_INLINE envoy_api_v2_core_Node_user_agent_version_type_oneofcases envoy_api_v2_core_Node_user_agent_version_type_case(const envoy_api_v2_core_Node* msg) { return (envoy_api_v2_core_Node_user_agent_version_type_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(56, 112)); }
+UPB_INLINE envoy_api_v2_core_Node_user_agent_version_type_oneofcases envoy_api_v2_core_Node_user_agent_version_type_case(const envoy_api_v2_core_Node* msg) { return (envoy_api_v2_core_Node_user_agent_version_type_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(60, 120)); }
 
 UPB_INLINE upb_strview envoy_api_v2_core_Node_id(const envoy_api_v2_core_Node *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
 UPB_INLINE upb_strview envoy_api_v2_core_Node_cluster(const envoy_api_v2_core_Node *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 16)); }
@@ -260,12 +266,13 @@ UPB_INLINE const struct google_protobuf_Struct* envoy_api_v2_core_Node_metadata(
 UPB_INLINE const envoy_api_v2_core_Locality* envoy_api_v2_core_Node_locality(const envoy_api_v2_core_Node *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_core_Locality*, UPB_SIZE(36, 72)); }
 UPB_INLINE upb_strview envoy_api_v2_core_Node_build_version(const envoy_api_v2_core_Node *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(16, 32)); }
 UPB_INLINE upb_strview envoy_api_v2_core_Node_user_agent_name(const envoy_api_v2_core_Node *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(24, 48)); }
-UPB_INLINE bool envoy_api_v2_core_Node_has_user_agent_version(const envoy_api_v2_core_Node *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(56, 112), 7); }
-UPB_INLINE upb_strview envoy_api_v2_core_Node_user_agent_version(const envoy_api_v2_core_Node *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(48, 96), UPB_SIZE(56, 112), 7, upb_strview_make("", strlen(""))); }
-UPB_INLINE bool envoy_api_v2_core_Node_has_user_agent_build_version(const envoy_api_v2_core_Node *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(56, 112), 8); }
-UPB_INLINE const envoy_api_v2_core_BuildVersion* envoy_api_v2_core_Node_user_agent_build_version(const envoy_api_v2_core_Node *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_core_BuildVersion*, UPB_SIZE(48, 96), UPB_SIZE(56, 112), 8, NULL); }
+UPB_INLINE bool envoy_api_v2_core_Node_has_user_agent_version(const envoy_api_v2_core_Node *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(60, 120), 7); }
+UPB_INLINE upb_strview envoy_api_v2_core_Node_user_agent_version(const envoy_api_v2_core_Node *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(52, 104), UPB_SIZE(60, 120), 7, upb_strview_make("", strlen(""))); }
+UPB_INLINE bool envoy_api_v2_core_Node_has_user_agent_build_version(const envoy_api_v2_core_Node *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(60, 120), 8); }
+UPB_INLINE const envoy_api_v2_core_BuildVersion* envoy_api_v2_core_Node_user_agent_build_version(const envoy_api_v2_core_Node *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_core_BuildVersion*, UPB_SIZE(52, 104), UPB_SIZE(60, 120), 8, NULL); }
 UPB_INLINE const envoy_api_v2_core_Extension* const* envoy_api_v2_core_Node_extensions(const envoy_api_v2_core_Node *msg, size_t *len) { return (const envoy_api_v2_core_Extension* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
 UPB_INLINE upb_strview const* envoy_api_v2_core_Node_client_features(const envoy_api_v2_core_Node *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
+UPB_INLINE const struct envoy_api_v2_core_Address* const* envoy_api_v2_core_Node_listening_addresses(const envoy_api_v2_core_Node *msg, size_t *len) { return (const struct envoy_api_v2_core_Address* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); }
 
 UPB_INLINE void envoy_api_v2_core_Node_set_id(envoy_api_v2_core_Node *msg, upb_strview value) {
   UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
@@ -304,10 +311,10 @@ UPB_INLINE void envoy_api_v2_core_Node_set_user_agent_name(envoy_api_v2_core_Nod
   UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(24, 48)) = value;
 }
 UPB_INLINE void envoy_api_v2_core_Node_set_user_agent_version(envoy_api_v2_core_Node *msg, upb_strview value) {
-  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(48, 96), value, UPB_SIZE(56, 112), 7);
+  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(52, 104), value, UPB_SIZE(60, 120), 7);
 }
 UPB_INLINE void envoy_api_v2_core_Node_set_user_agent_build_version(envoy_api_v2_core_Node *msg, envoy_api_v2_core_BuildVersion* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_core_BuildVersion*, UPB_SIZE(48, 96), value, UPB_SIZE(56, 112), 8);
+  UPB_WRITE_ONEOF(msg, envoy_api_v2_core_BuildVersion*, UPB_SIZE(52, 104), value, UPB_SIZE(60, 120), 8);
 }
 UPB_INLINE struct envoy_api_v2_core_BuildVersion* envoy_api_v2_core_Node_mutable_user_agent_build_version(envoy_api_v2_core_Node *msg, upb_arena *arena) {
   struct envoy_api_v2_core_BuildVersion* sub = (struct envoy_api_v2_core_BuildVersion*)envoy_api_v2_core_Node_user_agent_build_version(msg);
@@ -341,6 +348,19 @@ UPB_INLINE bool envoy_api_v2_core_Node_add_client_features(envoy_api_v2_core_Nod
   return _upb_array_append_accessor(
       msg, UPB_SIZE(44, 88), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
 }
+UPB_INLINE struct envoy_api_v2_core_Address** envoy_api_v2_core_Node_mutable_listening_addresses(envoy_api_v2_core_Node *msg, size_t *len) {
+  return (struct envoy_api_v2_core_Address**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len);
+}
+UPB_INLINE struct envoy_api_v2_core_Address** envoy_api_v2_core_Node_resize_listening_addresses(envoy_api_v2_core_Node *msg, size_t len, upb_arena *arena) {
+  return (struct envoy_api_v2_core_Address**)_upb_array_resize_accessor(msg, UPB_SIZE(48, 96), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+}
+UPB_INLINE struct envoy_api_v2_core_Address* envoy_api_v2_core_Node_add_listening_addresses(envoy_api_v2_core_Node *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_Address* sub = (struct envoy_api_v2_core_Address*)upb_msg_new(&envoy_api_v2_core_Address_msginit, arena);
+  bool ok = _upb_array_append_accessor(
+      msg, UPB_SIZE(48, 96), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
 
 /* envoy.api.v2.core.Metadata */
 
@@ -429,6 +449,30 @@ UPB_INLINE void envoy_api_v2_core_RuntimeUInt32_set_runtime_key(envoy_api_v2_cor
   UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
 }
 
+/* envoy.api.v2.core.RuntimeDouble */
+
+UPB_INLINE envoy_api_v2_core_RuntimeDouble *envoy_api_v2_core_RuntimeDouble_new(upb_arena *arena) {
+  return (envoy_api_v2_core_RuntimeDouble *)upb_msg_new(&envoy_api_v2_core_RuntimeDouble_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_core_RuntimeDouble *envoy_api_v2_core_RuntimeDouble_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_core_RuntimeDouble *ret = envoy_api_v2_core_RuntimeDouble_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_core_RuntimeDouble_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_core_RuntimeDouble_serialize(const envoy_api_v2_core_RuntimeDouble *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_core_RuntimeDouble_msginit, arena, len);
+}
+
+UPB_INLINE double envoy_api_v2_core_RuntimeDouble_default_value(const envoy_api_v2_core_RuntimeDouble *msg) { return UPB_FIELD_AT(msg, double, UPB_SIZE(0, 0)); }
+UPB_INLINE upb_strview envoy_api_v2_core_RuntimeDouble_runtime_key(const envoy_api_v2_core_RuntimeDouble *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)); }
+
+UPB_INLINE void envoy_api_v2_core_RuntimeDouble_set_default_value(envoy_api_v2_core_RuntimeDouble *msg, double value) {
+  UPB_FIELD_AT(msg, double, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE void envoy_api_v2_core_RuntimeDouble_set_runtime_key(envoy_api_v2_core_RuntimeDouble *msg, upb_strview value) {
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)) = value;
+}
+
 /* envoy.api.v2.core.RuntimeFeatureFlag */
 
 UPB_INLINE envoy_api_v2_core_RuntimeFeatureFlag *envoy_api_v2_core_RuntimeFeatureFlag_new(upb_arena *arena) {
@@ -597,6 +641,48 @@ UPB_INLINE void envoy_api_v2_core_DataSource_set_inline_string(envoy_api_v2_core
   UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(0, 0), value, UPB_SIZE(8, 16), 3);
 }
 
+/* envoy.api.v2.core.RetryPolicy */
+
+UPB_INLINE envoy_api_v2_core_RetryPolicy *envoy_api_v2_core_RetryPolicy_new(upb_arena *arena) {
+  return (envoy_api_v2_core_RetryPolicy *)upb_msg_new(&envoy_api_v2_core_RetryPolicy_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_core_RetryPolicy *envoy_api_v2_core_RetryPolicy_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_core_RetryPolicy *ret = envoy_api_v2_core_RetryPolicy_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_core_RetryPolicy_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_core_RetryPolicy_serialize(const envoy_api_v2_core_RetryPolicy *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_core_RetryPolicy_msginit, arena, len);
+}
+
+UPB_INLINE const struct envoy_api_v2_core_BackoffStrategy* envoy_api_v2_core_RetryPolicy_retry_back_off(const envoy_api_v2_core_RetryPolicy *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_BackoffStrategy*, UPB_SIZE(0, 0)); }
+UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_core_RetryPolicy_num_retries(const envoy_api_v2_core_RetryPolicy *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(4, 8)); }
+
+UPB_INLINE void envoy_api_v2_core_RetryPolicy_set_retry_back_off(envoy_api_v2_core_RetryPolicy *msg, struct envoy_api_v2_core_BackoffStrategy* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_core_BackoffStrategy*, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE struct envoy_api_v2_core_BackoffStrategy* envoy_api_v2_core_RetryPolicy_mutable_retry_back_off(envoy_api_v2_core_RetryPolicy *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_BackoffStrategy* sub = (struct envoy_api_v2_core_BackoffStrategy*)envoy_api_v2_core_RetryPolicy_retry_back_off(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_BackoffStrategy*)upb_msg_new(&envoy_api_v2_core_BackoffStrategy_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_core_RetryPolicy_set_retry_back_off(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_core_RetryPolicy_set_num_retries(envoy_api_v2_core_RetryPolicy *msg, struct google_protobuf_UInt32Value* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_UInt32Value*, UPB_SIZE(4, 8)) = value;
+}
+UPB_INLINE struct google_protobuf_UInt32Value* envoy_api_v2_core_RetryPolicy_mutable_num_retries(envoy_api_v2_core_RetryPolicy *msg, upb_arena *arena) {
+  struct google_protobuf_UInt32Value* sub = (struct google_protobuf_UInt32Value*)envoy_api_v2_core_RetryPolicy_num_retries(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_UInt32Value*)upb_msg_new(&google_protobuf_UInt32Value_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_core_RetryPolicy_set_num_retries(msg, sub);
+  }
+  return sub;
+}
+
 /* envoy.api.v2.core.RemoteDataSource */
 
 UPB_INLINE envoy_api_v2_core_RemoteDataSource *envoy_api_v2_core_RemoteDataSource_new(upb_arena *arena) {
@@ -613,6 +699,7 @@ UPB_INLINE char *envoy_api_v2_core_RemoteDataSource_serialize(const envoy_api_v2
 
 UPB_INLINE const struct envoy_api_v2_core_HttpUri* envoy_api_v2_core_RemoteDataSource_http_uri(const envoy_api_v2_core_RemoteDataSource *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_HttpUri*, UPB_SIZE(8, 16)); }
 UPB_INLINE upb_strview envoy_api_v2_core_RemoteDataSource_sha256(const envoy_api_v2_core_RemoteDataSource *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
+UPB_INLINE const envoy_api_v2_core_RetryPolicy* envoy_api_v2_core_RemoteDataSource_retry_policy(const envoy_api_v2_core_RemoteDataSource *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_core_RetryPolicy*, UPB_SIZE(12, 24)); }
 
 UPB_INLINE void envoy_api_v2_core_RemoteDataSource_set_http_uri(envoy_api_v2_core_RemoteDataSource *msg, struct envoy_api_v2_core_HttpUri* value) {
   UPB_FIELD_AT(msg, struct envoy_api_v2_core_HttpUri*, UPB_SIZE(8, 16)) = value;
@@ -629,6 +716,18 @@ UPB_INLINE struct envoy_api_v2_core_HttpUri* envoy_api_v2_core_RemoteDataSource_
 UPB_INLINE void envoy_api_v2_core_RemoteDataSource_set_sha256(envoy_api_v2_core_RemoteDataSource *msg, upb_strview value) {
   UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
 }
+UPB_INLINE void envoy_api_v2_core_RemoteDataSource_set_retry_policy(envoy_api_v2_core_RemoteDataSource *msg, envoy_api_v2_core_RetryPolicy* value) {
+  UPB_FIELD_AT(msg, envoy_api_v2_core_RetryPolicy*, UPB_SIZE(12, 24)) = value;
+}
+UPB_INLINE struct envoy_api_v2_core_RetryPolicy* envoy_api_v2_core_RemoteDataSource_mutable_retry_policy(envoy_api_v2_core_RemoteDataSource *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_RetryPolicy* sub = (struct envoy_api_v2_core_RetryPolicy*)envoy_api_v2_core_RemoteDataSource_retry_policy(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_RetryPolicy*)upb_msg_new(&envoy_api_v2_core_RetryPolicy_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_core_RemoteDataSource_set_retry_policy(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.api.v2.core.AsyncDataSource */
 
@@ -736,55 +835,6 @@ UPB_INLINE struct google_protobuf_Any* envoy_api_v2_core_TransportSocket_mutable
   return sub;
 }
 
-/* envoy.api.v2.core.SocketOption */
-
-UPB_INLINE envoy_api_v2_core_SocketOption *envoy_api_v2_core_SocketOption_new(upb_arena *arena) {
-  return (envoy_api_v2_core_SocketOption *)upb_msg_new(&envoy_api_v2_core_SocketOption_msginit, arena);
-}
-UPB_INLINE envoy_api_v2_core_SocketOption *envoy_api_v2_core_SocketOption_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  envoy_api_v2_core_SocketOption *ret = envoy_api_v2_core_SocketOption_new(arena);
-  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_core_SocketOption_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *envoy_api_v2_core_SocketOption_serialize(const envoy_api_v2_core_SocketOption *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &envoy_api_v2_core_SocketOption_msginit, arena, len);
-}
-
-typedef enum {
-  envoy_api_v2_core_SocketOption_value_int_value = 4,
-  envoy_api_v2_core_SocketOption_value_buf_value = 5,
-  envoy_api_v2_core_SocketOption_value_NOT_SET = 0
-} envoy_api_v2_core_SocketOption_value_oneofcases;
-UPB_INLINE envoy_api_v2_core_SocketOption_value_oneofcases envoy_api_v2_core_SocketOption_value_case(const envoy_api_v2_core_SocketOption* msg) { return (envoy_api_v2_core_SocketOption_value_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(40, 56)); }
-
-UPB_INLINE upb_strview envoy_api_v2_core_SocketOption_description(const envoy_api_v2_core_SocketOption *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(24, 24)); }
-UPB_INLINE int64_t envoy_api_v2_core_SocketOption_level(const envoy_api_v2_core_SocketOption *msg) { return UPB_FIELD_AT(msg, int64_t, UPB_SIZE(0, 0)); }
-UPB_INLINE int64_t envoy_api_v2_core_SocketOption_name(const envoy_api_v2_core_SocketOption *msg) { return UPB_FIELD_AT(msg, int64_t, UPB_SIZE(8, 8)); }
-UPB_INLINE bool envoy_api_v2_core_SocketOption_has_int_value(const envoy_api_v2_core_SocketOption *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(40, 56), 4); }
-UPB_INLINE int64_t envoy_api_v2_core_SocketOption_int_value(const envoy_api_v2_core_SocketOption *msg) { return UPB_READ_ONEOF(msg, int64_t, UPB_SIZE(32, 40), UPB_SIZE(40, 56), 4, 0); }
-UPB_INLINE bool envoy_api_v2_core_SocketOption_has_buf_value(const envoy_api_v2_core_SocketOption *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(40, 56), 5); }
-UPB_INLINE upb_strview envoy_api_v2_core_SocketOption_buf_value(const envoy_api_v2_core_SocketOption *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(32, 40), UPB_SIZE(40, 56), 5, upb_strview_make("", strlen(""))); }
-UPB_INLINE int32_t envoy_api_v2_core_SocketOption_state(const envoy_api_v2_core_SocketOption *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); }
-
-UPB_INLINE void envoy_api_v2_core_SocketOption_set_description(envoy_api_v2_core_SocketOption *msg, upb_strview value) {
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(24, 24)) = value;
-}
-UPB_INLINE void envoy_api_v2_core_SocketOption_set_level(envoy_api_v2_core_SocketOption *msg, int64_t value) {
-  UPB_FIELD_AT(msg, int64_t, UPB_SIZE(0, 0)) = value;
-}
-UPB_INLINE void envoy_api_v2_core_SocketOption_set_name(envoy_api_v2_core_SocketOption *msg, int64_t value) {
-  UPB_FIELD_AT(msg, int64_t, UPB_SIZE(8, 8)) = value;
-}
-UPB_INLINE void envoy_api_v2_core_SocketOption_set_int_value(envoy_api_v2_core_SocketOption *msg, int64_t value) {
-  UPB_WRITE_ONEOF(msg, int64_t, UPB_SIZE(32, 40), value, UPB_SIZE(40, 56), 4);
-}
-UPB_INLINE void envoy_api_v2_core_SocketOption_set_buf_value(envoy_api_v2_core_SocketOption *msg, upb_strview value) {
-  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(32, 40), value, UPB_SIZE(40, 56), 5);
-}
-UPB_INLINE void envoy_api_v2_core_SocketOption_set_state(envoy_api_v2_core_SocketOption *msg, int32_t value) {
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)) = value;
-}
-
 /* envoy.api.v2.core.RuntimeFractionalPercent */
 
 UPB_INLINE envoy_api_v2_core_RuntimeFractionalPercent *envoy_api_v2_core_RuntimeFractionalPercent_new(upb_arena *arena) {
index dd17a79..3f0fc4c 100644 (file)
@@ -14,6 +14,7 @@
 #include "google/protobuf/wrappers.upb.h"
 #include "envoy/annotations/deprecation.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
diff --git a/src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c b/src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c
new file mode 100644 (file)
index 0000000..5c7d8ab
--- /dev/null
@@ -0,0 +1,34 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/core/event_service_config.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg.h"
+#include "envoy/api/v2/core/event_service_config.upb.h"
+#include "envoy/api/v2/core/grpc_service.upb.h"
+#include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
+#include "validate/validate.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout *const envoy_api_v2_core_EventServiceConfig_submsgs[1] = {
+  &envoy_api_v2_core_GrpcService_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_core_EventServiceConfig__fields[1] = {
+  {1, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 0, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_core_EventServiceConfig_msginit = {
+  &envoy_api_v2_core_EventServiceConfig_submsgs[0],
+  &envoy_api_v2_core_EventServiceConfig__fields[0],
+  UPB_SIZE(8, 16), 1, false,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h b/src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h
new file mode 100644 (file)
index 0000000..47cc54d
--- /dev/null
@@ -0,0 +1,72 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/core/event_service_config.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef ENVOY_API_V2_CORE_EVENT_SERVICE_CONFIG_PROTO_UPB_H_
+#define ENVOY_API_V2_CORE_EVENT_SERVICE_CONFIG_PROTO_UPB_H_
+
+#include "upb/generated_util.h"
+#include "upb/msg.h"
+#include "upb/decode.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct envoy_api_v2_core_EventServiceConfig;
+typedef struct envoy_api_v2_core_EventServiceConfig envoy_api_v2_core_EventServiceConfig;
+extern const upb_msglayout envoy_api_v2_core_EventServiceConfig_msginit;
+struct envoy_api_v2_core_GrpcService;
+extern const upb_msglayout envoy_api_v2_core_GrpcService_msginit;
+
+
+/* envoy.api.v2.core.EventServiceConfig */
+
+UPB_INLINE envoy_api_v2_core_EventServiceConfig *envoy_api_v2_core_EventServiceConfig_new(upb_arena *arena) {
+  return (envoy_api_v2_core_EventServiceConfig *)upb_msg_new(&envoy_api_v2_core_EventServiceConfig_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_core_EventServiceConfig *envoy_api_v2_core_EventServiceConfig_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_core_EventServiceConfig *ret = envoy_api_v2_core_EventServiceConfig_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_core_EventServiceConfig_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_core_EventServiceConfig_serialize(const envoy_api_v2_core_EventServiceConfig *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_core_EventServiceConfig_msginit, arena, len);
+}
+
+typedef enum {
+  envoy_api_v2_core_EventServiceConfig_config_source_specifier_grpc_service = 1,
+  envoy_api_v2_core_EventServiceConfig_config_source_specifier_NOT_SET = 0
+} envoy_api_v2_core_EventServiceConfig_config_source_specifier_oneofcases;
+UPB_INLINE envoy_api_v2_core_EventServiceConfig_config_source_specifier_oneofcases envoy_api_v2_core_EventServiceConfig_config_source_specifier_case(const envoy_api_v2_core_EventServiceConfig* msg) { return (envoy_api_v2_core_EventServiceConfig_config_source_specifier_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 8)); }
+
+UPB_INLINE bool envoy_api_v2_core_EventServiceConfig_has_grpc_service(const envoy_api_v2_core_EventServiceConfig *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(4, 8), 1); }
+UPB_INLINE const struct envoy_api_v2_core_GrpcService* envoy_api_v2_core_EventServiceConfig_grpc_service(const envoy_api_v2_core_EventServiceConfig *msg) { return UPB_READ_ONEOF(msg, const struct envoy_api_v2_core_GrpcService*, UPB_SIZE(0, 0), UPB_SIZE(4, 8), 1, NULL); }
+
+UPB_INLINE void envoy_api_v2_core_EventServiceConfig_set_grpc_service(envoy_api_v2_core_EventServiceConfig *msg, struct envoy_api_v2_core_GrpcService* value) {
+  UPB_WRITE_ONEOF(msg, struct envoy_api_v2_core_GrpcService*, UPB_SIZE(0, 0), value, UPB_SIZE(4, 8), 1);
+}
+UPB_INLINE struct envoy_api_v2_core_GrpcService* envoy_api_v2_core_EventServiceConfig_mutable_grpc_service(envoy_api_v2_core_EventServiceConfig *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_GrpcService* sub = (struct envoy_api_v2_core_GrpcService*)envoy_api_v2_core_EventServiceConfig_grpc_service(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_GrpcService*)upb_msg_new(&envoy_api_v2_core_GrpcService_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_core_EventServiceConfig_set_grpc_service(msg, sub);
+  }
+  return sub;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* ENVOY_API_V2_CORE_EVENT_SERVICE_CONFIG_PROTO_UPB_H_ */
index f1b76b8..bcf33a0 100644 (file)
@@ -14,8 +14,9 @@
 #include "google/protobuf/duration.upb.h"
 #include "google/protobuf/empty.upb.h"
 #include "google/protobuf/struct.upb.h"
-#include "udpa/annotations/sensitive.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/sensitive.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index 01573eb..f62e741 100644 (file)
@@ -10,6 +10,7 @@
 #include "upb/msg.h"
 #include "envoy/api/v2/core/health_check.upb.h"
 #include "envoy/api/v2/core/base.upb.h"
+#include "envoy/api/v2/core/event_service_config.upb.h"
 #include "envoy/type/http.upb.h"
 #include "envoy/type/matcher/string.upb.h"
 #include "envoy/type/range.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "envoy/annotations/deprecation.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
 
-static const upb_msglayout *const envoy_api_v2_core_HealthCheck_submsgs[17] = {
+static const upb_msglayout *const envoy_api_v2_core_HealthCheck_submsgs[18] = {
+  &envoy_api_v2_core_EventServiceConfig_msginit,
   &envoy_api_v2_core_HealthCheck_CustomHealthCheck_msginit,
   &envoy_api_v2_core_HealthCheck_GrpcHealthCheck_msginit,
   &envoy_api_v2_core_HealthCheck_HttpHealthCheck_msginit,
@@ -34,33 +37,34 @@ static const upb_msglayout *const envoy_api_v2_core_HealthCheck_submsgs[17] = {
   &google_protobuf_UInt32Value_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_core_HealthCheck__fields[20] = {
-  {1, UPB_SIZE(16, 24), 0, 6, 11, 1},
-  {2, UPB_SIZE(20, 32), 0, 6, 11, 1},
-  {3, UPB_SIZE(24, 40), 0, 6, 11, 1},
-  {4, UPB_SIZE(28, 48), 0, 7, 11, 1},
-  {5, UPB_SIZE(32, 56), 0, 7, 11, 1},
-  {6, UPB_SIZE(36, 64), 0, 7, 11, 1},
-  {7, UPB_SIZE(40, 72), 0, 5, 11, 1},
-  {8, UPB_SIZE(68, 128), UPB_SIZE(-73, -137), 2, 11, 1},
-  {9, UPB_SIZE(68, 128), UPB_SIZE(-73, -137), 3, 11, 1},
-  {11, UPB_SIZE(68, 128), UPB_SIZE(-73, -137), 1, 11, 1},
-  {12, UPB_SIZE(44, 80), 0, 6, 11, 1},
-  {13, UPB_SIZE(68, 128), UPB_SIZE(-73, -137), 0, 11, 1},
-  {14, UPB_SIZE(48, 88), 0, 6, 11, 1},
-  {15, UPB_SIZE(52, 96), 0, 6, 11, 1},
-  {16, UPB_SIZE(56, 104), 0, 6, 11, 1},
+static const upb_msglayout_field envoy_api_v2_core_HealthCheck__fields[21] = {
+  {1, UPB_SIZE(16, 24), 0, 7, 11, 1},
+  {2, UPB_SIZE(20, 32), 0, 7, 11, 1},
+  {3, UPB_SIZE(24, 40), 0, 7, 11, 1},
+  {4, UPB_SIZE(28, 48), 0, 8, 11, 1},
+  {5, UPB_SIZE(32, 56), 0, 8, 11, 1},
+  {6, UPB_SIZE(36, 64), 0, 8, 11, 1},
+  {7, UPB_SIZE(40, 72), 0, 6, 11, 1},
+  {8, UPB_SIZE(72, 136), UPB_SIZE(-77, -145), 3, 11, 1},
+  {9, UPB_SIZE(72, 136), UPB_SIZE(-77, -145), 4, 11, 1},
+  {11, UPB_SIZE(72, 136), UPB_SIZE(-77, -145), 2, 11, 1},
+  {12, UPB_SIZE(44, 80), 0, 7, 11, 1},
+  {13, UPB_SIZE(72, 136), UPB_SIZE(-77, -145), 1, 11, 1},
+  {14, UPB_SIZE(48, 88), 0, 7, 11, 1},
+  {15, UPB_SIZE(52, 96), 0, 7, 11, 1},
+  {16, UPB_SIZE(56, 104), 0, 7, 11, 1},
   {17, UPB_SIZE(8, 8), 0, 0, 9, 1},
   {18, UPB_SIZE(0, 0), 0, 0, 13, 1},
   {19, UPB_SIZE(4, 4), 0, 0, 8, 1},
-  {20, UPB_SIZE(60, 112), 0, 6, 11, 1},
-  {21, UPB_SIZE(64, 120), 0, 4, 11, 1},
+  {20, UPB_SIZE(60, 112), 0, 7, 11, 1},
+  {21, UPB_SIZE(64, 120), 0, 5, 11, 1},
+  {22, UPB_SIZE(68, 128), 0, 0, 11, 1},
 };
 
 const upb_msglayout envoy_api_v2_core_HealthCheck_msginit = {
   &envoy_api_v2_core_HealthCheck_submsgs[0],
   &envoy_api_v2_core_HealthCheck__fields[0],
-  UPB_SIZE(80, 144), 20, false,
+  UPB_SIZE(80, 160), 21, false,
 };
 
 static const upb_msglayout_field envoy_api_v2_core_HealthCheck_Payload__fields[2] = {
index 587beac..bfe7af1 100644 (file)
@@ -44,6 +44,7 @@ extern const upb_msglayout envoy_api_v2_core_HealthCheck_RedisHealthCheck_msgini
 extern const upb_msglayout envoy_api_v2_core_HealthCheck_GrpcHealthCheck_msginit;
 extern const upb_msglayout envoy_api_v2_core_HealthCheck_CustomHealthCheck_msginit;
 extern const upb_msglayout envoy_api_v2_core_HealthCheck_TlsOptions_msginit;
+struct envoy_api_v2_core_EventServiceConfig;
 struct envoy_api_v2_core_HeaderValueOption;
 struct envoy_type_Int64Range;
 struct envoy_type_matcher_StringMatcher;
@@ -52,6 +53,7 @@ struct google_protobuf_BoolValue;
 struct google_protobuf_Duration;
 struct google_protobuf_Struct;
 struct google_protobuf_UInt32Value;
+extern const upb_msglayout envoy_api_v2_core_EventServiceConfig_msginit;
 extern const upb_msglayout envoy_api_v2_core_HeaderValueOption_msginit;
 extern const upb_msglayout envoy_type_Int64Range_msginit;
 extern const upb_msglayout envoy_type_matcher_StringMatcher_msginit;
@@ -92,7 +94,7 @@ typedef enum {
   envoy_api_v2_core_HealthCheck_health_checker_custom_health_check = 13,
   envoy_api_v2_core_HealthCheck_health_checker_NOT_SET = 0
 } envoy_api_v2_core_HealthCheck_health_checker_oneofcases;
-UPB_INLINE envoy_api_v2_core_HealthCheck_health_checker_oneofcases envoy_api_v2_core_HealthCheck_health_checker_case(const envoy_api_v2_core_HealthCheck* msg) { return (envoy_api_v2_core_HealthCheck_health_checker_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(72, 136)); }
+UPB_INLINE envoy_api_v2_core_HealthCheck_health_checker_oneofcases envoy_api_v2_core_HealthCheck_health_checker_case(const envoy_api_v2_core_HealthCheck* msg) { return (envoy_api_v2_core_HealthCheck_health_checker_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(76, 144)); }
 
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HealthCheck_timeout(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(16, 24)); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HealthCheck_interval(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(20, 32)); }
@@ -101,15 +103,15 @@ UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_core_HealthChe
 UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_core_HealthCheck_healthy_threshold(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(32, 56)); }
 UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_core_HealthCheck_alt_port(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(36, 64)); }
 UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_core_HealthCheck_reuse_connection(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(40, 72)); }
-UPB_INLINE bool envoy_api_v2_core_HealthCheck_has_http_health_check(const envoy_api_v2_core_HealthCheck *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(72, 136), 8); }
-UPB_INLINE const envoy_api_v2_core_HealthCheck_HttpHealthCheck* envoy_api_v2_core_HealthCheck_http_health_check(const envoy_api_v2_core_HealthCheck *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_core_HealthCheck_HttpHealthCheck*, UPB_SIZE(68, 128), UPB_SIZE(72, 136), 8, NULL); }
-UPB_INLINE bool envoy_api_v2_core_HealthCheck_has_tcp_health_check(const envoy_api_v2_core_HealthCheck *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(72, 136), 9); }
-UPB_INLINE const envoy_api_v2_core_HealthCheck_TcpHealthCheck* envoy_api_v2_core_HealthCheck_tcp_health_check(const envoy_api_v2_core_HealthCheck *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_core_HealthCheck_TcpHealthCheck*, UPB_SIZE(68, 128), UPB_SIZE(72, 136), 9, NULL); }
-UPB_INLINE bool envoy_api_v2_core_HealthCheck_has_grpc_health_check(const envoy_api_v2_core_HealthCheck *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(72, 136), 11); }
-UPB_INLINE const envoy_api_v2_core_HealthCheck_GrpcHealthCheck* envoy_api_v2_core_HealthCheck_grpc_health_check(const envoy_api_v2_core_HealthCheck *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_core_HealthCheck_GrpcHealthCheck*, UPB_SIZE(68, 128), UPB_SIZE(72, 136), 11, NULL); }
+UPB_INLINE bool envoy_api_v2_core_HealthCheck_has_http_health_check(const envoy_api_v2_core_HealthCheck *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(76, 144), 8); }
+UPB_INLINE const envoy_api_v2_core_HealthCheck_HttpHealthCheck* envoy_api_v2_core_HealthCheck_http_health_check(const envoy_api_v2_core_HealthCheck *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_core_HealthCheck_HttpHealthCheck*, UPB_SIZE(72, 136), UPB_SIZE(76, 144), 8, NULL); }
+UPB_INLINE bool envoy_api_v2_core_HealthCheck_has_tcp_health_check(const envoy_api_v2_core_HealthCheck *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(76, 144), 9); }
+UPB_INLINE const envoy_api_v2_core_HealthCheck_TcpHealthCheck* envoy_api_v2_core_HealthCheck_tcp_health_check(const envoy_api_v2_core_HealthCheck *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_core_HealthCheck_TcpHealthCheck*, UPB_SIZE(72, 136), UPB_SIZE(76, 144), 9, NULL); }
+UPB_INLINE bool envoy_api_v2_core_HealthCheck_has_grpc_health_check(const envoy_api_v2_core_HealthCheck *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(76, 144), 11); }
+UPB_INLINE const envoy_api_v2_core_HealthCheck_GrpcHealthCheck* envoy_api_v2_core_HealthCheck_grpc_health_check(const envoy_api_v2_core_HealthCheck *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_core_HealthCheck_GrpcHealthCheck*, UPB_SIZE(72, 136), UPB_SIZE(76, 144), 11, NULL); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HealthCheck_no_traffic_interval(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(44, 80)); }
-UPB_INLINE bool envoy_api_v2_core_HealthCheck_has_custom_health_check(const envoy_api_v2_core_HealthCheck *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(72, 136), 13); }
-UPB_INLINE const envoy_api_v2_core_HealthCheck_CustomHealthCheck* envoy_api_v2_core_HealthCheck_custom_health_check(const envoy_api_v2_core_HealthCheck *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_core_HealthCheck_CustomHealthCheck*, UPB_SIZE(68, 128), UPB_SIZE(72, 136), 13, NULL); }
+UPB_INLINE bool envoy_api_v2_core_HealthCheck_has_custom_health_check(const envoy_api_v2_core_HealthCheck *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(76, 144), 13); }
+UPB_INLINE const envoy_api_v2_core_HealthCheck_CustomHealthCheck* envoy_api_v2_core_HealthCheck_custom_health_check(const envoy_api_v2_core_HealthCheck *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_core_HealthCheck_CustomHealthCheck*, UPB_SIZE(72, 136), UPB_SIZE(76, 144), 13, NULL); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HealthCheck_unhealthy_interval(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(48, 88)); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HealthCheck_unhealthy_edge_interval(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(52, 96)); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HealthCheck_healthy_edge_interval(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(56, 104)); }
@@ -118,6 +120,7 @@ UPB_INLINE uint32_t envoy_api_v2_core_HealthCheck_interval_jitter_percent(const
 UPB_INLINE bool envoy_api_v2_core_HealthCheck_always_log_health_check_failures(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(4, 4)); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HealthCheck_initial_jitter(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(60, 112)); }
 UPB_INLINE const envoy_api_v2_core_HealthCheck_TlsOptions* envoy_api_v2_core_HealthCheck_tls_options(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_core_HealthCheck_TlsOptions*, UPB_SIZE(64, 120)); }
+UPB_INLINE const struct envoy_api_v2_core_EventServiceConfig* envoy_api_v2_core_HealthCheck_event_service(const envoy_api_v2_core_HealthCheck *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_EventServiceConfig*, UPB_SIZE(68, 128)); }
 
 UPB_INLINE void envoy_api_v2_core_HealthCheck_set_timeout(envoy_api_v2_core_HealthCheck *msg, struct google_protobuf_Duration* value) {
   UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(16, 24)) = value;
@@ -204,7 +207,7 @@ UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_core_HealthCheck_mutab
   return sub;
 }
 UPB_INLINE void envoy_api_v2_core_HealthCheck_set_http_health_check(envoy_api_v2_core_HealthCheck *msg, envoy_api_v2_core_HealthCheck_HttpHealthCheck* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_core_HealthCheck_HttpHealthCheck*, UPB_SIZE(68, 128), value, UPB_SIZE(72, 136), 8);
+  UPB_WRITE_ONEOF(msg, envoy_api_v2_core_HealthCheck_HttpHealthCheck*, UPB_SIZE(72, 136), value, UPB_SIZE(76, 144), 8);
 }
 UPB_INLINE struct envoy_api_v2_core_HealthCheck_HttpHealthCheck* envoy_api_v2_core_HealthCheck_mutable_http_health_check(envoy_api_v2_core_HealthCheck *msg, upb_arena *arena) {
   struct envoy_api_v2_core_HealthCheck_HttpHealthCheck* sub = (struct envoy_api_v2_core_HealthCheck_HttpHealthCheck*)envoy_api_v2_core_HealthCheck_http_health_check(msg);
@@ -216,7 +219,7 @@ UPB_INLINE struct envoy_api_v2_core_HealthCheck_HttpHealthCheck* envoy_api_v2_co
   return sub;
 }
 UPB_INLINE void envoy_api_v2_core_HealthCheck_set_tcp_health_check(envoy_api_v2_core_HealthCheck *msg, envoy_api_v2_core_HealthCheck_TcpHealthCheck* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_core_HealthCheck_TcpHealthCheck*, UPB_SIZE(68, 128), value, UPB_SIZE(72, 136), 9);
+  UPB_WRITE_ONEOF(msg, envoy_api_v2_core_HealthCheck_TcpHealthCheck*, UPB_SIZE(72, 136), value, UPB_SIZE(76, 144), 9);
 }
 UPB_INLINE struct envoy_api_v2_core_HealthCheck_TcpHealthCheck* envoy_api_v2_core_HealthCheck_mutable_tcp_health_check(envoy_api_v2_core_HealthCheck *msg, upb_arena *arena) {
   struct envoy_api_v2_core_HealthCheck_TcpHealthCheck* sub = (struct envoy_api_v2_core_HealthCheck_TcpHealthCheck*)envoy_api_v2_core_HealthCheck_tcp_health_check(msg);
@@ -228,7 +231,7 @@ UPB_INLINE struct envoy_api_v2_core_HealthCheck_TcpHealthCheck* envoy_api_v2_cor
   return sub;
 }
 UPB_INLINE void envoy_api_v2_core_HealthCheck_set_grpc_health_check(envoy_api_v2_core_HealthCheck *msg, envoy_api_v2_core_HealthCheck_GrpcHealthCheck* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_core_HealthCheck_GrpcHealthCheck*, UPB_SIZE(68, 128), value, UPB_SIZE(72, 136), 11);
+  UPB_WRITE_ONEOF(msg, envoy_api_v2_core_HealthCheck_GrpcHealthCheck*, UPB_SIZE(72, 136), value, UPB_SIZE(76, 144), 11);
 }
 UPB_INLINE struct envoy_api_v2_core_HealthCheck_GrpcHealthCheck* envoy_api_v2_core_HealthCheck_mutable_grpc_health_check(envoy_api_v2_core_HealthCheck *msg, upb_arena *arena) {
   struct envoy_api_v2_core_HealthCheck_GrpcHealthCheck* sub = (struct envoy_api_v2_core_HealthCheck_GrpcHealthCheck*)envoy_api_v2_core_HealthCheck_grpc_health_check(msg);
@@ -252,7 +255,7 @@ UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_core_HealthCheck_mutabl
   return sub;
 }
 UPB_INLINE void envoy_api_v2_core_HealthCheck_set_custom_health_check(envoy_api_v2_core_HealthCheck *msg, envoy_api_v2_core_HealthCheck_CustomHealthCheck* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_core_HealthCheck_CustomHealthCheck*, UPB_SIZE(68, 128), value, UPB_SIZE(72, 136), 13);
+  UPB_WRITE_ONEOF(msg, envoy_api_v2_core_HealthCheck_CustomHealthCheck*, UPB_SIZE(72, 136), value, UPB_SIZE(76, 144), 13);
 }
 UPB_INLINE struct envoy_api_v2_core_HealthCheck_CustomHealthCheck* envoy_api_v2_core_HealthCheck_mutable_custom_health_check(envoy_api_v2_core_HealthCheck *msg, upb_arena *arena) {
   struct envoy_api_v2_core_HealthCheck_CustomHealthCheck* sub = (struct envoy_api_v2_core_HealthCheck_CustomHealthCheck*)envoy_api_v2_core_HealthCheck_custom_health_check(msg);
@@ -332,6 +335,18 @@ UPB_INLINE struct envoy_api_v2_core_HealthCheck_TlsOptions* envoy_api_v2_core_He
   }
   return sub;
 }
+UPB_INLINE void envoy_api_v2_core_HealthCheck_set_event_service(envoy_api_v2_core_HealthCheck *msg, struct envoy_api_v2_core_EventServiceConfig* value) {
+  UPB_FIELD_AT(msg, struct envoy_api_v2_core_EventServiceConfig*, UPB_SIZE(68, 128)) = value;
+}
+UPB_INLINE struct envoy_api_v2_core_EventServiceConfig* envoy_api_v2_core_HealthCheck_mutable_event_service(envoy_api_v2_core_HealthCheck *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_EventServiceConfig* sub = (struct envoy_api_v2_core_EventServiceConfig*)envoy_api_v2_core_HealthCheck_event_service(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_core_EventServiceConfig*)upb_msg_new(&envoy_api_v2_core_EventServiceConfig_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_core_HealthCheck_set_event_service(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.api.v2.core.HealthCheck.Payload */
 
index 4bd6c61..34e945c 100644 (file)
@@ -11,6 +11,7 @@
 #include "envoy/api/v2/core/http_uri.upb.h"
 #include "google/protobuf/duration.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index 9822299..07d783c 100644 (file)
@@ -12,6 +12,7 @@
 #include "google/protobuf/duration.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
@@ -33,21 +34,23 @@ const upb_msglayout envoy_api_v2_core_UpstreamHttpProtocolOptions_msginit = {
   UPB_SIZE(2, 2), 2, false,
 };
 
-static const upb_msglayout *const envoy_api_v2_core_HttpProtocolOptions_submsgs[3] = {
+static const upb_msglayout *const envoy_api_v2_core_HttpProtocolOptions_submsgs[4] = {
   &google_protobuf_Duration_msginit,
   &google_protobuf_UInt32Value_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_core_HttpProtocolOptions__fields[3] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
-  {2, UPB_SIZE(4, 8), 0, 1, 11, 1},
-  {3, UPB_SIZE(8, 16), 0, 0, 11, 1},
+static const upb_msglayout_field envoy_api_v2_core_HttpProtocolOptions__fields[5] = {
+  {1, UPB_SIZE(8, 8), 0, 0, 11, 1},
+  {2, UPB_SIZE(12, 16), 0, 1, 11, 1},
+  {3, UPB_SIZE(16, 24), 0, 0, 11, 1},
+  {4, UPB_SIZE(20, 32), 0, 0, 11, 1},
+  {5, UPB_SIZE(0, 0), 0, 0, 14, 1},
 };
 
 const upb_msglayout envoy_api_v2_core_HttpProtocolOptions_msginit = {
   &envoy_api_v2_core_HttpProtocolOptions_submsgs[0],
   &envoy_api_v2_core_HttpProtocolOptions__fields[0],
-  UPB_SIZE(12, 24), 3, false,
+  UPB_SIZE(24, 40), 5, false,
 };
 
 static const upb_msglayout *const envoy_api_v2_core_Http1ProtocolOptions_submsgs[2] = {
@@ -89,29 +92,46 @@ const upb_msglayout envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat_Prope
   UPB_SIZE(0, 0), 0, false,
 };
 
-static const upb_msglayout *const envoy_api_v2_core_Http2ProtocolOptions_submsgs[9] = {
+static const upb_msglayout *const envoy_api_v2_core_Http2ProtocolOptions_submsgs[10] = {
+  &envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_msginit,
   &google_protobuf_UInt32Value_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_core_Http2ProtocolOptions__fields[12] = {
-  {1, UPB_SIZE(4, 8), 0, 0, 11, 1},
-  {2, UPB_SIZE(8, 16), 0, 0, 11, 1},
-  {3, UPB_SIZE(12, 24), 0, 0, 11, 1},
-  {4, UPB_SIZE(16, 32), 0, 0, 11, 1},
+static const upb_msglayout_field envoy_api_v2_core_Http2ProtocolOptions__fields[13] = {
+  {1, UPB_SIZE(4, 8), 0, 1, 11, 1},
+  {2, UPB_SIZE(8, 16), 0, 1, 11, 1},
+  {3, UPB_SIZE(12, 24), 0, 1, 11, 1},
+  {4, UPB_SIZE(16, 32), 0, 1, 11, 1},
   {5, UPB_SIZE(0, 0), 0, 0, 8, 1},
   {6, UPB_SIZE(1, 1), 0, 0, 8, 1},
-  {7, UPB_SIZE(20, 40), 0, 0, 11, 1},
-  {8, UPB_SIZE(24, 48), 0, 0, 11, 1},
-  {9, UPB_SIZE(28, 56), 0, 0, 11, 1},
-  {10, UPB_SIZE(32, 64), 0, 0, 11, 1},
-  {11, UPB_SIZE(36, 72), 0, 0, 11, 1},
+  {7, UPB_SIZE(20, 40), 0, 1, 11, 1},
+  {8, UPB_SIZE(24, 48), 0, 1, 11, 1},
+  {9, UPB_SIZE(28, 56), 0, 1, 11, 1},
+  {10, UPB_SIZE(32, 64), 0, 1, 11, 1},
+  {11, UPB_SIZE(36, 72), 0, 1, 11, 1},
   {12, UPB_SIZE(2, 2), 0, 0, 8, 1},
+  {13, UPB_SIZE(40, 80), 0, 0, 11, 3},
 };
 
 const upb_msglayout envoy_api_v2_core_Http2ProtocolOptions_msginit = {
   &envoy_api_v2_core_Http2ProtocolOptions_submsgs[0],
   &envoy_api_v2_core_Http2ProtocolOptions__fields[0],
-  UPB_SIZE(40, 80), 12, false,
+  UPB_SIZE(44, 88), 13, false,
+};
+
+static const upb_msglayout *const envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_submsgs[2] = {
+  &google_protobuf_UInt32Value_msginit,
+};
+
+static const upb_msglayout_field envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter__fields[2] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
+  {2, UPB_SIZE(4, 8), 0, 0, 11, 1},
+};
+
+const upb_msglayout envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_msginit = {
+  &envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_submsgs[0],
+  &envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter__fields[0],
+  UPB_SIZE(8, 16), 2, false,
 };
 
 static const upb_msglayout *const envoy_api_v2_core_GrpcProtocolOptions_submsgs[1] = {
index 0cdebc6..075adcb 100644 (file)
@@ -27,6 +27,7 @@ struct envoy_api_v2_core_Http1ProtocolOptions;
 struct envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat;
 struct envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords;
 struct envoy_api_v2_core_Http2ProtocolOptions;
+struct envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter;
 struct envoy_api_v2_core_GrpcProtocolOptions;
 typedef struct envoy_api_v2_core_TcpProtocolOptions envoy_api_v2_core_TcpProtocolOptions;
 typedef struct envoy_api_v2_core_UpstreamHttpProtocolOptions envoy_api_v2_core_UpstreamHttpProtocolOptions;
@@ -35,6 +36,7 @@ typedef struct envoy_api_v2_core_Http1ProtocolOptions envoy_api_v2_core_Http1Pro
 typedef struct envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat;
 typedef struct envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords;
 typedef struct envoy_api_v2_core_Http2ProtocolOptions envoy_api_v2_core_Http2ProtocolOptions;
+typedef struct envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter;
 typedef struct envoy_api_v2_core_GrpcProtocolOptions envoy_api_v2_core_GrpcProtocolOptions;
 extern const upb_msglayout envoy_api_v2_core_TcpProtocolOptions_msginit;
 extern const upb_msglayout envoy_api_v2_core_UpstreamHttpProtocolOptions_msginit;
@@ -43,6 +45,7 @@ extern const upb_msglayout envoy_api_v2_core_Http1ProtocolOptions_msginit;
 extern const upb_msglayout envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat_msginit;
 extern const upb_msglayout envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords_msginit;
 extern const upb_msglayout envoy_api_v2_core_Http2ProtocolOptions_msginit;
+extern const upb_msglayout envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_msginit;
 extern const upb_msglayout envoy_api_v2_core_GrpcProtocolOptions_msginit;
 struct google_protobuf_BoolValue;
 struct google_protobuf_Duration;
@@ -51,6 +54,12 @@ extern const upb_msglayout google_protobuf_BoolValue_msginit;
 extern const upb_msglayout google_protobuf_Duration_msginit;
 extern const upb_msglayout google_protobuf_UInt32Value_msginit;
 
+typedef enum {
+  envoy_api_v2_core_HttpProtocolOptions_ALLOW = 0,
+  envoy_api_v2_core_HttpProtocolOptions_REJECT_REQUEST = 1,
+  envoy_api_v2_core_HttpProtocolOptions_DROP_HEADER = 2
+} envoy_api_v2_core_HttpProtocolOptions_HeadersWithUnderscoresAction;
+
 
 /* envoy.api.v2.core.TcpProtocolOptions */
 
@@ -106,12 +115,14 @@ UPB_INLINE char *envoy_api_v2_core_HttpProtocolOptions_serialize(const envoy_api
   return upb_encode(msg, &envoy_api_v2_core_HttpProtocolOptions_msginit, arena, len);
 }
 
-UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HttpProtocolOptions_idle_timeout(const envoy_api_v2_core_HttpProtocolOptions *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(0, 0)); }
-UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_core_HttpProtocolOptions_max_headers_count(const envoy_api_v2_core_HttpProtocolOptions *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(4, 8)); }
-UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HttpProtocolOptions_max_connection_duration(const envoy_api_v2_core_HttpProtocolOptions *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(8, 16)); }
+UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HttpProtocolOptions_idle_timeout(const envoy_api_v2_core_HttpProtocolOptions *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(8, 8)); }
+UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_core_HttpProtocolOptions_max_headers_count(const envoy_api_v2_core_HttpProtocolOptions *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(12, 16)); }
+UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HttpProtocolOptions_max_connection_duration(const envoy_api_v2_core_HttpProtocolOptions *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(16, 24)); }
+UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_core_HttpProtocolOptions_max_stream_duration(const envoy_api_v2_core_HttpProtocolOptions *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(20, 32)); }
+UPB_INLINE int32_t envoy_api_v2_core_HttpProtocolOptions_headers_with_underscores_action(const envoy_api_v2_core_HttpProtocolOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)); }
 
 UPB_INLINE void envoy_api_v2_core_HttpProtocolOptions_set_idle_timeout(envoy_api_v2_core_HttpProtocolOptions *msg, struct google_protobuf_Duration* value) {
-  UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(0, 0)) = value;
+  UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(8, 8)) = value;
 }
 UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_core_HttpProtocolOptions_mutable_idle_timeout(envoy_api_v2_core_HttpProtocolOptions *msg, upb_arena *arena) {
   struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_api_v2_core_HttpProtocolOptions_idle_timeout(msg);
@@ -123,7 +134,7 @@ UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_core_HttpProtocolOption
   return sub;
 }
 UPB_INLINE void envoy_api_v2_core_HttpProtocolOptions_set_max_headers_count(envoy_api_v2_core_HttpProtocolOptions *msg, struct google_protobuf_UInt32Value* value) {
-  UPB_FIELD_AT(msg, struct google_protobuf_UInt32Value*, UPB_SIZE(4, 8)) = value;
+  UPB_FIELD_AT(msg, struct google_protobuf_UInt32Value*, UPB_SIZE(12, 16)) = value;
 }
 UPB_INLINE struct google_protobuf_UInt32Value* envoy_api_v2_core_HttpProtocolOptions_mutable_max_headers_count(envoy_api_v2_core_HttpProtocolOptions *msg, upb_arena *arena) {
   struct google_protobuf_UInt32Value* sub = (struct google_protobuf_UInt32Value*)envoy_api_v2_core_HttpProtocolOptions_max_headers_count(msg);
@@ -135,7 +146,7 @@ UPB_INLINE struct google_protobuf_UInt32Value* envoy_api_v2_core_HttpProtocolOpt
   return sub;
 }
 UPB_INLINE void envoy_api_v2_core_HttpProtocolOptions_set_max_connection_duration(envoy_api_v2_core_HttpProtocolOptions *msg, struct google_protobuf_Duration* value) {
-  UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(8, 16)) = value;
+  UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(16, 24)) = value;
 }
 UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_core_HttpProtocolOptions_mutable_max_connection_duration(envoy_api_v2_core_HttpProtocolOptions *msg, upb_arena *arena) {
   struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_api_v2_core_HttpProtocolOptions_max_connection_duration(msg);
@@ -146,6 +157,21 @@ UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_core_HttpProtocolOption
   }
   return sub;
 }
+UPB_INLINE void envoy_api_v2_core_HttpProtocolOptions_set_max_stream_duration(envoy_api_v2_core_HttpProtocolOptions *msg, struct google_protobuf_Duration* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(20, 32)) = value;
+}
+UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_core_HttpProtocolOptions_mutable_max_stream_duration(envoy_api_v2_core_HttpProtocolOptions *msg, upb_arena *arena) {
+  struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_api_v2_core_HttpProtocolOptions_max_stream_duration(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Duration*)upb_msg_new(&google_protobuf_Duration_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_core_HttpProtocolOptions_set_max_stream_duration(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_core_HttpProtocolOptions_set_headers_with_underscores_action(envoy_api_v2_core_HttpProtocolOptions *msg, int32_t value) {
+  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)) = value;
+}
 
 /* envoy.api.v2.core.Http1ProtocolOptions */
 
@@ -279,6 +305,7 @@ UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_core_Http2Prot
 UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_core_Http2ProtocolOptions_max_inbound_priority_frames_per_stream(const envoy_api_v2_core_Http2ProtocolOptions *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(32, 64)); }
 UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_core_Http2ProtocolOptions_max_inbound_window_update_frames_per_data_frame_sent(const envoy_api_v2_core_Http2ProtocolOptions *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(36, 72)); }
 UPB_INLINE bool envoy_api_v2_core_Http2ProtocolOptions_stream_error_on_invalid_http_messaging(const envoy_api_v2_core_Http2ProtocolOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)); }
+UPB_INLINE const envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter* const* envoy_api_v2_core_Http2ProtocolOptions_custom_settings_parameters(const envoy_api_v2_core_Http2ProtocolOptions *msg, size_t *len) { return (const envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
 
 UPB_INLINE void envoy_api_v2_core_Http2ProtocolOptions_set_hpack_table_size(envoy_api_v2_core_Http2ProtocolOptions *msg, struct google_protobuf_UInt32Value* value) {
   UPB_FIELD_AT(msg, struct google_protobuf_UInt32Value*, UPB_SIZE(4, 8)) = value;
@@ -397,6 +424,61 @@ UPB_INLINE struct google_protobuf_UInt32Value* envoy_api_v2_core_Http2ProtocolOp
 UPB_INLINE void envoy_api_v2_core_Http2ProtocolOptions_set_stream_error_on_invalid_http_messaging(envoy_api_v2_core_Http2ProtocolOptions *msg, bool value) {
   UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value;
 }
+UPB_INLINE envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter** envoy_api_v2_core_Http2ProtocolOptions_mutable_custom_settings_parameters(envoy_api_v2_core_Http2ProtocolOptions *msg, size_t *len) {
+  return (envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
+}
+UPB_INLINE envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter** envoy_api_v2_core_Http2ProtocolOptions_resize_custom_settings_parameters(envoy_api_v2_core_Http2ProtocolOptions *msg, size_t len, upb_arena *arena) {
+  return (envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+}
+UPB_INLINE struct envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter* envoy_api_v2_core_Http2ProtocolOptions_add_custom_settings_parameters(envoy_api_v2_core_Http2ProtocolOptions *msg, upb_arena *arena) {
+  struct envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter* sub = (struct envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter*)upb_msg_new(&envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_msginit, arena);
+  bool ok = _upb_array_append_accessor(
+      msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* envoy.api.v2.core.Http2ProtocolOptions.SettingsParameter */
+
+UPB_INLINE envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter *envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_new(upb_arena *arena) {
+  return (envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter *)upb_msg_new(&envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter *envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter *ret = envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_serialize(const envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_msginit, arena, len);
+}
+
+UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_identifier(const envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(0, 0)); }
+UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_value(const envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(4, 8)); }
+
+UPB_INLINE void envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_set_identifier(envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter *msg, struct google_protobuf_UInt32Value* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_UInt32Value*, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE struct google_protobuf_UInt32Value* envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_mutable_identifier(envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter *msg, upb_arena *arena) {
+  struct google_protobuf_UInt32Value* sub = (struct google_protobuf_UInt32Value*)envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_identifier(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_UInt32Value*)upb_msg_new(&google_protobuf_UInt32Value_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_set_identifier(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_set_value(envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter *msg, struct google_protobuf_UInt32Value* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_UInt32Value*, UPB_SIZE(4, 8)) = value;
+}
+UPB_INLINE struct google_protobuf_UInt32Value* envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_mutable_value(envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter *msg, upb_arena *arena) {
+  struct google_protobuf_UInt32Value* sub = (struct google_protobuf_UInt32Value*)envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_value(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_UInt32Value*)upb_msg_new(&google_protobuf_UInt32Value_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter_set_value(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.api.v2.core.GrpcProtocolOptions */
 
diff --git a/src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c b/src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c
new file mode 100644 (file)
index 0000000..85c7167
--- /dev/null
@@ -0,0 +1,34 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/core/socket_option.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg.h"
+#include "envoy/api/v2/core/socket_option.upb.h"
+#include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
+#include "validate/validate.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout_field envoy_api_v2_core_SocketOption__fields[6] = {
+  {1, UPB_SIZE(24, 24), 0, 0, 9, 1},
+  {2, UPB_SIZE(0, 0), 0, 0, 3, 1},
+  {3, UPB_SIZE(8, 8), 0, 0, 3, 1},
+  {4, UPB_SIZE(32, 40), UPB_SIZE(-41, -57), 0, 3, 1},
+  {5, UPB_SIZE(32, 40), UPB_SIZE(-41, -57), 0, 12, 1},
+  {6, UPB_SIZE(16, 16), 0, 0, 14, 1},
+};
+
+const upb_msglayout envoy_api_v2_core_SocketOption_msginit = {
+  NULL,
+  &envoy_api_v2_core_SocketOption__fields[0],
+  UPB_SIZE(48, 64), 6, false,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h b/src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h
new file mode 100644 (file)
index 0000000..6c4ee2e
--- /dev/null
@@ -0,0 +1,89 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/api/v2/core/socket_option.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef ENVOY_API_V2_CORE_SOCKET_OPTION_PROTO_UPB_H_
+#define ENVOY_API_V2_CORE_SOCKET_OPTION_PROTO_UPB_H_
+
+#include "upb/generated_util.h"
+#include "upb/msg.h"
+#include "upb/decode.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct envoy_api_v2_core_SocketOption;
+typedef struct envoy_api_v2_core_SocketOption envoy_api_v2_core_SocketOption;
+extern const upb_msglayout envoy_api_v2_core_SocketOption_msginit;
+
+typedef enum {
+  envoy_api_v2_core_SocketOption_STATE_PREBIND = 0,
+  envoy_api_v2_core_SocketOption_STATE_BOUND = 1,
+  envoy_api_v2_core_SocketOption_STATE_LISTENING = 2
+} envoy_api_v2_core_SocketOption_SocketState;
+
+
+/* envoy.api.v2.core.SocketOption */
+
+UPB_INLINE envoy_api_v2_core_SocketOption *envoy_api_v2_core_SocketOption_new(upb_arena *arena) {
+  return (envoy_api_v2_core_SocketOption *)upb_msg_new(&envoy_api_v2_core_SocketOption_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_core_SocketOption *envoy_api_v2_core_SocketOption_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_core_SocketOption *ret = envoy_api_v2_core_SocketOption_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_core_SocketOption_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_core_SocketOption_serialize(const envoy_api_v2_core_SocketOption *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_core_SocketOption_msginit, arena, len);
+}
+
+typedef enum {
+  envoy_api_v2_core_SocketOption_value_int_value = 4,
+  envoy_api_v2_core_SocketOption_value_buf_value = 5,
+  envoy_api_v2_core_SocketOption_value_NOT_SET = 0
+} envoy_api_v2_core_SocketOption_value_oneofcases;
+UPB_INLINE envoy_api_v2_core_SocketOption_value_oneofcases envoy_api_v2_core_SocketOption_value_case(const envoy_api_v2_core_SocketOption* msg) { return (envoy_api_v2_core_SocketOption_value_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(40, 56)); }
+
+UPB_INLINE upb_strview envoy_api_v2_core_SocketOption_description(const envoy_api_v2_core_SocketOption *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(24, 24)); }
+UPB_INLINE int64_t envoy_api_v2_core_SocketOption_level(const envoy_api_v2_core_SocketOption *msg) { return UPB_FIELD_AT(msg, int64_t, UPB_SIZE(0, 0)); }
+UPB_INLINE int64_t envoy_api_v2_core_SocketOption_name(const envoy_api_v2_core_SocketOption *msg) { return UPB_FIELD_AT(msg, int64_t, UPB_SIZE(8, 8)); }
+UPB_INLINE bool envoy_api_v2_core_SocketOption_has_int_value(const envoy_api_v2_core_SocketOption *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(40, 56), 4); }
+UPB_INLINE int64_t envoy_api_v2_core_SocketOption_int_value(const envoy_api_v2_core_SocketOption *msg) { return UPB_READ_ONEOF(msg, int64_t, UPB_SIZE(32, 40), UPB_SIZE(40, 56), 4, 0); }
+UPB_INLINE bool envoy_api_v2_core_SocketOption_has_buf_value(const envoy_api_v2_core_SocketOption *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(40, 56), 5); }
+UPB_INLINE upb_strview envoy_api_v2_core_SocketOption_buf_value(const envoy_api_v2_core_SocketOption *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(32, 40), UPB_SIZE(40, 56), 5, upb_strview_make("", strlen(""))); }
+UPB_INLINE int32_t envoy_api_v2_core_SocketOption_state(const envoy_api_v2_core_SocketOption *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); }
+
+UPB_INLINE void envoy_api_v2_core_SocketOption_set_description(envoy_api_v2_core_SocketOption *msg, upb_strview value) {
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(24, 24)) = value;
+}
+UPB_INLINE void envoy_api_v2_core_SocketOption_set_level(envoy_api_v2_core_SocketOption *msg, int64_t value) {
+  UPB_FIELD_AT(msg, int64_t, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE void envoy_api_v2_core_SocketOption_set_name(envoy_api_v2_core_SocketOption *msg, int64_t value) {
+  UPB_FIELD_AT(msg, int64_t, UPB_SIZE(8, 8)) = value;
+}
+UPB_INLINE void envoy_api_v2_core_SocketOption_set_int_value(envoy_api_v2_core_SocketOption *msg, int64_t value) {
+  UPB_WRITE_ONEOF(msg, int64_t, UPB_SIZE(32, 40), value, UPB_SIZE(40, 56), 4);
+}
+UPB_INLINE void envoy_api_v2_core_SocketOption_set_buf_value(envoy_api_v2_core_SocketOption *msg, upb_strview value) {
+  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(32, 40), value, UPB_SIZE(40, 56), 5);
+}
+UPB_INLINE void envoy_api_v2_core_SocketOption_set_state(envoy_api_v2_core_SocketOption *msg, int32_t value) {
+  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)) = value;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* ENVOY_API_V2_CORE_SOCKET_OPTION_PROTO_UPB_H_ */
index eaf14b3..0f80f72 100644 (file)
@@ -13,6 +13,7 @@
 #include "google/protobuf/any.upb.h"
 #include "google/rpc/status.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 
 #include "upb/port_def.inc"
 
index f68881a..74de7ab 100644 (file)
@@ -15,6 +15,7 @@
 #include "google/protobuf/wrappers.upb.h"
 #include "envoy/annotations/resource.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 #include "envoy/api/v2/endpoint.upb.h"
 
index 64a00d1..2481b6c 100644 (file)
@@ -15,6 +15,7 @@
 #include "google/protobuf/duration.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index d071a4f..b291ee9 100644 (file)
@@ -9,6 +9,7 @@
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/api/v2/endpoint/endpoint.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "envoy/api/v2/endpoint/endpoint_components.upb.h"
 
 #include "upb/port_def.inc"
index fc13392..ecdf2c2 100644 (file)
@@ -14,6 +14,7 @@
 #include "envoy/api/v2/core/health_check.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
@@ -23,25 +24,27 @@ static const upb_msglayout *const envoy_api_v2_endpoint_Endpoint_submsgs[2] = {
   &envoy_api_v2_endpoint_Endpoint_HealthCheckConfig_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_endpoint_Endpoint__fields[2] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
-  {2, UPB_SIZE(4, 8), 0, 1, 11, 1},
+static const upb_msglayout_field envoy_api_v2_endpoint_Endpoint__fields[3] = {
+  {1, UPB_SIZE(8, 16), 0, 0, 11, 1},
+  {2, UPB_SIZE(12, 24), 0, 1, 11, 1},
+  {3, UPB_SIZE(0, 0), 0, 0, 9, 1},
 };
 
 const upb_msglayout envoy_api_v2_endpoint_Endpoint_msginit = {
   &envoy_api_v2_endpoint_Endpoint_submsgs[0],
   &envoy_api_v2_endpoint_Endpoint__fields[0],
-  UPB_SIZE(8, 16), 2, false,
+  UPB_SIZE(16, 32), 3, false,
 };
 
-static const upb_msglayout_field envoy_api_v2_endpoint_Endpoint_HealthCheckConfig__fields[1] = {
+static const upb_msglayout_field envoy_api_v2_endpoint_Endpoint_HealthCheckConfig__fields[2] = {
   {1, UPB_SIZE(0, 0), 0, 0, 13, 1},
+  {2, UPB_SIZE(4, 8), 0, 0, 9, 1},
 };
 
 const upb_msglayout envoy_api_v2_endpoint_Endpoint_HealthCheckConfig_msginit = {
   NULL,
   &envoy_api_v2_endpoint_Endpoint_HealthCheckConfig__fields[0],
-  UPB_SIZE(4, 4), 1, false,
+  UPB_SIZE(16, 32), 2, false,
 };
 
 static const upb_msglayout *const envoy_api_v2_endpoint_LbEndpoint_submsgs[3] = {
index da973c9..22e6502 100644 (file)
@@ -56,11 +56,12 @@ UPB_INLINE char *envoy_api_v2_endpoint_Endpoint_serialize(const envoy_api_v2_end
   return upb_encode(msg, &envoy_api_v2_endpoint_Endpoint_msginit, arena, len);
 }
 
-UPB_INLINE const struct envoy_api_v2_core_Address* envoy_api_v2_endpoint_Endpoint_address(const envoy_api_v2_endpoint_Endpoint *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_Address*, UPB_SIZE(0, 0)); }
-UPB_INLINE const envoy_api_v2_endpoint_Endpoint_HealthCheckConfig* envoy_api_v2_endpoint_Endpoint_health_check_config(const envoy_api_v2_endpoint_Endpoint *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_endpoint_Endpoint_HealthCheckConfig*, UPB_SIZE(4, 8)); }
+UPB_INLINE const struct envoy_api_v2_core_Address* envoy_api_v2_endpoint_Endpoint_address(const envoy_api_v2_endpoint_Endpoint *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_Address*, UPB_SIZE(8, 16)); }
+UPB_INLINE const envoy_api_v2_endpoint_Endpoint_HealthCheckConfig* envoy_api_v2_endpoint_Endpoint_health_check_config(const envoy_api_v2_endpoint_Endpoint *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_endpoint_Endpoint_HealthCheckConfig*, UPB_SIZE(12, 24)); }
+UPB_INLINE upb_strview envoy_api_v2_endpoint_Endpoint_hostname(const envoy_api_v2_endpoint_Endpoint *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
 
 UPB_INLINE void envoy_api_v2_endpoint_Endpoint_set_address(envoy_api_v2_endpoint_Endpoint *msg, struct envoy_api_v2_core_Address* value) {
-  UPB_FIELD_AT(msg, struct envoy_api_v2_core_Address*, UPB_SIZE(0, 0)) = value;
+  UPB_FIELD_AT(msg, struct envoy_api_v2_core_Address*, UPB_SIZE(8, 16)) = value;
 }
 UPB_INLINE struct envoy_api_v2_core_Address* envoy_api_v2_endpoint_Endpoint_mutable_address(envoy_api_v2_endpoint_Endpoint *msg, upb_arena *arena) {
   struct envoy_api_v2_core_Address* sub = (struct envoy_api_v2_core_Address*)envoy_api_v2_endpoint_Endpoint_address(msg);
@@ -72,7 +73,7 @@ UPB_INLINE struct envoy_api_v2_core_Address* envoy_api_v2_endpoint_Endpoint_muta
   return sub;
 }
 UPB_INLINE void envoy_api_v2_endpoint_Endpoint_set_health_check_config(envoy_api_v2_endpoint_Endpoint *msg, envoy_api_v2_endpoint_Endpoint_HealthCheckConfig* value) {
-  UPB_FIELD_AT(msg, envoy_api_v2_endpoint_Endpoint_HealthCheckConfig*, UPB_SIZE(4, 8)) = value;
+  UPB_FIELD_AT(msg, envoy_api_v2_endpoint_Endpoint_HealthCheckConfig*, UPB_SIZE(12, 24)) = value;
 }
 UPB_INLINE struct envoy_api_v2_endpoint_Endpoint_HealthCheckConfig* envoy_api_v2_endpoint_Endpoint_mutable_health_check_config(envoy_api_v2_endpoint_Endpoint *msg, upb_arena *arena) {
   struct envoy_api_v2_endpoint_Endpoint_HealthCheckConfig* sub = (struct envoy_api_v2_endpoint_Endpoint_HealthCheckConfig*)envoy_api_v2_endpoint_Endpoint_health_check_config(msg);
@@ -83,6 +84,9 @@ UPB_INLINE struct envoy_api_v2_endpoint_Endpoint_HealthCheckConfig* envoy_api_v2
   }
   return sub;
 }
+UPB_INLINE void envoy_api_v2_endpoint_Endpoint_set_hostname(envoy_api_v2_endpoint_Endpoint *msg, upb_strview value) {
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
+}
 
 /* envoy.api.v2.endpoint.Endpoint.HealthCheckConfig */
 
@@ -99,10 +103,14 @@ UPB_INLINE char *envoy_api_v2_endpoint_Endpoint_HealthCheckConfig_serialize(cons
 }
 
 UPB_INLINE uint32_t envoy_api_v2_endpoint_Endpoint_HealthCheckConfig_port_value(const envoy_api_v2_endpoint_Endpoint_HealthCheckConfig *msg) { return UPB_FIELD_AT(msg, uint32_t, UPB_SIZE(0, 0)); }
+UPB_INLINE upb_strview envoy_api_v2_endpoint_Endpoint_HealthCheckConfig_hostname(const envoy_api_v2_endpoint_Endpoint_HealthCheckConfig *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); }
 
 UPB_INLINE void envoy_api_v2_endpoint_Endpoint_HealthCheckConfig_set_port_value(envoy_api_v2_endpoint_Endpoint_HealthCheckConfig *msg, uint32_t value) {
   UPB_FIELD_AT(msg, uint32_t, UPB_SIZE(0, 0)) = value;
 }
+UPB_INLINE void envoy_api_v2_endpoint_Endpoint_HealthCheckConfig_set_hostname(envoy_api_v2_endpoint_Endpoint_HealthCheckConfig *msg, upb_strview value) {
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
+}
 
 /* envoy.api.v2.endpoint.LbEndpoint */
 
index 7cc6819..be3c982 100644 (file)
@@ -14,6 +14,7 @@
 #include "google/protobuf/duration.upb.h"
 #include "google/protobuf/struct.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index 5b37278..5fe96bb 100644 (file)
@@ -15,6 +15,7 @@
 #include "google/protobuf/wrappers.upb.h"
 #include "envoy/annotations/resource.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 #include "envoy/api/v2/listener.upb.h"
 
index 161c04d..455b3c2 100644 (file)
 #include "envoy/api/v2/listener.upb.h"
 #include "envoy/api/v2/core/address.upb.h"
 #include "envoy/api/v2/core/base.upb.h"
+#include "envoy/api/v2/core/socket_option.upb.h"
 #include "envoy/api/v2/listener/listener_components.upb.h"
 #include "envoy/api/v2/listener/udp_listener_config.upb.h"
+#include "envoy/config/filter/accesslog/v2/accesslog.upb.h"
 #include "envoy/config/listener/v2/api_listener.upb.h"
 #include "google/api/annotations.upb.h"
 #include "google/protobuf/duration.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
 
-static const upb_msglayout *const envoy_api_v2_Listener_submsgs[15] = {
+static const upb_msglayout *const envoy_api_v2_Listener_submsgs[16] = {
   &envoy_api_v2_Listener_ConnectionBalanceConfig_msginit,
   &envoy_api_v2_Listener_DeprecatedV1_msginit,
   &envoy_api_v2_core_Address_msginit,
@@ -31,39 +34,41 @@ static const upb_msglayout *const envoy_api_v2_Listener_submsgs[15] = {
   &envoy_api_v2_listener_FilterChain_msginit,
   &envoy_api_v2_listener_ListenerFilter_msginit,
   &envoy_api_v2_listener_UdpListenerConfig_msginit,
+  &envoy_config_filter_accesslog_v2_AccessLog_msginit,
   &envoy_config_listener_v2_ApiListener_msginit,
   &google_protobuf_BoolValue_msginit,
   &google_protobuf_Duration_msginit,
   &google_protobuf_UInt32Value_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_Listener__fields[20] = {
+static const upb_msglayout_field envoy_api_v2_Listener__fields[21] = {
   {1, UPB_SIZE(20, 24), 0, 0, 9, 1},
   {2, UPB_SIZE(28, 40), 0, 2, 11, 1},
   {3, UPB_SIZE(76, 136), 0, 5, 11, 3},
-  {4, UPB_SIZE(32, 48), 0, 9, 11, 1},
-  {5, UPB_SIZE(36, 56), 0, 11, 11, 1},
+  {4, UPB_SIZE(32, 48), 0, 10, 11, 1},
+  {5, UPB_SIZE(36, 56), 0, 12, 11, 1},
   {6, UPB_SIZE(40, 64), 0, 3, 11, 1},
   {7, UPB_SIZE(44, 72), 0, 1, 11, 1},
   {8, UPB_SIZE(0, 0), 0, 0, 14, 1},
   {9, UPB_SIZE(80, 144), 0, 6, 11, 3},
-  {10, UPB_SIZE(48, 80), 0, 9, 11, 1},
-  {11, UPB_SIZE(52, 88), 0, 9, 11, 1},
-  {12, UPB_SIZE(56, 96), 0, 11, 11, 1},
+  {10, UPB_SIZE(48, 80), 0, 10, 11, 1},
+  {11, UPB_SIZE(52, 88), 0, 10, 11, 1},
+  {12, UPB_SIZE(56, 96), 0, 12, 11, 1},
   {13, UPB_SIZE(84, 152), 0, 4, 11, 3},
-  {15, UPB_SIZE(60, 104), 0, 10, 11, 1},
+  {15, UPB_SIZE(60, 104), 0, 11, 11, 1},
   {16, UPB_SIZE(8, 8), 0, 0, 14, 1},
   {17, UPB_SIZE(16, 16), 0, 0, 8, 1},
   {18, UPB_SIZE(64, 112), 0, 7, 11, 1},
-  {19, UPB_SIZE(68, 120), 0, 8, 11, 1},
+  {19, UPB_SIZE(68, 120), 0, 9, 11, 1},
   {20, UPB_SIZE(72, 128), 0, 0, 11, 1},
   {21, UPB_SIZE(17, 17), 0, 0, 8, 1},
+  {22, UPB_SIZE(88, 160), 0, 8, 11, 3},
 };
 
 const upb_msglayout envoy_api_v2_Listener_msginit = {
   &envoy_api_v2_Listener_submsgs[0],
   &envoy_api_v2_Listener__fields[0],
-  UPB_SIZE(88, 160), 20, false,
+  UPB_SIZE(96, 176), 21, false,
 };
 
 static const upb_msglayout *const envoy_api_v2_Listener_DeprecatedV1_submsgs[1] = {
index 9689def..0d509e2 100644 (file)
@@ -38,6 +38,7 @@ struct envoy_api_v2_core_SocketOption;
 struct envoy_api_v2_listener_FilterChain;
 struct envoy_api_v2_listener_ListenerFilter;
 struct envoy_api_v2_listener_UdpListenerConfig;
+struct envoy_config_filter_accesslog_v2_AccessLog;
 struct envoy_config_listener_v2_ApiListener;
 struct google_protobuf_BoolValue;
 struct google_protobuf_Duration;
@@ -48,6 +49,7 @@ extern const upb_msglayout envoy_api_v2_core_SocketOption_msginit;
 extern const upb_msglayout envoy_api_v2_listener_FilterChain_msginit;
 extern const upb_msglayout envoy_api_v2_listener_ListenerFilter_msginit;
 extern const upb_msglayout envoy_api_v2_listener_UdpListenerConfig_msginit;
+extern const upb_msglayout envoy_config_filter_accesslog_v2_AccessLog_msginit;
 extern const upb_msglayout envoy_config_listener_v2_ApiListener_msginit;
 extern const upb_msglayout google_protobuf_BoolValue_msginit;
 extern const upb_msglayout google_protobuf_Duration_msginit;
@@ -93,6 +95,7 @@ UPB_INLINE const struct envoy_api_v2_listener_UdpListenerConfig* envoy_api_v2_Li
 UPB_INLINE const struct envoy_config_listener_v2_ApiListener* envoy_api_v2_Listener_api_listener(const envoy_api_v2_Listener *msg) { return UPB_FIELD_AT(msg, const struct envoy_config_listener_v2_ApiListener*, UPB_SIZE(68, 120)); }
 UPB_INLINE const envoy_api_v2_Listener_ConnectionBalanceConfig* envoy_api_v2_Listener_connection_balance_config(const envoy_api_v2_Listener *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_Listener_ConnectionBalanceConfig*, UPB_SIZE(72, 128)); }
 UPB_INLINE bool envoy_api_v2_Listener_reuse_port(const envoy_api_v2_Listener *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(17, 17)); }
+UPB_INLINE const struct envoy_config_filter_accesslog_v2_AccessLog* const* envoy_api_v2_Listener_access_log(const envoy_api_v2_Listener *msg, size_t *len) { return (const struct envoy_config_filter_accesslog_v2_AccessLog* const*)_upb_array_accessor(msg, UPB_SIZE(88, 160), len); }
 
 UPB_INLINE void envoy_api_v2_Listener_set_name(envoy_api_v2_Listener *msg, upb_strview value) {
   UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 24)) = value;
@@ -292,6 +295,19 @@ UPB_INLINE struct envoy_api_v2_Listener_ConnectionBalanceConfig* envoy_api_v2_Li
 UPB_INLINE void envoy_api_v2_Listener_set_reuse_port(envoy_api_v2_Listener *msg, bool value) {
   UPB_FIELD_AT(msg, bool, UPB_SIZE(17, 17)) = value;
 }
+UPB_INLINE struct envoy_config_filter_accesslog_v2_AccessLog** envoy_api_v2_Listener_mutable_access_log(envoy_api_v2_Listener *msg, size_t *len) {
+  return (struct envoy_config_filter_accesslog_v2_AccessLog**)_upb_array_mutable_accessor(msg, UPB_SIZE(88, 160), len);
+}
+UPB_INLINE struct envoy_config_filter_accesslog_v2_AccessLog** envoy_api_v2_Listener_resize_access_log(envoy_api_v2_Listener *msg, size_t len, upb_arena *arena) {
+  return (struct envoy_config_filter_accesslog_v2_AccessLog**)_upb_array_resize_accessor(msg, UPB_SIZE(88, 160), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+}
+UPB_INLINE struct envoy_config_filter_accesslog_v2_AccessLog* envoy_api_v2_Listener_add_access_log(envoy_api_v2_Listener *msg, upb_arena *arena) {
+  struct envoy_config_filter_accesslog_v2_AccessLog* sub = (struct envoy_config_filter_accesslog_v2_AccessLog*)upb_msg_new(&envoy_config_filter_accesslog_v2_AccessLog_msginit, arena);
+  bool ok = _upb_array_append_accessor(
+      msg, UPB_SIZE(88, 160), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
 
 /* envoy.api.v2.Listener.DeprecatedV1 */
 
index ef74720..d9b3dc2 100644 (file)
@@ -9,6 +9,7 @@
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/api/v2/listener/listener.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "envoy/api/v2/listener/listener_components.upb.h"
 
 #include "upb/port_def.inc"
index cbce3e1..a014cd1 100644 (file)
@@ -9,7 +9,7 @@
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/api/v2/listener/listener_components.upb.h"
-#include "envoy/api/v2/auth/cert.upb.h"
+#include "envoy/api/v2/auth/tls.upb.h"
 #include "envoy/api/v2/core/address.upb.h"
 #include "envoy/api/v2/core/base.upb.h"
 #include "envoy/type/range.upb.h"
@@ -17,6 +17,7 @@
 #include "google/protobuf/struct.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index f32ff0b..7c9df77 100644 (file)
@@ -12,6 +12,7 @@
 #include "google/protobuf/any.upb.h"
 #include "google/protobuf/struct.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 
 #include "upb/port_def.inc"
 
index c17b868..e360b58 100644 (file)
@@ -14,6 +14,7 @@
 #include "google/protobuf/wrappers.upb.h"
 #include "envoy/annotations/resource.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 #include "envoy/api/v2/route.upb.h"
 
index 7486cb4..85ab57c 100644 (file)
@@ -14,6 +14,7 @@
 #include "envoy/api/v2/route/route_components.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index d8e9ffd..ba31395 100644 (file)
@@ -9,6 +9,7 @@
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/api/v2/route/route.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "envoy/api/v2/route/route_components.upb.h"
 
 #include "upb/port_def.inc"
index 7c56852..fdf7c4b 100644 (file)
 #include "google/protobuf/wrappers.upb.h"
 #include "envoy/annotations/deprecation.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
 
-static const upb_msglayout *const envoy_api_v2_route_VirtualHost_submsgs[11] = {
+static const upb_msglayout *const envoy_api_v2_route_VirtualHost_submsgs[12] = {
   &envoy_api_v2_core_HeaderValueOption_msginit,
   &envoy_api_v2_route_CorsPolicy_msginit,
   &envoy_api_v2_route_HedgePolicy_msginit,
@@ -35,33 +36,36 @@ static const upb_msglayout *const envoy_api_v2_route_VirtualHost_submsgs[11] = {
   &envoy_api_v2_route_VirtualCluster_msginit,
   &envoy_api_v2_route_VirtualHost_PerFilterConfigEntry_msginit,
   &envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry_msginit,
+  &google_protobuf_Any_msginit,
   &google_protobuf_UInt32Value_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_route_VirtualHost__fields[17] = {
+static const upb_msglayout_field envoy_api_v2_route_VirtualHost__fields[19] = {
   {1, UPB_SIZE(12, 16), 0, 0, 9, 1},
-  {2, UPB_SIZE(36, 64), 0, 0, 9, 3},
-  {3, UPB_SIZE(40, 72), 0, 5, 11, 3},
+  {2, UPB_SIZE(40, 72), 0, 0, 9, 3},
+  {3, UPB_SIZE(44, 80), 0, 5, 11, 3},
   {4, UPB_SIZE(0, 0), 0, 0, 14, 1},
-  {5, UPB_SIZE(44, 80), 0, 6, 11, 3},
-  {6, UPB_SIZE(48, 88), 0, 3, 11, 3},
-  {7, UPB_SIZE(52, 96), 0, 0, 11, 3},
+  {5, UPB_SIZE(48, 88), 0, 6, 11, 3},
+  {6, UPB_SIZE(52, 96), 0, 3, 11, 3},
+  {7, UPB_SIZE(56, 104), 0, 0, 11, 3},
   {8, UPB_SIZE(20, 32), 0, 1, 11, 1},
-  {10, UPB_SIZE(56, 104), 0, 0, 11, 3},
-  {11, UPB_SIZE(60, 112), 0, 0, 9, 3},
-  {12, UPB_SIZE(64, 120), 0, 7, 11, 3},
-  {13, UPB_SIZE(68, 128), 0, 0, 9, 3},
+  {10, UPB_SIZE(60, 112), 0, 0, 11, 3},
+  {11, UPB_SIZE(64, 120), 0, 0, 9, 3},
+  {12, UPB_SIZE(68, 128), 0, 7, 11, 3},
+  {13, UPB_SIZE(72, 136), 0, 0, 9, 3},
   {14, UPB_SIZE(8, 8), 0, 0, 8, 1},
-  {15, UPB_SIZE(72, 136), 0, 8, 11, 3},
+  {15, UPB_SIZE(76, 144), 0, 8, 11, 3},
   {16, UPB_SIZE(24, 40), 0, 4, 11, 1},
   {17, UPB_SIZE(28, 48), 0, 2, 11, 1},
-  {18, UPB_SIZE(32, 56), 0, 9, 11, 1},
+  {18, UPB_SIZE(32, 56), 0, 10, 11, 1},
+  {19, UPB_SIZE(9, 9), 0, 0, 8, 1},
+  {20, UPB_SIZE(36, 64), 0, 9, 11, 1},
 };
 
 const upb_msglayout envoy_api_v2_route_VirtualHost_msginit = {
   &envoy_api_v2_route_VirtualHost_submsgs[0],
   &envoy_api_v2_route_VirtualHost__fields[0],
-  UPB_SIZE(80, 144), 17, false,
+  UPB_SIZE(80, 160), 19, false,
 };
 
 static const upb_msglayout *const envoy_api_v2_route_VirtualHost_PerFilterConfigEntry_submsgs[1] = {
@@ -327,7 +331,7 @@ const upb_msglayout envoy_api_v2_route_CorsPolicy_msginit = {
   UPB_SIZE(64, 128), 11, false,
 };
 
-static const upb_msglayout *const envoy_api_v2_route_RouteAction_submsgs[17] = {
+static const upb_msglayout *const envoy_api_v2_route_RouteAction_submsgs[19] = {
   &envoy_api_v2_core_Metadata_msginit,
   &envoy_api_v2_route_CorsPolicy_msginit,
   &envoy_api_v2_route_HedgePolicy_msginit,
@@ -337,80 +341,88 @@ static const upb_msglayout *const envoy_api_v2_route_RouteAction_submsgs[17] = {
   &envoy_api_v2_route_RouteAction_RequestMirrorPolicy_msginit,
   &envoy_api_v2_route_RouteAction_UpgradeConfig_msginit,
   &envoy_api_v2_route_WeightedCluster_msginit,
+  &envoy_type_matcher_RegexMatchAndSubstitute_msginit,
+  &google_protobuf_Any_msginit,
   &google_protobuf_BoolValue_msginit,
   &google_protobuf_Duration_msginit,
   &google_protobuf_UInt32Value_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_route_RouteAction__fields[25] = {
-  {1, UPB_SIZE(92, 160), UPB_SIZE(-101, -177), 0, 9, 1},
-  {2, UPB_SIZE(92, 160), UPB_SIZE(-101, -177), 0, 9, 1},
-  {3, UPB_SIZE(92, 160), UPB_SIZE(-101, -177), 8, 11, 1},
+static const upb_msglayout_field envoy_api_v2_route_RouteAction__fields[27] = {
+  {1, UPB_SIZE(100, 176), UPB_SIZE(-109, -193), 0, 9, 1},
+  {2, UPB_SIZE(100, 176), UPB_SIZE(-109, -193), 0, 9, 1},
+  {3, UPB_SIZE(100, 176), UPB_SIZE(-109, -193), 8, 11, 1},
   {4, UPB_SIZE(32, 40), 0, 0, 11, 1},
   {5, UPB_SIZE(24, 24), 0, 0, 9, 1},
-  {6, UPB_SIZE(104, 184), UPB_SIZE(-113, -201), 0, 9, 1},
-  {7, UPB_SIZE(104, 184), UPB_SIZE(-113, -201), 9, 11, 1},
-  {8, UPB_SIZE(36, 48), 0, 10, 11, 1},
+  {6, UPB_SIZE(112, 200), UPB_SIZE(-121, -217), 0, 9, 1},
+  {7, UPB_SIZE(112, 200), UPB_SIZE(-121, -217), 11, 11, 1},
+  {8, UPB_SIZE(36, 48), 0, 12, 11, 1},
   {9, UPB_SIZE(40, 56), 0, 4, 11, 1},
   {10, UPB_SIZE(44, 64), 0, 6, 11, 1},
   {11, UPB_SIZE(0, 0), 0, 0, 14, 1},
-  {13, UPB_SIZE(76, 128), 0, 3, 11, 3},
-  {14, UPB_SIZE(48, 72), 0, 9, 11, 1},
-  {15, UPB_SIZE(80, 136), 0, 5, 11, 3},
+  {13, UPB_SIZE(84, 144), 0, 3, 11, 3},
+  {14, UPB_SIZE(48, 72), 0, 11, 11, 1},
+  {15, UPB_SIZE(88, 152), 0, 5, 11, 3},
   {17, UPB_SIZE(52, 80), 0, 1, 11, 1},
   {20, UPB_SIZE(8, 8), 0, 0, 14, 1},
-  {23, UPB_SIZE(56, 88), 0, 10, 11, 1},
-  {24, UPB_SIZE(60, 96), 0, 10, 11, 1},
-  {25, UPB_SIZE(84, 144), 0, 7, 11, 3},
+  {23, UPB_SIZE(56, 88), 0, 12, 11, 1},
+  {24, UPB_SIZE(60, 96), 0, 12, 11, 1},
+  {25, UPB_SIZE(92, 160), 0, 7, 11, 3},
   {26, UPB_SIZE(16, 16), 0, 0, 14, 1},
   {27, UPB_SIZE(64, 104), 0, 2, 11, 1},
-  {28, UPB_SIZE(68, 112), 0, 10, 11, 1},
-  {29, UPB_SIZE(104, 184), UPB_SIZE(-113, -201), 0, 9, 1},
-  {30, UPB_SIZE(88, 152), 0, 6, 11, 3},
-  {31, UPB_SIZE(72, 120), 0, 11, 11, 1},
+  {28, UPB_SIZE(68, 112), 0, 12, 11, 1},
+  {29, UPB_SIZE(112, 200), UPB_SIZE(-121, -217), 0, 9, 1},
+  {30, UPB_SIZE(96, 168), 0, 6, 11, 3},
+  {31, UPB_SIZE(72, 120), 0, 13, 11, 1},
+  {32, UPB_SIZE(76, 128), 0, 9, 11, 1},
+  {33, UPB_SIZE(80, 136), 0, 10, 11, 1},
 };
 
 const upb_msglayout envoy_api_v2_route_RouteAction_msginit = {
   &envoy_api_v2_route_RouteAction_submsgs[0],
   &envoy_api_v2_route_RouteAction__fields[0],
-  UPB_SIZE(120, 208), 25, false,
+  UPB_SIZE(128, 224), 27, false,
 };
 
-static const upb_msglayout *const envoy_api_v2_route_RouteAction_RequestMirrorPolicy_submsgs[1] = {
+static const upb_msglayout *const envoy_api_v2_route_RouteAction_RequestMirrorPolicy_submsgs[2] = {
   &envoy_api_v2_core_RuntimeFractionalPercent_msginit,
+  &google_protobuf_BoolValue_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_route_RouteAction_RequestMirrorPolicy__fields[3] = {
+static const upb_msglayout_field envoy_api_v2_route_RouteAction_RequestMirrorPolicy__fields[4] = {
   {1, UPB_SIZE(0, 0), 0, 0, 9, 1},
   {2, UPB_SIZE(8, 16), 0, 0, 9, 1},
   {3, UPB_SIZE(16, 32), 0, 0, 11, 1},
+  {4, UPB_SIZE(20, 40), 0, 1, 11, 1},
 };
 
 const upb_msglayout envoy_api_v2_route_RouteAction_RequestMirrorPolicy_msginit = {
   &envoy_api_v2_route_RouteAction_RequestMirrorPolicy_submsgs[0],
   &envoy_api_v2_route_RouteAction_RequestMirrorPolicy__fields[0],
-  UPB_SIZE(24, 48), 3, false,
+  UPB_SIZE(24, 48), 4, false,
 };
 
-static const upb_msglayout *const envoy_api_v2_route_RouteAction_HashPolicy_submsgs[4] = {
+static const upb_msglayout *const envoy_api_v2_route_RouteAction_HashPolicy_submsgs[5] = {
   &envoy_api_v2_route_RouteAction_HashPolicy_ConnectionProperties_msginit,
   &envoy_api_v2_route_RouteAction_HashPolicy_Cookie_msginit,
+  &envoy_api_v2_route_RouteAction_HashPolicy_FilterState_msginit,
   &envoy_api_v2_route_RouteAction_HashPolicy_Header_msginit,
   &envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter_msginit,
 };
 
-static const upb_msglayout_field envoy_api_v2_route_RouteAction_HashPolicy__fields[5] = {
-  {1, UPB_SIZE(4, 8), UPB_SIZE(-9, -17), 2, 11, 1},
+static const upb_msglayout_field envoy_api_v2_route_RouteAction_HashPolicy__fields[6] = {
+  {1, UPB_SIZE(4, 8), UPB_SIZE(-9, -17), 3, 11, 1},
   {2, UPB_SIZE(4, 8), UPB_SIZE(-9, -17), 1, 11, 1},
   {3, UPB_SIZE(4, 8), UPB_SIZE(-9, -17), 0, 11, 1},
   {4, UPB_SIZE(0, 0), 0, 0, 8, 1},
-  {5, UPB_SIZE(4, 8), UPB_SIZE(-9, -17), 3, 11, 1},
+  {5, UPB_SIZE(4, 8), UPB_SIZE(-9, -17), 4, 11, 1},
+  {6, UPB_SIZE(4, 8), UPB_SIZE(-9, -17), 2, 11, 1},
 };
 
 const upb_msglayout envoy_api_v2_route_RouteAction_HashPolicy_msginit = {
   &envoy_api_v2_route_RouteAction_HashPolicy_submsgs[0],
   &envoy_api_v2_route_RouteAction_HashPolicy__fields[0],
-  UPB_SIZE(12, 24), 5, false,
+  UPB_SIZE(12, 24), 6, false,
 };
 
 static const upb_msglayout_field envoy_api_v2_route_RouteAction_HashPolicy_Header__fields[1] = {
@@ -459,6 +471,16 @@ const upb_msglayout envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter_msg
   UPB_SIZE(8, 16), 1, false,
 };
 
+static const upb_msglayout_field envoy_api_v2_route_RouteAction_HashPolicy_FilterState__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 9, 1},
+};
+
+const upb_msglayout envoy_api_v2_route_RouteAction_HashPolicy_FilterState_msginit = {
+  NULL,
+  &envoy_api_v2_route_RouteAction_HashPolicy_FilterState__fields[0],
+  UPB_SIZE(8, 16), 1, false,
+};
+
 static const upb_msglayout *const envoy_api_v2_route_RouteAction_UpgradeConfig_submsgs[1] = {
   &google_protobuf_BoolValue_msginit,
 };
index ac2640b..8380be5 100644 (file)
@@ -42,6 +42,7 @@ struct envoy_api_v2_route_RouteAction_HashPolicy_Header;
 struct envoy_api_v2_route_RouteAction_HashPolicy_Cookie;
 struct envoy_api_v2_route_RouteAction_HashPolicy_ConnectionProperties;
 struct envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter;
+struct envoy_api_v2_route_RouteAction_HashPolicy_FilterState;
 struct envoy_api_v2_route_RouteAction_UpgradeConfig;
 struct envoy_api_v2_route_RetryPolicy;
 struct envoy_api_v2_route_RetryPolicy_RetryPriority;
@@ -85,6 +86,7 @@ typedef struct envoy_api_v2_route_RouteAction_HashPolicy_Header envoy_api_v2_rou
 typedef struct envoy_api_v2_route_RouteAction_HashPolicy_Cookie envoy_api_v2_route_RouteAction_HashPolicy_Cookie;
 typedef struct envoy_api_v2_route_RouteAction_HashPolicy_ConnectionProperties envoy_api_v2_route_RouteAction_HashPolicy_ConnectionProperties;
 typedef struct envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter;
+typedef struct envoy_api_v2_route_RouteAction_HashPolicy_FilterState envoy_api_v2_route_RouteAction_HashPolicy_FilterState;
 typedef struct envoy_api_v2_route_RouteAction_UpgradeConfig envoy_api_v2_route_RouteAction_UpgradeConfig;
 typedef struct envoy_api_v2_route_RetryPolicy envoy_api_v2_route_RetryPolicy;
 typedef struct envoy_api_v2_route_RetryPolicy_RetryPriority envoy_api_v2_route_RetryPolicy_RetryPriority;
@@ -128,6 +130,7 @@ extern const upb_msglayout envoy_api_v2_route_RouteAction_HashPolicy_Header_msgi
 extern const upb_msglayout envoy_api_v2_route_RouteAction_HashPolicy_Cookie_msginit;
 extern const upb_msglayout envoy_api_v2_route_RouteAction_HashPolicy_ConnectionProperties_msginit;
 extern const upb_msglayout envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter_msginit;
+extern const upb_msglayout envoy_api_v2_route_RouteAction_HashPolicy_FilterState_msginit;
 extern const upb_msglayout envoy_api_v2_route_RouteAction_UpgradeConfig_msginit;
 extern const upb_msglayout envoy_api_v2_route_RetryPolicy_msginit;
 extern const upb_msglayout envoy_api_v2_route_RetryPolicy_RetryPriority_msginit;
@@ -155,6 +158,7 @@ struct envoy_api_v2_core_Metadata;
 struct envoy_api_v2_core_RuntimeFractionalPercent;
 struct envoy_type_FractionalPercent;
 struct envoy_type_Int64Range;
+struct envoy_type_matcher_RegexMatchAndSubstitute;
 struct envoy_type_matcher_RegexMatcher;
 struct envoy_type_matcher_StringMatcher;
 struct envoy_type_tracing_v2_CustomTag;
@@ -169,6 +173,7 @@ extern const upb_msglayout envoy_api_v2_core_Metadata_msginit;
 extern const upb_msglayout envoy_api_v2_core_RuntimeFractionalPercent_msginit;
 extern const upb_msglayout envoy_type_FractionalPercent_msginit;
 extern const upb_msglayout envoy_type_Int64Range_msginit;
+extern const upb_msglayout envoy_type_matcher_RegexMatchAndSubstitute_msginit;
 extern const upb_msglayout envoy_type_matcher_RegexMatcher_msginit;
 extern const upb_msglayout envoy_type_matcher_StringMatcher_msginit;
 extern const upb_msglayout envoy_type_tracing_v2_CustomTag_msginit;
@@ -218,46 +223,48 @@ UPB_INLINE char *envoy_api_v2_route_VirtualHost_serialize(const envoy_api_v2_rou
 }
 
 UPB_INLINE upb_strview envoy_api_v2_route_VirtualHost_name(const envoy_api_v2_route_VirtualHost *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 16)); }
-UPB_INLINE upb_strview const* envoy_api_v2_route_VirtualHost_domains(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 64), len); }
-UPB_INLINE const envoy_api_v2_route_Route* const* envoy_api_v2_route_VirtualHost_routes(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const envoy_api_v2_route_Route* const*)_upb_array_accessor(msg, UPB_SIZE(40, 72), len); }
+UPB_INLINE upb_strview const* envoy_api_v2_route_VirtualHost_domains(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(40, 72), len); }
+UPB_INLINE const envoy_api_v2_route_Route* const* envoy_api_v2_route_VirtualHost_routes(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const envoy_api_v2_route_Route* const*)_upb_array_accessor(msg, UPB_SIZE(44, 80), len); }
 UPB_INLINE int32_t envoy_api_v2_route_VirtualHost_require_tls(const envoy_api_v2_route_VirtualHost *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)); }
-UPB_INLINE const envoy_api_v2_route_VirtualCluster* const* envoy_api_v2_route_VirtualHost_virtual_clusters(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const envoy_api_v2_route_VirtualCluster* const*)_upb_array_accessor(msg, UPB_SIZE(44, 80), len); }
-UPB_INLINE const envoy_api_v2_route_RateLimit* const* envoy_api_v2_route_VirtualHost_rate_limits(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const envoy_api_v2_route_RateLimit* const*)_upb_array_accessor(msg, UPB_SIZE(48, 88), len); }
-UPB_INLINE const struct envoy_api_v2_core_HeaderValueOption* const* envoy_api_v2_route_VirtualHost_request_headers_to_add(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const struct envoy_api_v2_core_HeaderValueOption* const*)_upb_array_accessor(msg, UPB_SIZE(52, 96), len); }
+UPB_INLINE const envoy_api_v2_route_VirtualCluster* const* envoy_api_v2_route_VirtualHost_virtual_clusters(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const envoy_api_v2_route_VirtualCluster* const*)_upb_array_accessor(msg, UPB_SIZE(48, 88), len); }
+UPB_INLINE const envoy_api_v2_route_RateLimit* const* envoy_api_v2_route_VirtualHost_rate_limits(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const envoy_api_v2_route_RateLimit* const*)_upb_array_accessor(msg, UPB_SIZE(52, 96), len); }
+UPB_INLINE const struct envoy_api_v2_core_HeaderValueOption* const* envoy_api_v2_route_VirtualHost_request_headers_to_add(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const struct envoy_api_v2_core_HeaderValueOption* const*)_upb_array_accessor(msg, UPB_SIZE(56, 104), len); }
 UPB_INLINE const envoy_api_v2_route_CorsPolicy* envoy_api_v2_route_VirtualHost_cors(const envoy_api_v2_route_VirtualHost *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_route_CorsPolicy*, UPB_SIZE(20, 32)); }
-UPB_INLINE const struct envoy_api_v2_core_HeaderValueOption* const* envoy_api_v2_route_VirtualHost_response_headers_to_add(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const struct envoy_api_v2_core_HeaderValueOption* const*)_upb_array_accessor(msg, UPB_SIZE(56, 104), len); }
-UPB_INLINE upb_strview const* envoy_api_v2_route_VirtualHost_response_headers_to_remove(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(60, 112), len); }
-UPB_INLINE const envoy_api_v2_route_VirtualHost_PerFilterConfigEntry* const* envoy_api_v2_route_VirtualHost_per_filter_config(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const envoy_api_v2_route_VirtualHost_PerFilterConfigEntry* const*)_upb_array_accessor(msg, UPB_SIZE(64, 120), len); }
-UPB_INLINE upb_strview const* envoy_api_v2_route_VirtualHost_request_headers_to_remove(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(68, 128), len); }
+UPB_INLINE const struct envoy_api_v2_core_HeaderValueOption* const* envoy_api_v2_route_VirtualHost_response_headers_to_add(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const struct envoy_api_v2_core_HeaderValueOption* const*)_upb_array_accessor(msg, UPB_SIZE(60, 112), len); }
+UPB_INLINE upb_strview const* envoy_api_v2_route_VirtualHost_response_headers_to_remove(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(64, 120), len); }
+UPB_INLINE const envoy_api_v2_route_VirtualHost_PerFilterConfigEntry* const* envoy_api_v2_route_VirtualHost_per_filter_config(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const envoy_api_v2_route_VirtualHost_PerFilterConfigEntry* const*)_upb_array_accessor(msg, UPB_SIZE(68, 128), len); }
+UPB_INLINE upb_strview const* envoy_api_v2_route_VirtualHost_request_headers_to_remove(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(72, 136), len); }
 UPB_INLINE bool envoy_api_v2_route_VirtualHost_include_request_attempt_count(const envoy_api_v2_route_VirtualHost *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(8, 8)); }
-UPB_INLINE const envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry* const* envoy_api_v2_route_VirtualHost_typed_per_filter_config(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry* const*)_upb_array_accessor(msg, UPB_SIZE(72, 136), len); }
+UPB_INLINE const envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry* const* envoy_api_v2_route_VirtualHost_typed_per_filter_config(const envoy_api_v2_route_VirtualHost *msg, size_t *len) { return (const envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry* const*)_upb_array_accessor(msg, UPB_SIZE(76, 144), len); }
 UPB_INLINE const envoy_api_v2_route_RetryPolicy* envoy_api_v2_route_VirtualHost_retry_policy(const envoy_api_v2_route_VirtualHost *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_route_RetryPolicy*, UPB_SIZE(24, 40)); }
 UPB_INLINE const envoy_api_v2_route_HedgePolicy* envoy_api_v2_route_VirtualHost_hedge_policy(const envoy_api_v2_route_VirtualHost *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_route_HedgePolicy*, UPB_SIZE(28, 48)); }
 UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_route_VirtualHost_per_request_buffer_limit_bytes(const envoy_api_v2_route_VirtualHost *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(32, 56)); }
+UPB_INLINE bool envoy_api_v2_route_VirtualHost_include_attempt_count_in_response(const envoy_api_v2_route_VirtualHost *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(9, 9)); }
+UPB_INLINE const struct google_protobuf_Any* envoy_api_v2_route_VirtualHost_retry_policy_typed_config(const envoy_api_v2_route_VirtualHost *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Any*, UPB_SIZE(36, 64)); }
 
 UPB_INLINE void envoy_api_v2_route_VirtualHost_set_name(envoy_api_v2_route_VirtualHost *msg, upb_strview value) {
   UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 16)) = value;
 }
 UPB_INLINE upb_strview* envoy_api_v2_route_VirtualHost_mutable_domains(envoy_api_v2_route_VirtualHost *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 64), len);
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 72), len);
 }
 UPB_INLINE upb_strview* envoy_api_v2_route_VirtualHost_resize_domains(envoy_api_v2_route_VirtualHost *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(36, 64), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(40, 72), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
 }
 UPB_INLINE bool envoy_api_v2_route_VirtualHost_add_domains(envoy_api_v2_route_VirtualHost *msg, upb_strview val, upb_arena *arena) {
   return _upb_array_append_accessor(
-      msg, UPB_SIZE(36, 64), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+      msg, UPB_SIZE(40, 72), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
 }
 UPB_INLINE envoy_api_v2_route_Route** envoy_api_v2_route_VirtualHost_mutable_routes(envoy_api_v2_route_VirtualHost *msg, size_t *len) {
-  return (envoy_api_v2_route_Route**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 72), len);
+  return (envoy_api_v2_route_Route**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 80), len);
 }
 UPB_INLINE envoy_api_v2_route_Route** envoy_api_v2_route_VirtualHost_resize_routes(envoy_api_v2_route_VirtualHost *msg, size_t len, upb_arena *arena) {
-  return (envoy_api_v2_route_Route**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 72), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (envoy_api_v2_route_Route**)_upb_array_resize_accessor(msg, UPB_SIZE(44, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_api_v2_route_Route* envoy_api_v2_route_VirtualHost_add_routes(envoy_api_v2_route_VirtualHost *msg, upb_arena *arena) {
   struct envoy_api_v2_route_Route* sub = (struct envoy_api_v2_route_Route*)upb_msg_new(&envoy_api_v2_route_Route_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(40, 72), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(44, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -265,41 +272,41 @@ UPB_INLINE void envoy_api_v2_route_VirtualHost_set_require_tls(envoy_api_v2_rout
   UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)) = value;
 }
 UPB_INLINE envoy_api_v2_route_VirtualCluster** envoy_api_v2_route_VirtualHost_mutable_virtual_clusters(envoy_api_v2_route_VirtualHost *msg, size_t *len) {
-  return (envoy_api_v2_route_VirtualCluster**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 80), len);
+  return (envoy_api_v2_route_VirtualCluster**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 88), len);
 }
 UPB_INLINE envoy_api_v2_route_VirtualCluster** envoy_api_v2_route_VirtualHost_resize_virtual_clusters(envoy_api_v2_route_VirtualHost *msg, size_t len, upb_arena *arena) {
-  return (envoy_api_v2_route_VirtualCluster**)_upb_array_resize_accessor(msg, UPB_SIZE(44, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (envoy_api_v2_route_VirtualCluster**)_upb_array_resize_accessor(msg, UPB_SIZE(48, 88), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_api_v2_route_VirtualCluster* envoy_api_v2_route_VirtualHost_add_virtual_clusters(envoy_api_v2_route_VirtualHost *msg, upb_arena *arena) {
   struct envoy_api_v2_route_VirtualCluster* sub = (struct envoy_api_v2_route_VirtualCluster*)upb_msg_new(&envoy_api_v2_route_VirtualCluster_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(44, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(48, 88), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
 UPB_INLINE envoy_api_v2_route_RateLimit** envoy_api_v2_route_VirtualHost_mutable_rate_limits(envoy_api_v2_route_VirtualHost *msg, size_t *len) {
-  return (envoy_api_v2_route_RateLimit**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 88), len);
+  return (envoy_api_v2_route_RateLimit**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 96), len);
 }
 UPB_INLINE envoy_api_v2_route_RateLimit** envoy_api_v2_route_VirtualHost_resize_rate_limits(envoy_api_v2_route_VirtualHost *msg, size_t len, upb_arena *arena) {
-  return (envoy_api_v2_route_RateLimit**)_upb_array_resize_accessor(msg, UPB_SIZE(48, 88), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (envoy_api_v2_route_RateLimit**)_upb_array_resize_accessor(msg, UPB_SIZE(52, 96), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_api_v2_route_RateLimit* envoy_api_v2_route_VirtualHost_add_rate_limits(envoy_api_v2_route_VirtualHost *msg, upb_arena *arena) {
   struct envoy_api_v2_route_RateLimit* sub = (struct envoy_api_v2_route_RateLimit*)upb_msg_new(&envoy_api_v2_route_RateLimit_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(48, 88), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(52, 96), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
 UPB_INLINE struct envoy_api_v2_core_HeaderValueOption** envoy_api_v2_route_VirtualHost_mutable_request_headers_to_add(envoy_api_v2_route_VirtualHost *msg, size_t *len) {
-  return (struct envoy_api_v2_core_HeaderValueOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 96), len);
+  return (struct envoy_api_v2_core_HeaderValueOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 104), len);
 }
 UPB_INLINE struct envoy_api_v2_core_HeaderValueOption** envoy_api_v2_route_VirtualHost_resize_request_headers_to_add(envoy_api_v2_route_VirtualHost *msg, size_t len, upb_arena *arena) {
-  return (struct envoy_api_v2_core_HeaderValueOption**)_upb_array_resize_accessor(msg, UPB_SIZE(52, 96), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (struct envoy_api_v2_core_HeaderValueOption**)_upb_array_resize_accessor(msg, UPB_SIZE(56, 104), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_api_v2_core_HeaderValueOption* envoy_api_v2_route_VirtualHost_add_request_headers_to_add(envoy_api_v2_route_VirtualHost *msg, upb_arena *arena) {
   struct envoy_api_v2_core_HeaderValueOption* sub = (struct envoy_api_v2_core_HeaderValueOption*)upb_msg_new(&envoy_api_v2_core_HeaderValueOption_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(52, 96), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(56, 104), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -316,64 +323,64 @@ UPB_INLINE struct envoy_api_v2_route_CorsPolicy* envoy_api_v2_route_VirtualHost_
   return sub;
 }
 UPB_INLINE struct envoy_api_v2_core_HeaderValueOption** envoy_api_v2_route_VirtualHost_mutable_response_headers_to_add(envoy_api_v2_route_VirtualHost *msg, size_t *len) {
-  return (struct envoy_api_v2_core_HeaderValueOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 104), len);
+  return (struct envoy_api_v2_core_HeaderValueOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 112), len);
 }
 UPB_INLINE struct envoy_api_v2_core_HeaderValueOption** envoy_api_v2_route_VirtualHost_resize_response_headers_to_add(envoy_api_v2_route_VirtualHost *msg, size_t len, upb_arena *arena) {
-  return (struct envoy_api_v2_core_HeaderValueOption**)_upb_array_resize_accessor(msg, UPB_SIZE(56, 104), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (struct envoy_api_v2_core_HeaderValueOption**)_upb_array_resize_accessor(msg, UPB_SIZE(60, 112), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_api_v2_core_HeaderValueOption* envoy_api_v2_route_VirtualHost_add_response_headers_to_add(envoy_api_v2_route_VirtualHost *msg, upb_arena *arena) {
   struct envoy_api_v2_core_HeaderValueOption* sub = (struct envoy_api_v2_core_HeaderValueOption*)upb_msg_new(&envoy_api_v2_core_HeaderValueOption_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(56, 104), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(60, 112), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
 UPB_INLINE upb_strview* envoy_api_v2_route_VirtualHost_mutable_response_headers_to_remove(envoy_api_v2_route_VirtualHost *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 112), len);
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(64, 120), len);
 }
 UPB_INLINE upb_strview* envoy_api_v2_route_VirtualHost_resize_response_headers_to_remove(envoy_api_v2_route_VirtualHost *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(60, 112), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(64, 120), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
 }
 UPB_INLINE bool envoy_api_v2_route_VirtualHost_add_response_headers_to_remove(envoy_api_v2_route_VirtualHost *msg, upb_strview val, upb_arena *arena) {
   return _upb_array_append_accessor(
-      msg, UPB_SIZE(60, 112), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+      msg, UPB_SIZE(64, 120), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
 }
 UPB_INLINE envoy_api_v2_route_VirtualHost_PerFilterConfigEntry** envoy_api_v2_route_VirtualHost_mutable_per_filter_config(envoy_api_v2_route_VirtualHost *msg, size_t *len) {
-  return (envoy_api_v2_route_VirtualHost_PerFilterConfigEntry**)_upb_array_mutable_accessor(msg, UPB_SIZE(64, 120), len);
+  return (envoy_api_v2_route_VirtualHost_PerFilterConfigEntry**)_upb_array_mutable_accessor(msg, UPB_SIZE(68, 128), len);
 }
 UPB_INLINE envoy_api_v2_route_VirtualHost_PerFilterConfigEntry** envoy_api_v2_route_VirtualHost_resize_per_filter_config(envoy_api_v2_route_VirtualHost *msg, size_t len, upb_arena *arena) {
-  return (envoy_api_v2_route_VirtualHost_PerFilterConfigEntry**)_upb_array_resize_accessor(msg, UPB_SIZE(64, 120), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (envoy_api_v2_route_VirtualHost_PerFilterConfigEntry**)_upb_array_resize_accessor(msg, UPB_SIZE(68, 128), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_api_v2_route_VirtualHost_PerFilterConfigEntry* envoy_api_v2_route_VirtualHost_add_per_filter_config(envoy_api_v2_route_VirtualHost *msg, upb_arena *arena) {
   struct envoy_api_v2_route_VirtualHost_PerFilterConfigEntry* sub = (struct envoy_api_v2_route_VirtualHost_PerFilterConfigEntry*)upb_msg_new(&envoy_api_v2_route_VirtualHost_PerFilterConfigEntry_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(64, 120), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(68, 128), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
 UPB_INLINE upb_strview* envoy_api_v2_route_VirtualHost_mutable_request_headers_to_remove(envoy_api_v2_route_VirtualHost *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(68, 128), len);
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(72, 136), len);
 }
 UPB_INLINE upb_strview* envoy_api_v2_route_VirtualHost_resize_request_headers_to_remove(envoy_api_v2_route_VirtualHost *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(68, 128), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(72, 136), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
 }
 UPB_INLINE bool envoy_api_v2_route_VirtualHost_add_request_headers_to_remove(envoy_api_v2_route_VirtualHost *msg, upb_strview val, upb_arena *arena) {
   return _upb_array_append_accessor(
-      msg, UPB_SIZE(68, 128), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+      msg, UPB_SIZE(72, 136), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
 }
 UPB_INLINE void envoy_api_v2_route_VirtualHost_set_include_request_attempt_count(envoy_api_v2_route_VirtualHost *msg, bool value) {
   UPB_FIELD_AT(msg, bool, UPB_SIZE(8, 8)) = value;
 }
 UPB_INLINE envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry** envoy_api_v2_route_VirtualHost_mutable_typed_per_filter_config(envoy_api_v2_route_VirtualHost *msg, size_t *len) {
-  return (envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry**)_upb_array_mutable_accessor(msg, UPB_SIZE(72, 136), len);
+  return (envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry**)_upb_array_mutable_accessor(msg, UPB_SIZE(76, 144), len);
 }
 UPB_INLINE envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry** envoy_api_v2_route_VirtualHost_resize_typed_per_filter_config(envoy_api_v2_route_VirtualHost *msg, size_t len, upb_arena *arena) {
-  return (envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry**)_upb_array_resize_accessor(msg, UPB_SIZE(72, 136), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry**)_upb_array_resize_accessor(msg, UPB_SIZE(76, 144), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry* envoy_api_v2_route_VirtualHost_add_typed_per_filter_config(envoy_api_v2_route_VirtualHost *msg, upb_arena *arena) {
   struct envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry* sub = (struct envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry*)upb_msg_new(&envoy_api_v2_route_VirtualHost_TypedPerFilterConfigEntry_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(72, 136), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(76, 144), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -413,6 +420,21 @@ UPB_INLINE struct google_protobuf_UInt32Value* envoy_api_v2_route_VirtualHost_mu
   }
   return sub;
 }
+UPB_INLINE void envoy_api_v2_route_VirtualHost_set_include_attempt_count_in_response(envoy_api_v2_route_VirtualHost *msg, bool value) {
+  UPB_FIELD_AT(msg, bool, UPB_SIZE(9, 9)) = value;
+}
+UPB_INLINE void envoy_api_v2_route_VirtualHost_set_retry_policy_typed_config(envoy_api_v2_route_VirtualHost *msg, struct google_protobuf_Any* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_Any*, UPB_SIZE(36, 64)) = value;
+}
+UPB_INLINE struct google_protobuf_Any* envoy_api_v2_route_VirtualHost_mutable_retry_policy_typed_config(envoy_api_v2_route_VirtualHost *msg, upb_arena *arena) {
+  struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_api_v2_route_VirtualHost_retry_policy_typed_config(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Any*)upb_msg_new(&google_protobuf_Any_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_route_VirtualHost_set_retry_policy_typed_config(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.api.v2.route.VirtualHost.PerFilterConfigEntry */
 
@@ -1381,7 +1403,7 @@ typedef enum {
   envoy_api_v2_route_RouteAction_cluster_specifier_weighted_clusters = 3,
   envoy_api_v2_route_RouteAction_cluster_specifier_NOT_SET = 0
 } envoy_api_v2_route_RouteAction_cluster_specifier_oneofcases;
-UPB_INLINE envoy_api_v2_route_RouteAction_cluster_specifier_oneofcases envoy_api_v2_route_RouteAction_cluster_specifier_case(const envoy_api_v2_route_RouteAction* msg) { return (envoy_api_v2_route_RouteAction_cluster_specifier_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(100, 176)); }
+UPB_INLINE envoy_api_v2_route_RouteAction_cluster_specifier_oneofcases envoy_api_v2_route_RouteAction_cluster_specifier_case(const envoy_api_v2_route_RouteAction* msg) { return (envoy_api_v2_route_RouteAction_cluster_specifier_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(108, 192)); }
 
 typedef enum {
   envoy_api_v2_route_RouteAction_host_rewrite_specifier_host_rewrite = 6,
@@ -1389,48 +1411,50 @@ typedef enum {
   envoy_api_v2_route_RouteAction_host_rewrite_specifier_auto_host_rewrite_header = 29,
   envoy_api_v2_route_RouteAction_host_rewrite_specifier_NOT_SET = 0
 } envoy_api_v2_route_RouteAction_host_rewrite_specifier_oneofcases;
-UPB_INLINE envoy_api_v2_route_RouteAction_host_rewrite_specifier_oneofcases envoy_api_v2_route_RouteAction_host_rewrite_specifier_case(const envoy_api_v2_route_RouteAction* msg) { return (envoy_api_v2_route_RouteAction_host_rewrite_specifier_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(112, 200)); }
-
-UPB_INLINE bool envoy_api_v2_route_RouteAction_has_cluster(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(100, 176), 1); }
-UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_cluster(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(92, 160), UPB_SIZE(100, 176), 1, upb_strview_make("", strlen(""))); }
-UPB_INLINE bool envoy_api_v2_route_RouteAction_has_cluster_header(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(100, 176), 2); }
-UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_cluster_header(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(92, 160), UPB_SIZE(100, 176), 2, upb_strview_make("", strlen(""))); }
-UPB_INLINE bool envoy_api_v2_route_RouteAction_has_weighted_clusters(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(100, 176), 3); }
-UPB_INLINE const envoy_api_v2_route_WeightedCluster* envoy_api_v2_route_RouteAction_weighted_clusters(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_route_WeightedCluster*, UPB_SIZE(92, 160), UPB_SIZE(100, 176), 3, NULL); }
+UPB_INLINE envoy_api_v2_route_RouteAction_host_rewrite_specifier_oneofcases envoy_api_v2_route_RouteAction_host_rewrite_specifier_case(const envoy_api_v2_route_RouteAction* msg) { return (envoy_api_v2_route_RouteAction_host_rewrite_specifier_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(120, 216)); }
+
+UPB_INLINE bool envoy_api_v2_route_RouteAction_has_cluster(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(108, 192), 1); }
+UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_cluster(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(100, 176), UPB_SIZE(108, 192), 1, upb_strview_make("", strlen(""))); }
+UPB_INLINE bool envoy_api_v2_route_RouteAction_has_cluster_header(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(108, 192), 2); }
+UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_cluster_header(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(100, 176), UPB_SIZE(108, 192), 2, upb_strview_make("", strlen(""))); }
+UPB_INLINE bool envoy_api_v2_route_RouteAction_has_weighted_clusters(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(108, 192), 3); }
+UPB_INLINE const envoy_api_v2_route_WeightedCluster* envoy_api_v2_route_RouteAction_weighted_clusters(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_route_WeightedCluster*, UPB_SIZE(100, 176), UPB_SIZE(108, 192), 3, NULL); }
 UPB_INLINE const struct envoy_api_v2_core_Metadata* envoy_api_v2_route_RouteAction_metadata_match(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_Metadata*, UPB_SIZE(32, 40)); }
 UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_prefix_rewrite(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(24, 24)); }
-UPB_INLINE bool envoy_api_v2_route_RouteAction_has_host_rewrite(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(112, 200), 6); }
-UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_host_rewrite(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(104, 184), UPB_SIZE(112, 200), 6, upb_strview_make("", strlen(""))); }
-UPB_INLINE bool envoy_api_v2_route_RouteAction_has_auto_host_rewrite(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(112, 200), 7); }
-UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_route_RouteAction_auto_host_rewrite(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(104, 184), UPB_SIZE(112, 200), 7, NULL); }
+UPB_INLINE bool envoy_api_v2_route_RouteAction_has_host_rewrite(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 216), 6); }
+UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_host_rewrite(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(112, 200), UPB_SIZE(120, 216), 6, upb_strview_make("", strlen(""))); }
+UPB_INLINE bool envoy_api_v2_route_RouteAction_has_auto_host_rewrite(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 216), 7); }
+UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_route_RouteAction_auto_host_rewrite(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(112, 200), UPB_SIZE(120, 216), 7, NULL); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_route_RouteAction_timeout(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(36, 48)); }
 UPB_INLINE const envoy_api_v2_route_RetryPolicy* envoy_api_v2_route_RouteAction_retry_policy(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_route_RetryPolicy*, UPB_SIZE(40, 56)); }
 UPB_INLINE const envoy_api_v2_route_RouteAction_RequestMirrorPolicy* envoy_api_v2_route_RouteAction_request_mirror_policy(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_route_RouteAction_RequestMirrorPolicy*, UPB_SIZE(44, 64)); }
 UPB_INLINE int32_t envoy_api_v2_route_RouteAction_priority(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)); }
-UPB_INLINE const envoy_api_v2_route_RateLimit* const* envoy_api_v2_route_RouteAction_rate_limits(const envoy_api_v2_route_RouteAction *msg, size_t *len) { return (const envoy_api_v2_route_RateLimit* const*)_upb_array_accessor(msg, UPB_SIZE(76, 128), len); }
+UPB_INLINE const envoy_api_v2_route_RateLimit* const* envoy_api_v2_route_RouteAction_rate_limits(const envoy_api_v2_route_RouteAction *msg, size_t *len) { return (const envoy_api_v2_route_RateLimit* const*)_upb_array_accessor(msg, UPB_SIZE(84, 144), len); }
 UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_route_RouteAction_include_vh_rate_limits(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(48, 72)); }
-UPB_INLINE const envoy_api_v2_route_RouteAction_HashPolicy* const* envoy_api_v2_route_RouteAction_hash_policy(const envoy_api_v2_route_RouteAction *msg, size_t *len) { return (const envoy_api_v2_route_RouteAction_HashPolicy* const*)_upb_array_accessor(msg, UPB_SIZE(80, 136), len); }
+UPB_INLINE const envoy_api_v2_route_RouteAction_HashPolicy* const* envoy_api_v2_route_RouteAction_hash_policy(const envoy_api_v2_route_RouteAction *msg, size_t *len) { return (const envoy_api_v2_route_RouteAction_HashPolicy* const*)_upb_array_accessor(msg, UPB_SIZE(88, 152), len); }
 UPB_INLINE const envoy_api_v2_route_CorsPolicy* envoy_api_v2_route_RouteAction_cors(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_route_CorsPolicy*, UPB_SIZE(52, 80)); }
 UPB_INLINE int32_t envoy_api_v2_route_RouteAction_cluster_not_found_response_code(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_route_RouteAction_max_grpc_timeout(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(56, 88)); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_route_RouteAction_idle_timeout(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(60, 96)); }
-UPB_INLINE const envoy_api_v2_route_RouteAction_UpgradeConfig* const* envoy_api_v2_route_RouteAction_upgrade_configs(const envoy_api_v2_route_RouteAction *msg, size_t *len) { return (const envoy_api_v2_route_RouteAction_UpgradeConfig* const*)_upb_array_accessor(msg, UPB_SIZE(84, 144), len); }
+UPB_INLINE const envoy_api_v2_route_RouteAction_UpgradeConfig* const* envoy_api_v2_route_RouteAction_upgrade_configs(const envoy_api_v2_route_RouteAction *msg, size_t *len) { return (const envoy_api_v2_route_RouteAction_UpgradeConfig* const*)_upb_array_accessor(msg, UPB_SIZE(92, 160), len); }
 UPB_INLINE int32_t envoy_api_v2_route_RouteAction_internal_redirect_action(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); }
 UPB_INLINE const envoy_api_v2_route_HedgePolicy* envoy_api_v2_route_RouteAction_hedge_policy(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const envoy_api_v2_route_HedgePolicy*, UPB_SIZE(64, 104)); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_route_RouteAction_grpc_timeout_offset(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(68, 112)); }
-UPB_INLINE bool envoy_api_v2_route_RouteAction_has_auto_host_rewrite_header(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(112, 200), 29); }
-UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_auto_host_rewrite_header(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(104, 184), UPB_SIZE(112, 200), 29, upb_strview_make("", strlen(""))); }
-UPB_INLINE const envoy_api_v2_route_RouteAction_RequestMirrorPolicy* const* envoy_api_v2_route_RouteAction_request_mirror_policies(const envoy_api_v2_route_RouteAction *msg, size_t *len) { return (const envoy_api_v2_route_RouteAction_RequestMirrorPolicy* const*)_upb_array_accessor(msg, UPB_SIZE(88, 152), len); }
+UPB_INLINE bool envoy_api_v2_route_RouteAction_has_auto_host_rewrite_header(const envoy_api_v2_route_RouteAction *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 216), 29); }
+UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_auto_host_rewrite_header(const envoy_api_v2_route_RouteAction *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(112, 200), UPB_SIZE(120, 216), 29, upb_strview_make("", strlen(""))); }
+UPB_INLINE const envoy_api_v2_route_RouteAction_RequestMirrorPolicy* const* envoy_api_v2_route_RouteAction_request_mirror_policies(const envoy_api_v2_route_RouteAction *msg, size_t *len) { return (const envoy_api_v2_route_RouteAction_RequestMirrorPolicy* const*)_upb_array_accessor(msg, UPB_SIZE(96, 168), len); }
 UPB_INLINE const struct google_protobuf_UInt32Value* envoy_api_v2_route_RouteAction_max_internal_redirects(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(72, 120)); }
+UPB_INLINE const struct envoy_type_matcher_RegexMatchAndSubstitute* envoy_api_v2_route_RouteAction_regex_rewrite(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const struct envoy_type_matcher_RegexMatchAndSubstitute*, UPB_SIZE(76, 128)); }
+UPB_INLINE const struct google_protobuf_Any* envoy_api_v2_route_RouteAction_retry_policy_typed_config(const envoy_api_v2_route_RouteAction *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Any*, UPB_SIZE(80, 136)); }
 
 UPB_INLINE void envoy_api_v2_route_RouteAction_set_cluster(envoy_api_v2_route_RouteAction *msg, upb_strview value) {
-  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(92, 160), value, UPB_SIZE(100, 176), 1);
+  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(100, 176), value, UPB_SIZE(108, 192), 1);
 }
 UPB_INLINE void envoy_api_v2_route_RouteAction_set_cluster_header(envoy_api_v2_route_RouteAction *msg, upb_strview value) {
-  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(92, 160), value, UPB_SIZE(100, 176), 2);
+  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(100, 176), value, UPB_SIZE(108, 192), 2);
 }
 UPB_INLINE void envoy_api_v2_route_RouteAction_set_weighted_clusters(envoy_api_v2_route_RouteAction *msg, envoy_api_v2_route_WeightedCluster* value) {
-  UPB_WRITE_ONEOF(msg, envoy_api_v2_route_WeightedCluster*, UPB_SIZE(92, 160), value, UPB_SIZE(100, 176), 3);
+  UPB_WRITE_ONEOF(msg, envoy_api_v2_route_WeightedCluster*, UPB_SIZE(100, 176), value, UPB_SIZE(108, 192), 3);
 }
 UPB_INLINE struct envoy_api_v2_route_WeightedCluster* envoy_api_v2_route_RouteAction_mutable_weighted_clusters(envoy_api_v2_route_RouteAction *msg, upb_arena *arena) {
   struct envoy_api_v2_route_WeightedCluster* sub = (struct envoy_api_v2_route_WeightedCluster*)envoy_api_v2_route_RouteAction_weighted_clusters(msg);
@@ -1457,10 +1481,10 @@ UPB_INLINE void envoy_api_v2_route_RouteAction_set_prefix_rewrite(envoy_api_v2_r
   UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(24, 24)) = value;
 }
 UPB_INLINE void envoy_api_v2_route_RouteAction_set_host_rewrite(envoy_api_v2_route_RouteAction *msg, upb_strview value) {
-  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(104, 184), value, UPB_SIZE(112, 200), 6);
+  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(112, 200), value, UPB_SIZE(120, 216), 6);
 }
 UPB_INLINE void envoy_api_v2_route_RouteAction_set_auto_host_rewrite(envoy_api_v2_route_RouteAction *msg, struct google_protobuf_BoolValue* value) {
-  UPB_WRITE_ONEOF(msg, struct google_protobuf_BoolValue*, UPB_SIZE(104, 184), value, UPB_SIZE(112, 200), 7);
+  UPB_WRITE_ONEOF(msg, struct google_protobuf_BoolValue*, UPB_SIZE(112, 200), value, UPB_SIZE(120, 216), 7);
 }
 UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_route_RouteAction_mutable_auto_host_rewrite(envoy_api_v2_route_RouteAction *msg, upb_arena *arena) {
   struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_api_v2_route_RouteAction_auto_host_rewrite(msg);
@@ -1511,15 +1535,15 @@ UPB_INLINE void envoy_api_v2_route_RouteAction_set_priority(envoy_api_v2_route_R
   UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)) = value;
 }
 UPB_INLINE envoy_api_v2_route_RateLimit** envoy_api_v2_route_RouteAction_mutable_rate_limits(envoy_api_v2_route_RouteAction *msg, size_t *len) {
-  return (envoy_api_v2_route_RateLimit**)_upb_array_mutable_accessor(msg, UPB_SIZE(76, 128), len);
+  return (envoy_api_v2_route_RateLimit**)_upb_array_mutable_accessor(msg, UPB_SIZE(84, 144), len);
 }
 UPB_INLINE envoy_api_v2_route_RateLimit** envoy_api_v2_route_RouteAction_resize_rate_limits(envoy_api_v2_route_RouteAction *msg, size_t len, upb_arena *arena) {
-  return (envoy_api_v2_route_RateLimit**)_upb_array_resize_accessor(msg, UPB_SIZE(76, 128), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (envoy_api_v2_route_RateLimit**)_upb_array_resize_accessor(msg, UPB_SIZE(84, 144), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_api_v2_route_RateLimit* envoy_api_v2_route_RouteAction_add_rate_limits(envoy_api_v2_route_RouteAction *msg, upb_arena *arena) {
   struct envoy_api_v2_route_RateLimit* sub = (struct envoy_api_v2_route_RateLimit*)upb_msg_new(&envoy_api_v2_route_RateLimit_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(76, 128), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(84, 144), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -1536,15 +1560,15 @@ UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_route_RouteAction_muta
   return sub;
 }
 UPB_INLINE envoy_api_v2_route_RouteAction_HashPolicy** envoy_api_v2_route_RouteAction_mutable_hash_policy(envoy_api_v2_route_RouteAction *msg, size_t *len) {
-  return (envoy_api_v2_route_RouteAction_HashPolicy**)_upb_array_mutable_accessor(msg, UPB_SIZE(80, 136), len);
+  return (envoy_api_v2_route_RouteAction_HashPolicy**)_upb_array_mutable_accessor(msg, UPB_SIZE(88, 152), len);
 }
 UPB_INLINE envoy_api_v2_route_RouteAction_HashPolicy** envoy_api_v2_route_RouteAction_resize_hash_policy(envoy_api_v2_route_RouteAction *msg, size_t len, upb_arena *arena) {
-  return (envoy_api_v2_route_RouteAction_HashPolicy**)_upb_array_resize_accessor(msg, UPB_SIZE(80, 136), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (envoy_api_v2_route_RouteAction_HashPolicy**)_upb_array_resize_accessor(msg, UPB_SIZE(88, 152), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_api_v2_route_RouteAction_HashPolicy* envoy_api_v2_route_RouteAction_add_hash_policy(envoy_api_v2_route_RouteAction *msg, upb_arena *arena) {
   struct envoy_api_v2_route_RouteAction_HashPolicy* sub = (struct envoy_api_v2_route_RouteAction_HashPolicy*)upb_msg_new(&envoy_api_v2_route_RouteAction_HashPolicy_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(80, 136), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(88, 152), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -1588,15 +1612,15 @@ UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_route_RouteAction_mutab
   return sub;
 }
 UPB_INLINE envoy_api_v2_route_RouteAction_UpgradeConfig** envoy_api_v2_route_RouteAction_mutable_upgrade_configs(envoy_api_v2_route_RouteAction *msg, size_t *len) {
-  return (envoy_api_v2_route_RouteAction_UpgradeConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(84, 144), len);
+  return (envoy_api_v2_route_RouteAction_UpgradeConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(92, 160), len);
 }
 UPB_INLINE envoy_api_v2_route_RouteAction_UpgradeConfig** envoy_api_v2_route_RouteAction_resize_upgrade_configs(envoy_api_v2_route_RouteAction *msg, size_t len, upb_arena *arena) {
-  return (envoy_api_v2_route_RouteAction_UpgradeConfig**)_upb_array_resize_accessor(msg, UPB_SIZE(84, 144), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (envoy_api_v2_route_RouteAction_UpgradeConfig**)_upb_array_resize_accessor(msg, UPB_SIZE(92, 160), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_api_v2_route_RouteAction_UpgradeConfig* envoy_api_v2_route_RouteAction_add_upgrade_configs(envoy_api_v2_route_RouteAction *msg, upb_arena *arena) {
   struct envoy_api_v2_route_RouteAction_UpgradeConfig* sub = (struct envoy_api_v2_route_RouteAction_UpgradeConfig*)upb_msg_new(&envoy_api_v2_route_RouteAction_UpgradeConfig_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(84, 144), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(92, 160), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -1628,18 +1652,18 @@ UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_route_RouteAction_mutab
   return sub;
 }
 UPB_INLINE void envoy_api_v2_route_RouteAction_set_auto_host_rewrite_header(envoy_api_v2_route_RouteAction *msg, upb_strview value) {
-  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(104, 184), value, UPB_SIZE(112, 200), 29);
+  UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(112, 200), value, UPB_SIZE(120, 216), 29);
 }
 UPB_INLINE envoy_api_v2_route_RouteAction_RequestMirrorPolicy** envoy_api_v2_route_RouteAction_mutable_request_mirror_policies(envoy_api_v2_route_RouteAction *msg, size_t *len) {
-  return (envoy_api_v2_route_RouteAction_RequestMirrorPolicy**)_upb_array_mutable_accessor(msg, UPB_SIZE(88, 152), len);
+  return (envoy_api_v2_route_RouteAction_RequestMirrorPolicy**)_upb_array_mutable_accessor(msg, UPB_SIZE(96, 168), len);
 }
 UPB_INLINE envoy_api_v2_route_RouteAction_RequestMirrorPolicy** envoy_api_v2_route_RouteAction_resize_request_mirror_policies(envoy_api_v2_route_RouteAction *msg, size_t len, upb_arena *arena) {
-  return (envoy_api_v2_route_RouteAction_RequestMirrorPolicy**)_upb_array_resize_accessor(msg, UPB_SIZE(88, 152), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (envoy_api_v2_route_RouteAction_RequestMirrorPolicy**)_upb_array_resize_accessor(msg, UPB_SIZE(96, 168), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_api_v2_route_RouteAction_RequestMirrorPolicy* envoy_api_v2_route_RouteAction_add_request_mirror_policies(envoy_api_v2_route_RouteAction *msg, upb_arena *arena) {
   struct envoy_api_v2_route_RouteAction_RequestMirrorPolicy* sub = (struct envoy_api_v2_route_RouteAction_RequestMirrorPolicy*)upb_msg_new(&envoy_api_v2_route_RouteAction_RequestMirrorPolicy_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(88, 152), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(96, 168), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -1655,6 +1679,30 @@ UPB_INLINE struct google_protobuf_UInt32Value* envoy_api_v2_route_RouteAction_mu
   }
   return sub;
 }
+UPB_INLINE void envoy_api_v2_route_RouteAction_set_regex_rewrite(envoy_api_v2_route_RouteAction *msg, struct envoy_type_matcher_RegexMatchAndSubstitute* value) {
+  UPB_FIELD_AT(msg, struct envoy_type_matcher_RegexMatchAndSubstitute*, UPB_SIZE(76, 128)) = value;
+}
+UPB_INLINE struct envoy_type_matcher_RegexMatchAndSubstitute* envoy_api_v2_route_RouteAction_mutable_regex_rewrite(envoy_api_v2_route_RouteAction *msg, upb_arena *arena) {
+  struct envoy_type_matcher_RegexMatchAndSubstitute* sub = (struct envoy_type_matcher_RegexMatchAndSubstitute*)envoy_api_v2_route_RouteAction_regex_rewrite(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_type_matcher_RegexMatchAndSubstitute*)upb_msg_new(&envoy_type_matcher_RegexMatchAndSubstitute_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_route_RouteAction_set_regex_rewrite(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_api_v2_route_RouteAction_set_retry_policy_typed_config(envoy_api_v2_route_RouteAction *msg, struct google_protobuf_Any* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_Any*, UPB_SIZE(80, 136)) = value;
+}
+UPB_INLINE struct google_protobuf_Any* envoy_api_v2_route_RouteAction_mutable_retry_policy_typed_config(envoy_api_v2_route_RouteAction *msg, upb_arena *arena) {
+  struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_api_v2_route_RouteAction_retry_policy_typed_config(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Any*)upb_msg_new(&google_protobuf_Any_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_route_RouteAction_set_retry_policy_typed_config(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.api.v2.route.RouteAction.RequestMirrorPolicy */
 
@@ -1673,6 +1721,7 @@ UPB_INLINE char *envoy_api_v2_route_RouteAction_RequestMirrorPolicy_serialize(co
 UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_RequestMirrorPolicy_cluster(const envoy_api_v2_route_RouteAction_RequestMirrorPolicy *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
 UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_RequestMirrorPolicy_runtime_key(const envoy_api_v2_route_RouteAction_RequestMirrorPolicy *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 16)); }
 UPB_INLINE const struct envoy_api_v2_core_RuntimeFractionalPercent* envoy_api_v2_route_RouteAction_RequestMirrorPolicy_runtime_fraction(const envoy_api_v2_route_RouteAction_RequestMirrorPolicy *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_RuntimeFractionalPercent*, UPB_SIZE(16, 32)); }
+UPB_INLINE const struct google_protobuf_BoolValue* envoy_api_v2_route_RouteAction_RequestMirrorPolicy_trace_sampled(const envoy_api_v2_route_RouteAction_RequestMirrorPolicy *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(20, 40)); }
 
 UPB_INLINE void envoy_api_v2_route_RouteAction_RequestMirrorPolicy_set_cluster(envoy_api_v2_route_RouteAction_RequestMirrorPolicy *msg, upb_strview value) {
   UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
@@ -1692,6 +1741,18 @@ UPB_INLINE struct envoy_api_v2_core_RuntimeFractionalPercent* envoy_api_v2_route
   }
   return sub;
 }
+UPB_INLINE void envoy_api_v2_route_RouteAction_RequestMirrorPolicy_set_trace_sampled(envoy_api_v2_route_RouteAction_RequestMirrorPolicy *msg, struct google_protobuf_BoolValue* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_BoolValue*, UPB_SIZE(20, 40)) = value;
+}
+UPB_INLINE struct google_protobuf_BoolValue* envoy_api_v2_route_RouteAction_RequestMirrorPolicy_mutable_trace_sampled(envoy_api_v2_route_RouteAction_RequestMirrorPolicy *msg, upb_arena *arena) {
+  struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_api_v2_route_RouteAction_RequestMirrorPolicy_trace_sampled(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_BoolValue*)upb_msg_new(&google_protobuf_BoolValue_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_route_RouteAction_RequestMirrorPolicy_set_trace_sampled(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.api.v2.route.RouteAction.HashPolicy */
 
@@ -1712,6 +1773,7 @@ typedef enum {
   envoy_api_v2_route_RouteAction_HashPolicy_policy_specifier_cookie = 2,
   envoy_api_v2_route_RouteAction_HashPolicy_policy_specifier_connection_properties = 3,
   envoy_api_v2_route_RouteAction_HashPolicy_policy_specifier_query_parameter = 5,
+  envoy_api_v2_route_RouteAction_HashPolicy_policy_specifier_filter_state = 6,
   envoy_api_v2_route_RouteAction_HashPolicy_policy_specifier_NOT_SET = 0
 } envoy_api_v2_route_RouteAction_HashPolicy_policy_specifier_oneofcases;
 UPB_INLINE envoy_api_v2_route_RouteAction_HashPolicy_policy_specifier_oneofcases envoy_api_v2_route_RouteAction_HashPolicy_policy_specifier_case(const envoy_api_v2_route_RouteAction_HashPolicy* msg) { return (envoy_api_v2_route_RouteAction_HashPolicy_policy_specifier_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 16)); }
@@ -1725,6 +1787,8 @@ UPB_INLINE const envoy_api_v2_route_RouteAction_HashPolicy_ConnectionProperties*
 UPB_INLINE bool envoy_api_v2_route_RouteAction_HashPolicy_terminal(const envoy_api_v2_route_RouteAction_HashPolicy *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)); }
 UPB_INLINE bool envoy_api_v2_route_RouteAction_HashPolicy_has_query_parameter(const envoy_api_v2_route_RouteAction_HashPolicy *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(8, 16), 5); }
 UPB_INLINE const envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter* envoy_api_v2_route_RouteAction_HashPolicy_query_parameter(const envoy_api_v2_route_RouteAction_HashPolicy *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter*, UPB_SIZE(4, 8), UPB_SIZE(8, 16), 5, NULL); }
+UPB_INLINE bool envoy_api_v2_route_RouteAction_HashPolicy_has_filter_state(const envoy_api_v2_route_RouteAction_HashPolicy *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(8, 16), 6); }
+UPB_INLINE const envoy_api_v2_route_RouteAction_HashPolicy_FilterState* envoy_api_v2_route_RouteAction_HashPolicy_filter_state(const envoy_api_v2_route_RouteAction_HashPolicy *msg) { return UPB_READ_ONEOF(msg, const envoy_api_v2_route_RouteAction_HashPolicy_FilterState*, UPB_SIZE(4, 8), UPB_SIZE(8, 16), 6, NULL); }
 
 UPB_INLINE void envoy_api_v2_route_RouteAction_HashPolicy_set_header(envoy_api_v2_route_RouteAction_HashPolicy *msg, envoy_api_v2_route_RouteAction_HashPolicy_Header* value) {
   UPB_WRITE_ONEOF(msg, envoy_api_v2_route_RouteAction_HashPolicy_Header*, UPB_SIZE(4, 8), value, UPB_SIZE(8, 16), 1);
@@ -1777,6 +1841,18 @@ UPB_INLINE struct envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter* envo
   }
   return sub;
 }
+UPB_INLINE void envoy_api_v2_route_RouteAction_HashPolicy_set_filter_state(envoy_api_v2_route_RouteAction_HashPolicy *msg, envoy_api_v2_route_RouteAction_HashPolicy_FilterState* value) {
+  UPB_WRITE_ONEOF(msg, envoy_api_v2_route_RouteAction_HashPolicy_FilterState*, UPB_SIZE(4, 8), value, UPB_SIZE(8, 16), 6);
+}
+UPB_INLINE struct envoy_api_v2_route_RouteAction_HashPolicy_FilterState* envoy_api_v2_route_RouteAction_HashPolicy_mutable_filter_state(envoy_api_v2_route_RouteAction_HashPolicy *msg, upb_arena *arena) {
+  struct envoy_api_v2_route_RouteAction_HashPolicy_FilterState* sub = (struct envoy_api_v2_route_RouteAction_HashPolicy_FilterState*)envoy_api_v2_route_RouteAction_HashPolicy_filter_state(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_api_v2_route_RouteAction_HashPolicy_FilterState*)upb_msg_new(&envoy_api_v2_route_RouteAction_HashPolicy_FilterState_msginit, arena);
+    if (!sub) return NULL;
+    envoy_api_v2_route_RouteAction_HashPolicy_set_filter_state(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.api.v2.route.RouteAction.HashPolicy.Header */
 
@@ -1875,6 +1951,26 @@ UPB_INLINE void envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter_set_nam
   UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
 }
 
+/* envoy.api.v2.route.RouteAction.HashPolicy.FilterState */
+
+UPB_INLINE envoy_api_v2_route_RouteAction_HashPolicy_FilterState *envoy_api_v2_route_RouteAction_HashPolicy_FilterState_new(upb_arena *arena) {
+  return (envoy_api_v2_route_RouteAction_HashPolicy_FilterState *)upb_msg_new(&envoy_api_v2_route_RouteAction_HashPolicy_FilterState_msginit, arena);
+}
+UPB_INLINE envoy_api_v2_route_RouteAction_HashPolicy_FilterState *envoy_api_v2_route_RouteAction_HashPolicy_FilterState_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_api_v2_route_RouteAction_HashPolicy_FilterState *ret = envoy_api_v2_route_RouteAction_HashPolicy_FilterState_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_api_v2_route_RouteAction_HashPolicy_FilterState_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_api_v2_route_RouteAction_HashPolicy_FilterState_serialize(const envoy_api_v2_route_RouteAction_HashPolicy_FilterState *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_api_v2_route_RouteAction_HashPolicy_FilterState_msginit, arena, len);
+}
+
+UPB_INLINE upb_strview envoy_api_v2_route_RouteAction_HashPolicy_FilterState_key(const envoy_api_v2_route_RouteAction_HashPolicy_FilterState *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
+
+UPB_INLINE void envoy_api_v2_route_RouteAction_HashPolicy_FilterState_set_key(envoy_api_v2_route_RouteAction_HashPolicy_FilterState *msg, upb_strview value) {
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
+}
+
 /* envoy.api.v2.route.RouteAction.UpgradeConfig */
 
 UPB_INLINE envoy_api_v2_route_RouteAction_UpgradeConfig *envoy_api_v2_route_RouteAction_UpgradeConfig_new(upb_arena *arena) {
index 6de0fdd..0526116 100644 (file)
@@ -10,6 +10,7 @@
 #include "upb/msg.h"
 #include "envoy/api/v2/scoped_route.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index 1711cb7..9b5a7f5 100644 (file)
@@ -13,6 +13,7 @@
 #include "google/api/annotations.upb.h"
 #include "envoy/annotations/resource.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "envoy/api/v2/scoped_route.upb.h"
 
 #include "upb/port_def.inc"
index d551ab2..42aef4f 100644 (file)
@@ -15,6 +15,7 @@
 #include "google/protobuf/any.upb.h"
 #include "google/protobuf/struct.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index b062628..c7f2bb1 100644 (file)
@@ -14,6 +14,7 @@
 #include "envoy/api/v2/route.upb.h"
 #include "envoy/api/v2/scoped_route.upb.h"
 #include "envoy/config/filter/accesslog/v2/accesslog.upb.h"
+#include "envoy/config/trace/v2/http_tracer.upb.h"
 #include "envoy/type/percent.upb.h"
 #include "envoy/type/tracing/v2/custom_tag.upb.h"
 #include "google/protobuf/any.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "envoy/annotations/deprecation.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
 
-static const upb_msglayout *const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_submsgs[22] = {
+static const upb_msglayout *const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_submsgs[23] = {
   &envoy_api_v2_RouteConfiguration_msginit,
   &envoy_api_v2_core_Http1ProtocolOptions_msginit,
   &envoy_api_v2_core_Http2ProtocolOptions_msginit,
@@ -38,28 +40,29 @@ static const upb_msglayout *const envoy_config_filter_network_http_connection_ma
   &envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig_msginit,
   &envoy_config_filter_network_http_connection_manager_v2_HttpFilter_msginit,
   &envoy_config_filter_network_http_connection_manager_v2_Rds_msginit,
+  &envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_msginit,
   &envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_msginit,
   &google_protobuf_BoolValue_msginit,
   &google_protobuf_Duration_msginit,
   &google_protobuf_UInt32Value_msginit,
 };
 
-static const upb_msglayout_field envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager__fields[34] = {
+static const upb_msglayout_field envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager__fields[35] = {
   {1, UPB_SIZE(0, 0), 0, 0, 14, 1},
   {2, UPB_SIZE(36, 40), 0, 0, 9, 1},
-  {3, UPB_SIZE(136, 240), UPB_SIZE(-141, -249), 10, 11, 1},
-  {4, UPB_SIZE(136, 240), UPB_SIZE(-141, -249), 0, 11, 1},
-  {5, UPB_SIZE(124, 216), 0, 9, 11, 3},
-  {6, UPB_SIZE(60, 88), 0, 12, 11, 1},
+  {3, UPB_SIZE(140, 248), UPB_SIZE(-145, -257), 10, 11, 1},
+  {4, UPB_SIZE(140, 248), UPB_SIZE(-145, -257), 0, 11, 1},
+  {5, UPB_SIZE(128, 224), 0, 9, 11, 3},
+  {6, UPB_SIZE(60, 88), 0, 13, 11, 1},
   {7, UPB_SIZE(64, 96), 0, 7, 11, 1},
   {8, UPB_SIZE(68, 104), 0, 1, 11, 1},
   {9, UPB_SIZE(72, 112), 0, 2, 11, 1},
   {10, UPB_SIZE(44, 56), 0, 0, 9, 1},
-  {11, UPB_SIZE(76, 120), 0, 13, 11, 1},
-  {12, UPB_SIZE(80, 128), 0, 13, 11, 1},
-  {13, UPB_SIZE(128, 224), 0, 4, 11, 3},
-  {14, UPB_SIZE(84, 136), 0, 12, 11, 1},
-  {15, UPB_SIZE(88, 144), 0, 12, 11, 1},
+  {11, UPB_SIZE(76, 120), 0, 14, 11, 1},
+  {12, UPB_SIZE(80, 128), 0, 14, 11, 1},
+  {13, UPB_SIZE(132, 232), 0, 4, 11, 3},
+  {14, UPB_SIZE(84, 136), 0, 13, 11, 1},
+  {15, UPB_SIZE(88, 144), 0, 13, 11, 1},
   {16, UPB_SIZE(8, 8), 0, 0, 14, 1},
   {17, UPB_SIZE(92, 152), 0, 6, 11, 1},
   {18, UPB_SIZE(28, 28), 0, 0, 8, 1},
@@ -67,47 +70,50 @@ static const upb_msglayout_field envoy_config_filter_network_http_connection_man
   {20, UPB_SIZE(29, 29), 0, 0, 8, 1},
   {21, UPB_SIZE(30, 30), 0, 0, 8, 1},
   {22, UPB_SIZE(52, 72), 0, 0, 9, 1},
-  {23, UPB_SIZE(132, 232), 0, 8, 11, 3},
-  {24, UPB_SIZE(96, 160), 0, 13, 11, 1},
+  {23, UPB_SIZE(136, 240), 0, 8, 11, 3},
+  {24, UPB_SIZE(96, 160), 0, 14, 11, 1},
   {25, UPB_SIZE(100, 168), 0, 5, 11, 1},
-  {26, UPB_SIZE(104, 176), 0, 13, 11, 1},
-  {28, UPB_SIZE(108, 184), 0, 13, 11, 1},
-  {29, UPB_SIZE(112, 192), 0, 14, 11, 1},
-  {30, UPB_SIZE(116, 200), 0, 12, 11, 1},
-  {31, UPB_SIZE(136, 240), UPB_SIZE(-141, -249), 11, 11, 1},
+  {26, UPB_SIZE(104, 176), 0, 14, 11, 1},
+  {28, UPB_SIZE(108, 184), 0, 14, 11, 1},
+  {29, UPB_SIZE(112, 192), 0, 15, 11, 1},
+  {30, UPB_SIZE(116, 200), 0, 13, 11, 1},
+  {31, UPB_SIZE(140, 248), UPB_SIZE(-145, -257), 12, 11, 1},
   {32, UPB_SIZE(31, 31), 0, 0, 8, 1},
   {33, UPB_SIZE(32, 32), 0, 0, 8, 1},
   {34, UPB_SIZE(16, 16), 0, 0, 14, 1},
   {35, UPB_SIZE(120, 208), 0, 3, 11, 1},
+  {36, UPB_SIZE(124, 216), 0, 11, 11, 1},
 };
 
 const upb_msglayout envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_msginit = {
   &envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_submsgs[0],
   &envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager__fields[0],
-  UPB_SIZE(144, 256), 34, false,
+  UPB_SIZE(152, 272), 35, false,
 };
 
-static const upb_msglayout *const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_submsgs[5] = {
+static const upb_msglayout *const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_submsgs[6] = {
+  &envoy_config_trace_v2_Tracing_Http_msginit,
   &envoy_type_Percent_msginit,
   &envoy_type_tracing_v2_CustomTag_msginit,
   &google_protobuf_UInt32Value_msginit,
 };
 
-static const upb_msglayout_field envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing__fields[8] = {
+static const upb_msglayout_field envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing__fields[9] = {
   {1, UPB_SIZE(0, 0), 0, 0, 14, 1},
-  {2, UPB_SIZE(28, 48), 0, 0, 9, 3},
-  {3, UPB_SIZE(12, 16), 0, 0, 11, 1},
-  {4, UPB_SIZE(16, 24), 0, 0, 11, 1},
-  {5, UPB_SIZE(20, 32), 0, 0, 11, 1},
+  {2, UPB_SIZE(32, 56), 0, 0, 9, 3},
+  {3, UPB_SIZE(12, 16), 0, 1, 11, 1},
+  {4, UPB_SIZE(16, 24), 0, 1, 11, 1},
+  {5, UPB_SIZE(20, 32), 0, 1, 11, 1},
   {6, UPB_SIZE(8, 8), 0, 0, 8, 1},
-  {7, UPB_SIZE(24, 40), 0, 2, 11, 1},
-  {8, UPB_SIZE(32, 56), 0, 1, 11, 3},
+  {7, UPB_SIZE(24, 40), 0, 3, 11, 1},
+  {8, UPB_SIZE(36, 64), 0, 2, 11, 3},
+  {9, UPB_SIZE(28, 48), 0, 0, 11, 1},
 };
 
 const upb_msglayout envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_msginit = {
   &envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_submsgs[0],
   &envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing__fields[0],
-  UPB_SIZE(40, 64), 8, false,
+  UPB_SIZE(40, 72), 9, false,
 };
 
 static const upb_msglayout_field envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig__fields[1] = {
@@ -292,5 +298,19 @@ const upb_msglayout envoy_config_filter_network_http_connection_manager_v2_HttpF
   UPB_SIZE(16, 32), 3, false,
 };
 
+static const upb_msglayout *const envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_submsgs[1] = {
+  &google_protobuf_Any_msginit,
+};
+
+static const upb_msglayout_field envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
+};
+
+const upb_msglayout envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_msginit = {
+  &envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_submsgs[0],
+  &envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension__fields[0],
+  UPB_SIZE(4, 8), 1, false,
+};
+
 #include "upb/port_undef.inc"
 
index 9425252..a0fe5c7 100644 (file)
@@ -34,6 +34,7 @@ struct envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_Scope
 struct envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement;
 struct envoy_config_filter_network_http_connection_manager_v2_ScopedRds;
 struct envoy_config_filter_network_http_connection_manager_v2_HttpFilter;
+struct envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension;
 typedef struct envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager;
 typedef struct envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing;
 typedef struct envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig;
@@ -48,6 +49,7 @@ typedef struct envoy_config_filter_network_http_connection_manager_v2_ScopedRout
 typedef struct envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement;
 typedef struct envoy_config_filter_network_http_connection_manager_v2_ScopedRds envoy_config_filter_network_http_connection_manager_v2_ScopedRds;
 typedef struct envoy_config_filter_network_http_connection_manager_v2_HttpFilter envoy_config_filter_network_http_connection_manager_v2_HttpFilter;
+typedef struct envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension;
 extern const upb_msglayout envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_msginit;
 extern const upb_msglayout envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_msginit;
 extern const upb_msglayout envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig_msginit;
@@ -62,6 +64,7 @@ extern const upb_msglayout envoy_config_filter_network_http_connection_manager_v
 extern const upb_msglayout envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement_msginit;
 extern const upb_msglayout envoy_config_filter_network_http_connection_manager_v2_ScopedRds_msginit;
 extern const upb_msglayout envoy_config_filter_network_http_connection_manager_v2_HttpFilter_msginit;
+extern const upb_msglayout envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_msginit;
 struct envoy_api_v2_RouteConfiguration;
 struct envoy_api_v2_ScopedRouteConfiguration;
 struct envoy_api_v2_core_ConfigSource;
@@ -69,6 +72,7 @@ struct envoy_api_v2_core_Http1ProtocolOptions;
 struct envoy_api_v2_core_Http2ProtocolOptions;
 struct envoy_api_v2_core_HttpProtocolOptions;
 struct envoy_config_filter_accesslog_v2_AccessLog;
+struct envoy_config_trace_v2_Tracing_Http;
 struct envoy_type_Percent;
 struct envoy_type_tracing_v2_CustomTag;
 struct google_protobuf_Any;
@@ -83,6 +87,7 @@ extern const upb_msglayout envoy_api_v2_core_Http1ProtocolOptions_msginit;
 extern const upb_msglayout envoy_api_v2_core_Http2ProtocolOptions_msginit;
 extern const upb_msglayout envoy_api_v2_core_HttpProtocolOptions_msginit;
 extern const upb_msglayout envoy_config_filter_accesslog_v2_AccessLog_msginit;
+extern const upb_msglayout envoy_config_trace_v2_Tracing_Http_msginit;
 extern const upb_msglayout envoy_type_Percent_msginit;
 extern const upb_msglayout envoy_type_tracing_v2_CustomTag_msginit;
 extern const upb_msglayout google_protobuf_Any_msginit;
@@ -138,15 +143,15 @@ typedef enum {
   envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_specifier_scoped_routes = 31,
   envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_specifier_NOT_SET = 0
 } envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_specifier_oneofcases;
-UPB_INLINE envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_specifier_oneofcases envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_specifier_case(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager* msg) { return (envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_specifier_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(140, 248)); }
+UPB_INLINE envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_specifier_oneofcases envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_specifier_case(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager* msg) { return (envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_specifier_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(144, 256)); }
 
 UPB_INLINE int32_t envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_codec_type(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)); }
 UPB_INLINE upb_strview envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_stat_prefix(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 40)); }
-UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_has_rds(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(140, 248), 3); }
-UPB_INLINE const envoy_config_filter_network_http_connection_manager_v2_Rds* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_rds(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_READ_ONEOF(msg, const envoy_config_filter_network_http_connection_manager_v2_Rds*, UPB_SIZE(136, 240), UPB_SIZE(140, 248), 3, NULL); }
-UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_has_route_config(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(140, 248), 4); }
-UPB_INLINE const struct envoy_api_v2_RouteConfiguration* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_config(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_READ_ONEOF(msg, const struct envoy_api_v2_RouteConfiguration*, UPB_SIZE(136, 240), UPB_SIZE(140, 248), 4, NULL); }
-UPB_INLINE const envoy_config_filter_network_http_connection_manager_v2_HttpFilter* const* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_http_filters(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t *len) { return (const envoy_config_filter_network_http_connection_manager_v2_HttpFilter* const*)_upb_array_accessor(msg, UPB_SIZE(124, 216), len); }
+UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_has_rds(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(144, 256), 3); }
+UPB_INLINE const envoy_config_filter_network_http_connection_manager_v2_Rds* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_rds(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_READ_ONEOF(msg, const envoy_config_filter_network_http_connection_manager_v2_Rds*, UPB_SIZE(140, 248), UPB_SIZE(144, 256), 3, NULL); }
+UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_has_route_config(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(144, 256), 4); }
+UPB_INLINE const struct envoy_api_v2_RouteConfiguration* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_config(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_READ_ONEOF(msg, const struct envoy_api_v2_RouteConfiguration*, UPB_SIZE(140, 248), UPB_SIZE(144, 256), 4, NULL); }
+UPB_INLINE const envoy_config_filter_network_http_connection_manager_v2_HttpFilter* const* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_http_filters(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t *len) { return (const envoy_config_filter_network_http_connection_manager_v2_HttpFilter* const*)_upb_array_accessor(msg, UPB_SIZE(128, 224), len); }
 UPB_INLINE const struct google_protobuf_BoolValue* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_add_user_agent(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(60, 88)); }
 UPB_INLINE const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_tracing(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing*, UPB_SIZE(64, 96)); }
 UPB_INLINE const struct envoy_api_v2_core_Http1ProtocolOptions* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_http_protocol_options(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_Http1ProtocolOptions*, UPB_SIZE(68, 104)); }
@@ -154,7 +159,7 @@ UPB_INLINE const struct envoy_api_v2_core_Http2ProtocolOptions* envoy_config_fil
 UPB_INLINE upb_strview envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_server_name(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(44, 56)); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_idle_timeout(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(76, 120)); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_drain_timeout(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(80, 128)); }
-UPB_INLINE const struct envoy_config_filter_accesslog_v2_AccessLog* const* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_access_log(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t *len) { return (const struct envoy_config_filter_accesslog_v2_AccessLog* const*)_upb_array_accessor(msg, UPB_SIZE(128, 224), len); }
+UPB_INLINE const struct envoy_config_filter_accesslog_v2_AccessLog* const* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_access_log(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t *len) { return (const struct envoy_config_filter_accesslog_v2_AccessLog* const*)_upb_array_accessor(msg, UPB_SIZE(132, 232), len); }
 UPB_INLINE const struct google_protobuf_BoolValue* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_use_remote_address(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(84, 136)); }
 UPB_INLINE const struct google_protobuf_BoolValue* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_generate_request_id(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(88, 144)); }
 UPB_INLINE int32_t envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_forward_client_cert_details(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
@@ -164,19 +169,20 @@ UPB_INLINE uint32_t envoy_config_filter_network_http_connection_manager_v2_HttpC
 UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_represent_ipv4_remote_address_as_ipv4_mapped_ipv6(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(29, 29)); }
 UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_skip_xff_append(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(30, 30)); }
 UPB_INLINE upb_strview envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_via(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 72)); }
-UPB_INLINE const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig* const* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_upgrade_configs(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t *len) { return (const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig* const*)_upb_array_accessor(msg, UPB_SIZE(132, 232), len); }
+UPB_INLINE const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig* const* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_upgrade_configs(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t *len) { return (const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig* const*)_upb_array_accessor(msg, UPB_SIZE(136, 240), len); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_stream_idle_timeout(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(96, 160)); }
 UPB_INLINE const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_internal_address_config(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig*, UPB_SIZE(100, 168)); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_delayed_close_timeout(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(104, 176)); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_request_timeout(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(108, 184)); }
 UPB_INLINE const struct google_protobuf_UInt32Value* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_max_request_headers_kb(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(112, 192)); }
 UPB_INLINE const struct google_protobuf_BoolValue* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_normalize_path(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_BoolValue*, UPB_SIZE(116, 200)); }
-UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_has_scoped_routes(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(140, 248), 31); }
-UPB_INLINE const envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_scoped_routes(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_READ_ONEOF(msg, const envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes*, UPB_SIZE(136, 240), UPB_SIZE(140, 248), 31, NULL); }
+UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_has_scoped_routes(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(144, 256), 31); }
+UPB_INLINE const envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_scoped_routes(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_READ_ONEOF(msg, const envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes*, UPB_SIZE(140, 248), UPB_SIZE(144, 256), 31, NULL); }
 UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_preserve_external_request_id(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(31, 31)); }
 UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_merge_slashes(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(32, 32)); }
 UPB_INLINE int32_t envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_server_header_transformation(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); }
 UPB_INLINE const struct envoy_api_v2_core_HttpProtocolOptions* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_common_http_protocol_options(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_HttpProtocolOptions*, UPB_SIZE(120, 208)); }
+UPB_INLINE const envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_request_id_extension(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg) { return UPB_FIELD_AT(msg, const envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension*, UPB_SIZE(124, 216)); }
 
 UPB_INLINE void envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_set_codec_type(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, int32_t value) {
   UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)) = value;
@@ -185,7 +191,7 @@ UPB_INLINE void envoy_config_filter_network_http_connection_manager_v2_HttpConne
   UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 40)) = value;
 }
 UPB_INLINE void envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_set_rds(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, envoy_config_filter_network_http_connection_manager_v2_Rds* value) {
-  UPB_WRITE_ONEOF(msg, envoy_config_filter_network_http_connection_manager_v2_Rds*, UPB_SIZE(136, 240), value, UPB_SIZE(140, 248), 3);
+  UPB_WRITE_ONEOF(msg, envoy_config_filter_network_http_connection_manager_v2_Rds*, UPB_SIZE(140, 248), value, UPB_SIZE(144, 256), 3);
 }
 UPB_INLINE struct envoy_config_filter_network_http_connection_manager_v2_Rds* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_mutable_rds(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, upb_arena *arena) {
   struct envoy_config_filter_network_http_connection_manager_v2_Rds* sub = (struct envoy_config_filter_network_http_connection_manager_v2_Rds*)envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_rds(msg);
@@ -197,7 +203,7 @@ UPB_INLINE struct envoy_config_filter_network_http_connection_manager_v2_Rds* en
   return sub;
 }
 UPB_INLINE void envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_set_route_config(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, struct envoy_api_v2_RouteConfiguration* value) {
-  UPB_WRITE_ONEOF(msg, struct envoy_api_v2_RouteConfiguration*, UPB_SIZE(136, 240), value, UPB_SIZE(140, 248), 4);
+  UPB_WRITE_ONEOF(msg, struct envoy_api_v2_RouteConfiguration*, UPB_SIZE(140, 248), value, UPB_SIZE(144, 256), 4);
 }
 UPB_INLINE struct envoy_api_v2_RouteConfiguration* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_mutable_route_config(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, upb_arena *arena) {
   struct envoy_api_v2_RouteConfiguration* sub = (struct envoy_api_v2_RouteConfiguration*)envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_config(msg);
@@ -209,15 +215,15 @@ UPB_INLINE struct envoy_api_v2_RouteConfiguration* envoy_config_filter_network_h
   return sub;
 }
 UPB_INLINE envoy_config_filter_network_http_connection_manager_v2_HttpFilter** envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_mutable_http_filters(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t *len) {
-  return (envoy_config_filter_network_http_connection_manager_v2_HttpFilter**)_upb_array_mutable_accessor(msg, UPB_SIZE(124, 216), len);
+  return (envoy_config_filter_network_http_connection_manager_v2_HttpFilter**)_upb_array_mutable_accessor(msg, UPB_SIZE(128, 224), len);
 }
 UPB_INLINE envoy_config_filter_network_http_connection_manager_v2_HttpFilter** envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_resize_http_filters(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t len, upb_arena *arena) {
-  return (envoy_config_filter_network_http_connection_manager_v2_HttpFilter**)_upb_array_resize_accessor(msg, UPB_SIZE(124, 216), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (envoy_config_filter_network_http_connection_manager_v2_HttpFilter**)_upb_array_resize_accessor(msg, UPB_SIZE(128, 224), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_config_filter_network_http_connection_manager_v2_HttpFilter* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_add_http_filters(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, upb_arena *arena) {
   struct envoy_config_filter_network_http_connection_manager_v2_HttpFilter* sub = (struct envoy_config_filter_network_http_connection_manager_v2_HttpFilter*)upb_msg_new(&envoy_config_filter_network_http_connection_manager_v2_HttpFilter_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(124, 216), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(128, 224), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -297,15 +303,15 @@ UPB_INLINE struct google_protobuf_Duration* envoy_config_filter_network_http_con
   return sub;
 }
 UPB_INLINE struct envoy_config_filter_accesslog_v2_AccessLog** envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_mutable_access_log(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t *len) {
-  return (struct envoy_config_filter_accesslog_v2_AccessLog**)_upb_array_mutable_accessor(msg, UPB_SIZE(128, 224), len);
+  return (struct envoy_config_filter_accesslog_v2_AccessLog**)_upb_array_mutable_accessor(msg, UPB_SIZE(132, 232), len);
 }
 UPB_INLINE struct envoy_config_filter_accesslog_v2_AccessLog** envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_resize_access_log(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t len, upb_arena *arena) {
-  return (struct envoy_config_filter_accesslog_v2_AccessLog**)_upb_array_resize_accessor(msg, UPB_SIZE(128, 224), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (struct envoy_config_filter_accesslog_v2_AccessLog**)_upb_array_resize_accessor(msg, UPB_SIZE(132, 232), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_config_filter_accesslog_v2_AccessLog* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_add_access_log(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, upb_arena *arena) {
   struct envoy_config_filter_accesslog_v2_AccessLog* sub = (struct envoy_config_filter_accesslog_v2_AccessLog*)upb_msg_new(&envoy_config_filter_accesslog_v2_AccessLog_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(128, 224), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(132, 232), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -364,15 +370,15 @@ UPB_INLINE void envoy_config_filter_network_http_connection_manager_v2_HttpConne
   UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 72)) = value;
 }
 UPB_INLINE envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig** envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_mutable_upgrade_configs(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t *len) {
-  return (envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(132, 232), len);
+  return (envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(136, 240), len);
 }
 UPB_INLINE envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig** envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_resize_upgrade_configs(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, size_t len, upb_arena *arena) {
-  return (envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig**)_upb_array_resize_accessor(msg, UPB_SIZE(132, 232), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig**)_upb_array_resize_accessor(msg, UPB_SIZE(136, 240), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_add_upgrade_configs(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, upb_arena *arena) {
   struct envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig* sub = (struct envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig*)upb_msg_new(&envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(132, 232), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(136, 240), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -449,7 +455,7 @@ UPB_INLINE struct google_protobuf_BoolValue* envoy_config_filter_network_http_co
   return sub;
 }
 UPB_INLINE void envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_set_scoped_routes(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes* value) {
-  UPB_WRITE_ONEOF(msg, envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes*, UPB_SIZE(136, 240), value, UPB_SIZE(140, 248), 31);
+  UPB_WRITE_ONEOF(msg, envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes*, UPB_SIZE(140, 248), value, UPB_SIZE(144, 256), 31);
 }
 UPB_INLINE struct envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_mutable_scoped_routes(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, upb_arena *arena) {
   struct envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes* sub = (struct envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes*)envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_scoped_routes(msg);
@@ -481,6 +487,18 @@ UPB_INLINE struct envoy_api_v2_core_HttpProtocolOptions* envoy_config_filter_net
   }
   return sub;
 }
+UPB_INLINE void envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_set_request_id_extension(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension* value) {
+  UPB_FIELD_AT(msg, envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension*, UPB_SIZE(124, 216)) = value;
+}
+UPB_INLINE struct envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_mutable_request_id_extension(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager *msg, upb_arena *arena) {
+  struct envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension* sub = (struct envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension*)envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_request_id_extension(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension*)upb_msg_new(&envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_set_request_id_extension(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager.Tracing */
 
@@ -497,26 +515,27 @@ UPB_INLINE char *envoy_config_filter_network_http_connection_manager_v2_HttpConn
 }
 
 UPB_INLINE int32_t envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_operation_name(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)); }
-UPB_INLINE upb_strview const* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_request_headers_for_tags(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 48), len); }
+UPB_INLINE upb_strview const* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_request_headers_for_tags(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(32, 56), len); }
 UPB_INLINE const struct envoy_type_Percent* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_client_sampling(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg) { return UPB_FIELD_AT(msg, const struct envoy_type_Percent*, UPB_SIZE(12, 16)); }
 UPB_INLINE const struct envoy_type_Percent* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_random_sampling(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg) { return UPB_FIELD_AT(msg, const struct envoy_type_Percent*, UPB_SIZE(16, 24)); }
 UPB_INLINE const struct envoy_type_Percent* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_overall_sampling(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg) { return UPB_FIELD_AT(msg, const struct envoy_type_Percent*, UPB_SIZE(20, 32)); }
 UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_verbose(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(8, 8)); }
 UPB_INLINE const struct google_protobuf_UInt32Value* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_max_path_tag_length(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_UInt32Value*, UPB_SIZE(24, 40)); }
-UPB_INLINE const struct envoy_type_tracing_v2_CustomTag* const* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_custom_tags(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, size_t *len) { return (const struct envoy_type_tracing_v2_CustomTag* const*)_upb_array_accessor(msg, UPB_SIZE(32, 56), len); }
+UPB_INLINE const struct envoy_type_tracing_v2_CustomTag* const* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_custom_tags(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, size_t *len) { return (const struct envoy_type_tracing_v2_CustomTag* const*)_upb_array_accessor(msg, UPB_SIZE(36, 64), len); }
+UPB_INLINE const struct envoy_config_trace_v2_Tracing_Http* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_provider(const envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg) { return UPB_FIELD_AT(msg, const struct envoy_config_trace_v2_Tracing_Http*, UPB_SIZE(28, 48)); }
 
 UPB_INLINE void envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_set_operation_name(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, int32_t value) {
   UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)) = value;
 }
 UPB_INLINE upb_strview* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_mutable_request_headers_for_tags(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 48), len);
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 56), len);
 }
 UPB_INLINE upb_strview* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_resize_request_headers_for_tags(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(28, 48), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(32, 56), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
 }
 UPB_INLINE bool envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_add_request_headers_for_tags(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, upb_strview val, upb_arena *arena) {
   return _upb_array_append_accessor(
-      msg, UPB_SIZE(28, 48), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+      msg, UPB_SIZE(32, 56), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
 }
 UPB_INLINE void envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_set_client_sampling(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, struct envoy_type_Percent* value) {
   UPB_FIELD_AT(msg, struct envoy_type_Percent*, UPB_SIZE(12, 16)) = value;
@@ -570,18 +589,30 @@ UPB_INLINE struct google_protobuf_UInt32Value* envoy_config_filter_network_http_
   return sub;
 }
 UPB_INLINE struct envoy_type_tracing_v2_CustomTag** envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_mutable_custom_tags(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, size_t *len) {
-  return (struct envoy_type_tracing_v2_CustomTag**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 56), len);
+  return (struct envoy_type_tracing_v2_CustomTag**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 64), len);
 }
 UPB_INLINE struct envoy_type_tracing_v2_CustomTag** envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_resize_custom_tags(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, size_t len, upb_arena *arena) {
-  return (struct envoy_type_tracing_v2_CustomTag**)_upb_array_resize_accessor(msg, UPB_SIZE(32, 56), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
+  return (struct envoy_type_tracing_v2_CustomTag**)_upb_array_resize_accessor(msg, UPB_SIZE(36, 64), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
 }
 UPB_INLINE struct envoy_type_tracing_v2_CustomTag* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_add_custom_tags(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, upb_arena *arena) {
   struct envoy_type_tracing_v2_CustomTag* sub = (struct envoy_type_tracing_v2_CustomTag*)upb_msg_new(&envoy_type_tracing_v2_CustomTag_msginit, arena);
   bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(32, 56), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
+      msg, UPB_SIZE(36, 64), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
+UPB_INLINE void envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_set_provider(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, struct envoy_config_trace_v2_Tracing_Http* value) {
+  UPB_FIELD_AT(msg, struct envoy_config_trace_v2_Tracing_Http*, UPB_SIZE(28, 48)) = value;
+}
+UPB_INLINE struct envoy_config_trace_v2_Tracing_Http* envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_mutable_provider(envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing *msg, upb_arena *arena) {
+  struct envoy_config_trace_v2_Tracing_Http* sub = (struct envoy_config_trace_v2_Tracing_Http*)envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_provider(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_config_trace_v2_Tracing_Http*)upb_msg_new(&envoy_config_trace_v2_Tracing_Http_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_set_provider(msg, sub);
+  }
+  return sub;
+}
 
 /* envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager.InternalAddressConfig */
 
@@ -1063,6 +1094,35 @@ UPB_INLINE struct google_protobuf_Any* envoy_config_filter_network_http_connecti
   return sub;
 }
 
+/* envoy.config.filter.network.http_connection_manager.v2.RequestIDExtension */
+
+UPB_INLINE envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension *envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_new(upb_arena *arena) {
+  return (envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension *)upb_msg_new(&envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_msginit, arena);
+}
+UPB_INLINE envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension *envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension *ret = envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_serialize(const envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_msginit, arena, len);
+}
+
+UPB_INLINE const struct google_protobuf_Any* envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_typed_config(const envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Any*, UPB_SIZE(0, 0)); }
+
+UPB_INLINE void envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_set_typed_config(envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension *msg, struct google_protobuf_Any* value) {
+  UPB_FIELD_AT(msg, struct google_protobuf_Any*, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE struct google_protobuf_Any* envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_mutable_typed_config(envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension *msg, upb_arena *arena) {
+  struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_typed_config(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Any*)upb_msg_new(&google_protobuf_Any_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension_set_typed_config(msg, sub);
+  }
+  return sub;
+}
+
 #ifdef __cplusplus
 }  /* extern "C" */
 #endif
index 36f332f..ce2d53e 100644 (file)
@@ -11,6 +11,7 @@
 #include "envoy/config/listener/v2/api_listener.upb.h"
 #include "google/protobuf/any.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 
 #include "upb/port_def.inc"
 
diff --git a/src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c b/src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c
new file mode 100644 (file)
index 0000000..2b5153a
--- /dev/null
@@ -0,0 +1,51 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/config/trace/v2/http_tracer.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg.h"
+#include "envoy/config/trace/v2/http_tracer.upb.h"
+#include "google/protobuf/any.upb.h"
+#include "google/protobuf/struct.upb.h"
+#include "udpa/annotations/status.upb.h"
+#include "validate/validate.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout *const envoy_config_trace_v2_Tracing_submsgs[1] = {
+  &envoy_config_trace_v2_Tracing_Http_msginit,
+};
+
+static const upb_msglayout_field envoy_config_trace_v2_Tracing__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 1},
+};
+
+const upb_msglayout envoy_config_trace_v2_Tracing_msginit = {
+  &envoy_config_trace_v2_Tracing_submsgs[0],
+  &envoy_config_trace_v2_Tracing__fields[0],
+  UPB_SIZE(4, 8), 1, false,
+};
+
+static const upb_msglayout *const envoy_config_trace_v2_Tracing_Http_submsgs[2] = {
+  &google_protobuf_Any_msginit,
+  &google_protobuf_Struct_msginit,
+};
+
+static const upb_msglayout_field envoy_config_trace_v2_Tracing_Http__fields[3] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 9, 1},
+  {2, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 1, 11, 1},
+  {3, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1},
+};
+
+const upb_msglayout envoy_config_trace_v2_Tracing_Http_msginit = {
+  &envoy_config_trace_v2_Tracing_Http_submsgs[0],
+  &envoy_config_trace_v2_Tracing_Http__fields[0],
+  UPB_SIZE(16, 32), 3, false,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h b/src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h
new file mode 100644 (file)
index 0000000..093fc0a
--- /dev/null
@@ -0,0 +1,125 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     envoy/config/trace/v2/http_tracer.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef ENVOY_CONFIG_TRACE_V2_HTTP_TRACER_PROTO_UPB_H_
+#define ENVOY_CONFIG_TRACE_V2_HTTP_TRACER_PROTO_UPB_H_
+
+#include "upb/generated_util.h"
+#include "upb/msg.h"
+#include "upb/decode.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct envoy_config_trace_v2_Tracing;
+struct envoy_config_trace_v2_Tracing_Http;
+typedef struct envoy_config_trace_v2_Tracing envoy_config_trace_v2_Tracing;
+typedef struct envoy_config_trace_v2_Tracing_Http envoy_config_trace_v2_Tracing_Http;
+extern const upb_msglayout envoy_config_trace_v2_Tracing_msginit;
+extern const upb_msglayout envoy_config_trace_v2_Tracing_Http_msginit;
+struct google_protobuf_Any;
+struct google_protobuf_Struct;
+extern const upb_msglayout google_protobuf_Any_msginit;
+extern const upb_msglayout google_protobuf_Struct_msginit;
+
+
+/* envoy.config.trace.v2.Tracing */
+
+UPB_INLINE envoy_config_trace_v2_Tracing *envoy_config_trace_v2_Tracing_new(upb_arena *arena) {
+  return (envoy_config_trace_v2_Tracing *)upb_msg_new(&envoy_config_trace_v2_Tracing_msginit, arena);
+}
+UPB_INLINE envoy_config_trace_v2_Tracing *envoy_config_trace_v2_Tracing_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_config_trace_v2_Tracing *ret = envoy_config_trace_v2_Tracing_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_config_trace_v2_Tracing_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_config_trace_v2_Tracing_serialize(const envoy_config_trace_v2_Tracing *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_config_trace_v2_Tracing_msginit, arena, len);
+}
+
+UPB_INLINE const envoy_config_trace_v2_Tracing_Http* envoy_config_trace_v2_Tracing_http(const envoy_config_trace_v2_Tracing *msg) { return UPB_FIELD_AT(msg, const envoy_config_trace_v2_Tracing_Http*, UPB_SIZE(0, 0)); }
+
+UPB_INLINE void envoy_config_trace_v2_Tracing_set_http(envoy_config_trace_v2_Tracing *msg, envoy_config_trace_v2_Tracing_Http* value) {
+  UPB_FIELD_AT(msg, envoy_config_trace_v2_Tracing_Http*, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE struct envoy_config_trace_v2_Tracing_Http* envoy_config_trace_v2_Tracing_mutable_http(envoy_config_trace_v2_Tracing *msg, upb_arena *arena) {
+  struct envoy_config_trace_v2_Tracing_Http* sub = (struct envoy_config_trace_v2_Tracing_Http*)envoy_config_trace_v2_Tracing_http(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_config_trace_v2_Tracing_Http*)upb_msg_new(&envoy_config_trace_v2_Tracing_Http_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_trace_v2_Tracing_set_http(msg, sub);
+  }
+  return sub;
+}
+
+/* envoy.config.trace.v2.Tracing.Http */
+
+UPB_INLINE envoy_config_trace_v2_Tracing_Http *envoy_config_trace_v2_Tracing_Http_new(upb_arena *arena) {
+  return (envoy_config_trace_v2_Tracing_Http *)upb_msg_new(&envoy_config_trace_v2_Tracing_Http_msginit, arena);
+}
+UPB_INLINE envoy_config_trace_v2_Tracing_Http *envoy_config_trace_v2_Tracing_Http_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_config_trace_v2_Tracing_Http *ret = envoy_config_trace_v2_Tracing_Http_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_config_trace_v2_Tracing_Http_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_config_trace_v2_Tracing_Http_serialize(const envoy_config_trace_v2_Tracing_Http *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_config_trace_v2_Tracing_Http_msginit, arena, len);
+}
+
+typedef enum {
+  envoy_config_trace_v2_Tracing_Http_config_type_config = 2,
+  envoy_config_trace_v2_Tracing_Http_config_type_typed_config = 3,
+  envoy_config_trace_v2_Tracing_Http_config_type_NOT_SET = 0
+} envoy_config_trace_v2_Tracing_Http_config_type_oneofcases;
+UPB_INLINE envoy_config_trace_v2_Tracing_Http_config_type_oneofcases envoy_config_trace_v2_Tracing_Http_config_type_case(const envoy_config_trace_v2_Tracing_Http* msg) { return (envoy_config_trace_v2_Tracing_Http_config_type_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(12, 24)); }
+
+UPB_INLINE upb_strview envoy_config_trace_v2_Tracing_Http_name(const envoy_config_trace_v2_Tracing_Http *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
+UPB_INLINE bool envoy_config_trace_v2_Tracing_Http_has_config(const envoy_config_trace_v2_Tracing_Http *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 2); }
+UPB_INLINE const struct google_protobuf_Struct* envoy_config_trace_v2_Tracing_Http_config(const envoy_config_trace_v2_Tracing_Http *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_Struct*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 2, NULL); }
+UPB_INLINE bool envoy_config_trace_v2_Tracing_Http_has_typed_config(const envoy_config_trace_v2_Tracing_Http *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(12, 24), 3); }
+UPB_INLINE const struct google_protobuf_Any* envoy_config_trace_v2_Tracing_Http_typed_config(const envoy_config_trace_v2_Tracing_Http *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_Any*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 3, NULL); }
+
+UPB_INLINE void envoy_config_trace_v2_Tracing_Http_set_name(envoy_config_trace_v2_Tracing_Http *msg, upb_strview value) {
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
+}
+UPB_INLINE void envoy_config_trace_v2_Tracing_Http_set_config(envoy_config_trace_v2_Tracing_Http *msg, struct google_protobuf_Struct* value) {
+  UPB_WRITE_ONEOF(msg, struct google_protobuf_Struct*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 2);
+}
+UPB_INLINE struct google_protobuf_Struct* envoy_config_trace_v2_Tracing_Http_mutable_config(envoy_config_trace_v2_Tracing_Http *msg, upb_arena *arena) {
+  struct google_protobuf_Struct* sub = (struct google_protobuf_Struct*)envoy_config_trace_v2_Tracing_Http_config(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Struct*)upb_msg_new(&google_protobuf_Struct_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_trace_v2_Tracing_Http_set_config(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_config_trace_v2_Tracing_Http_set_typed_config(envoy_config_trace_v2_Tracing_Http *msg, struct google_protobuf_Any* value) {
+  UPB_WRITE_ONEOF(msg, struct google_protobuf_Any*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 3);
+}
+UPB_INLINE struct google_protobuf_Any* envoy_config_trace_v2_Tracing_Http_mutable_typed_config(envoy_config_trace_v2_Tracing_Http *msg, upb_arena *arena) {
+  struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_config_trace_v2_Tracing_Http_typed_config(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Any*)upb_msg_new(&google_protobuf_Any_msginit, arena);
+    if (!sub) return NULL;
+    envoy_config_trace_v2_Tracing_Http_set_typed_config(msg, sub);
+  }
+  return sub;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* ENVOY_CONFIG_TRACE_V2_HTTP_TRACER_PROTO_UPB_H_ */
index 5611346..6c6f98f 100644 (file)
@@ -10,6 +10,7 @@
 #include "upb/msg.h"
 #include "envoy/service/discovery/v2/ads.upb.h"
 #include "envoy/api/v2/discovery.upb.h"
+#include "udpa/annotations/status.upb.h"
 
 #include "upb/port_def.inc"
 
index a6e4bd2..98bd884 100644 (file)
@@ -12,6 +12,7 @@
 #include "envoy/api/v2/core/base.upb.h"
 #include "envoy/api/v2/endpoint/load_report.upb.h"
 #include "google/protobuf/duration.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
@@ -36,16 +37,17 @@ static const upb_msglayout *const envoy_service_load_stats_v2_LoadStatsResponse_
   &google_protobuf_Duration_msginit,
 };
 
-static const upb_msglayout_field envoy_service_load_stats_v2_LoadStatsResponse__fields[3] = {
+static const upb_msglayout_field envoy_service_load_stats_v2_LoadStatsResponse__fields[4] = {
   {1, UPB_SIZE(8, 16), 0, 0, 9, 3},
   {2, UPB_SIZE(4, 8), 0, 0, 11, 1},
   {3, UPB_SIZE(0, 0), 0, 0, 8, 1},
+  {4, UPB_SIZE(1, 1), 0, 0, 8, 1},
 };
 
 const upb_msglayout envoy_service_load_stats_v2_LoadStatsResponse_msginit = {
   &envoy_service_load_stats_v2_LoadStatsResponse_submsgs[0],
   &envoy_service_load_stats_v2_LoadStatsResponse__fields[0],
-  UPB_SIZE(12, 24), 3, false,
+  UPB_SIZE(12, 24), 4, false,
 };
 
 #include "upb/port_undef.inc"
index 457deaf..7e364eb 100644 (file)
@@ -94,6 +94,7 @@ UPB_INLINE char *envoy_service_load_stats_v2_LoadStatsResponse_serialize(const e
 UPB_INLINE upb_strview const* envoy_service_load_stats_v2_LoadStatsResponse_clusters(const envoy_service_load_stats_v2_LoadStatsResponse *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); }
 UPB_INLINE const struct google_protobuf_Duration* envoy_service_load_stats_v2_LoadStatsResponse_load_reporting_interval(const envoy_service_load_stats_v2_LoadStatsResponse *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(4, 8)); }
 UPB_INLINE bool envoy_service_load_stats_v2_LoadStatsResponse_report_endpoint_granularity(const envoy_service_load_stats_v2_LoadStatsResponse *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)); }
+UPB_INLINE bool envoy_service_load_stats_v2_LoadStatsResponse_send_all_clusters(const envoy_service_load_stats_v2_LoadStatsResponse *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); }
 
 UPB_INLINE upb_strview* envoy_service_load_stats_v2_LoadStatsResponse_mutable_clusters(envoy_service_load_stats_v2_LoadStatsResponse *msg, size_t *len) {
   return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len);
@@ -120,6 +121,9 @@ UPB_INLINE struct google_protobuf_Duration* envoy_service_load_stats_v2_LoadStat
 UPB_INLINE void envoy_service_load_stats_v2_LoadStatsResponse_set_report_endpoint_granularity(envoy_service_load_stats_v2_LoadStatsResponse *msg, bool value) {
   UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)) = value;
 }
+UPB_INLINE void envoy_service_load_stats_v2_LoadStatsResponse_set_send_all_clusters(envoy_service_load_stats_v2_LoadStatsResponse *msg, bool value) {
+  UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value;
+}
 
 #ifdef __cplusplus
 }  /* extern "C" */
index 3217029..a5175f6 100644 (file)
@@ -9,6 +9,7 @@
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/type/http.upb.h"
+#include "udpa/annotations/status.upb.h"
 
 #include "upb/port_def.inc"
 
index 679e9be..dd8fe6c 100644 (file)
@@ -10,6 +10,7 @@
 #include "upb/msg.h"
 #include "envoy/type/matcher/regex.upb.h"
 #include "google/protobuf/wrappers.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
@@ -43,5 +44,20 @@ const upb_msglayout envoy_type_matcher_RegexMatcher_GoogleRE2_msginit = {
   UPB_SIZE(4, 8), 1, false,
 };
 
+static const upb_msglayout *const envoy_type_matcher_RegexMatchAndSubstitute_submsgs[1] = {
+  &envoy_type_matcher_RegexMatcher_msginit,
+};
+
+static const upb_msglayout_field envoy_type_matcher_RegexMatchAndSubstitute__fields[2] = {
+  {1, UPB_SIZE(8, 16), 0, 0, 11, 1},
+  {2, UPB_SIZE(0, 0), 0, 0, 9, 1},
+};
+
+const upb_msglayout envoy_type_matcher_RegexMatchAndSubstitute_msginit = {
+  &envoy_type_matcher_RegexMatchAndSubstitute_submsgs[0],
+  &envoy_type_matcher_RegexMatchAndSubstitute__fields[0],
+  UPB_SIZE(16, 32), 2, false,
+};
+
 #include "upb/port_undef.inc"
 
index 1a39673..d6c4571 100644 (file)
@@ -22,10 +22,13 @@ extern "C" {
 
 struct envoy_type_matcher_RegexMatcher;
 struct envoy_type_matcher_RegexMatcher_GoogleRE2;
+struct envoy_type_matcher_RegexMatchAndSubstitute;
 typedef struct envoy_type_matcher_RegexMatcher envoy_type_matcher_RegexMatcher;
 typedef struct envoy_type_matcher_RegexMatcher_GoogleRE2 envoy_type_matcher_RegexMatcher_GoogleRE2;
+typedef struct envoy_type_matcher_RegexMatchAndSubstitute envoy_type_matcher_RegexMatchAndSubstitute;
 extern const upb_msglayout envoy_type_matcher_RegexMatcher_msginit;
 extern const upb_msglayout envoy_type_matcher_RegexMatcher_GoogleRE2_msginit;
+extern const upb_msglayout envoy_type_matcher_RegexMatchAndSubstitute_msginit;
 struct google_protobuf_UInt32Value;
 extern const upb_msglayout google_protobuf_UInt32Value_msginit;
 
@@ -99,6 +102,39 @@ UPB_INLINE struct google_protobuf_UInt32Value* envoy_type_matcher_RegexMatcher_G
   return sub;
 }
 
+/* envoy.type.matcher.RegexMatchAndSubstitute */
+
+UPB_INLINE envoy_type_matcher_RegexMatchAndSubstitute *envoy_type_matcher_RegexMatchAndSubstitute_new(upb_arena *arena) {
+  return (envoy_type_matcher_RegexMatchAndSubstitute *)upb_msg_new(&envoy_type_matcher_RegexMatchAndSubstitute_msginit, arena);
+}
+UPB_INLINE envoy_type_matcher_RegexMatchAndSubstitute *envoy_type_matcher_RegexMatchAndSubstitute_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  envoy_type_matcher_RegexMatchAndSubstitute *ret = envoy_type_matcher_RegexMatchAndSubstitute_new(arena);
+  return (ret && upb_decode(buf, size, ret, &envoy_type_matcher_RegexMatchAndSubstitute_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *envoy_type_matcher_RegexMatchAndSubstitute_serialize(const envoy_type_matcher_RegexMatchAndSubstitute *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &envoy_type_matcher_RegexMatchAndSubstitute_msginit, arena, len);
+}
+
+UPB_INLINE const envoy_type_matcher_RegexMatcher* envoy_type_matcher_RegexMatchAndSubstitute_pattern(const envoy_type_matcher_RegexMatchAndSubstitute *msg) { return UPB_FIELD_AT(msg, const envoy_type_matcher_RegexMatcher*, UPB_SIZE(8, 16)); }
+UPB_INLINE upb_strview envoy_type_matcher_RegexMatchAndSubstitute_substitution(const envoy_type_matcher_RegexMatchAndSubstitute *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)); }
+
+UPB_INLINE void envoy_type_matcher_RegexMatchAndSubstitute_set_pattern(envoy_type_matcher_RegexMatchAndSubstitute *msg, envoy_type_matcher_RegexMatcher* value) {
+  UPB_FIELD_AT(msg, envoy_type_matcher_RegexMatcher*, UPB_SIZE(8, 16)) = value;
+}
+UPB_INLINE struct envoy_type_matcher_RegexMatcher* envoy_type_matcher_RegexMatchAndSubstitute_mutable_pattern(envoy_type_matcher_RegexMatchAndSubstitute *msg, upb_arena *arena) {
+  struct envoy_type_matcher_RegexMatcher* sub = (struct envoy_type_matcher_RegexMatcher*)envoy_type_matcher_RegexMatchAndSubstitute_pattern(msg);
+  if (sub == NULL) {
+    sub = (struct envoy_type_matcher_RegexMatcher*)upb_msg_new(&envoy_type_matcher_RegexMatcher_msginit, arena);
+    if (!sub) return NULL;
+    envoy_type_matcher_RegexMatchAndSubstitute_set_pattern(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void envoy_type_matcher_RegexMatchAndSubstitute_set_substitution(envoy_type_matcher_RegexMatchAndSubstitute *msg, upb_strview value) {
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(0, 0)) = value;
+}
+
 #ifdef __cplusplus
 }  /* extern "C" */
 #endif
index 208a022..beab523 100644 (file)
@@ -11,6 +11,7 @@
 #include "envoy/type/matcher/string.upb.h"
 #include "envoy/type/matcher/regex.upb.h"
 #include "envoy/annotations/deprecation.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index e2f69c7..3f98ea0 100644 (file)
@@ -10,6 +10,7 @@
 #include "upb/msg.h"
 #include "envoy/type/metadata/v2/metadata.upb.h"
 #include "udpa/annotations/migrate.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index 0754073..06d08e1 100644 (file)
@@ -9,6 +9,7 @@
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/type/percent.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index 67de8d0..5a002f8 100644 (file)
@@ -9,6 +9,7 @@
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/type/range.upb.h"
+#include "udpa/annotations/status.upb.h"
 
 #include "upb/port_def.inc"
 
index a4dd26e..1192693 100644 (file)
@@ -9,6 +9,7 @@
 #include <stddef.h>
 #include "upb/msg.h"
 #include "envoy/type/semantic_version.upb.h"
+#include "udpa/annotations/status.upb.h"
 
 #include "upb/port_def.inc"
 
index 5a05897..064e7e2 100644 (file)
@@ -10,6 +10,7 @@
 #include "upb/msg.h"
 #include "envoy/type/tracing/v2/custom_tag.upb.h"
 #include "envoy/type/metadata/v2/metadata.upb.h"
+#include "udpa/annotations/status.upb.h"
 #include "validate/validate.upb.h"
 
 #include "upb/port_def.inc"
index 61b9299..64fa929 100644 (file)
@@ -130,23 +130,24 @@ static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1
   &google_protobuf_FieldOptions_msginit,
 };
 
-static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[10] = {
-  {1, UPB_SIZE(32, 32), 5, 0, 9, 1},
-  {2, UPB_SIZE(40, 48), 6, 0, 9, 1},
+static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = {
+  {1, UPB_SIZE(36, 40), 6, 0, 9, 1},
+  {2, UPB_SIZE(44, 56), 7, 0, 9, 1},
   {3, UPB_SIZE(24, 24), 3, 0, 5, 1},
   {4, UPB_SIZE(8, 8), 1, 0, 14, 1},
   {5, UPB_SIZE(16, 16), 2, 0, 14, 1},
-  {6, UPB_SIZE(48, 64), 7, 0, 9, 1},
-  {7, UPB_SIZE(56, 80), 8, 0, 9, 1},
-  {8, UPB_SIZE(72, 112), 10, 0, 11, 1},
+  {6, UPB_SIZE(52, 72), 8, 0, 9, 1},
+  {7, UPB_SIZE(60, 88), 9, 0, 9, 1},
+  {8, UPB_SIZE(76, 120), 11, 0, 11, 1},
   {9, UPB_SIZE(28, 28), 4, 0, 5, 1},
-  {10, UPB_SIZE(64, 96), 9, 0, 9, 1},
+  {10, UPB_SIZE(68, 104), 10, 0, 9, 1},
+  {17, UPB_SIZE(32, 32), 5, 0, 8, 1},
 };
 
 const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = {
   &google_protobuf_FieldDescriptorProto_submsgs[0],
   &google_protobuf_FieldDescriptorProto__fields[0],
-  UPB_SIZE(80, 128), 10, false,
+  UPB_SIZE(80, 128), 11, false,
 };
 
 static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = {
index 6816149..062dd1c 100644 (file)
@@ -598,34 +598,36 @@ UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_pro
   return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len);
 }
 
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 40)); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(44, 56)); }
 UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 3); }
 UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(24, 24)); }
 UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 1); }
 UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
 UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 2); }
 UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 80)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); }
-UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_FieldOptions*, UPB_SIZE(72, 112)); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 72)); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 88)); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 11); }
+UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_FieldOptions*, UPB_SIZE(76, 120)); }
 UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 4); }
 UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(28, 28)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 96)); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 104)); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(32, 32)); }
 
 UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 5);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)) = value;
+  _upb_sethas(msg, 6);
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 40)) = value;
 }
 UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 6);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)) = value;
+  _upb_sethas(msg, 7);
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(44, 56)) = value;
 }
 UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
   _upb_sethas(msg, 3);
@@ -640,16 +642,16 @@ UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_Fi
   UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)) = value;
 }
 UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 7);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)) = value;
+  _upb_sethas(msg, 8);
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 72)) = value;
 }
 UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 8);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 80)) = value;
+  _upb_sethas(msg, 9);
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 88)) = value;
 }
 UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) {
-  _upb_sethas(msg, 10);
-  UPB_FIELD_AT(msg, google_protobuf_FieldOptions*, UPB_SIZE(72, 112)) = value;
+  _upb_sethas(msg, 11);
+  UPB_FIELD_AT(msg, google_protobuf_FieldOptions*, UPB_SIZE(76, 120)) = value;
 }
 UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) {
   struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg);
@@ -665,8 +667,12 @@ UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_prot
   UPB_FIELD_AT(msg, int32_t, UPB_SIZE(28, 28)) = value;
 }
 UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 9);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 96)) = value;
+  _upb_sethas(msg, 10);
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 104)) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) {
+  _upb_sethas(msg, 5);
+  UPB_FIELD_AT(msg, bool, UPB_SIZE(32, 32)) = value;
 }
 
 /* google.protobuf.OneofDescriptorProto */
diff --git a/src/core/ext/upb-generated/udpa/annotations/status.upb.c b/src/core/ext/upb-generated/udpa/annotations/status.upb.c
new file mode 100644 (file)
index 0000000..05cb76c
--- /dev/null
@@ -0,0 +1,28 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     udpa/annotations/status.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg.h"
+#include "udpa/annotations/status.upb.h"
+#include "google/protobuf/descriptor.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout_field udpa_annotations_StatusAnnotation__fields[2] = {
+  {1, UPB_SIZE(8, 8), 0, 0, 8, 1},
+  {2, UPB_SIZE(0, 0), 0, 0, 14, 1},
+};
+
+const upb_msglayout udpa_annotations_StatusAnnotation_msginit = {
+  NULL,
+  &udpa_annotations_StatusAnnotation__fields[0],
+  UPB_SIZE(16, 16), 2, false,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/udpa/annotations/status.upb.h b/src/core/ext/upb-generated/udpa/annotations/status.upb.h
new file mode 100644 (file)
index 0000000..e98e882
--- /dev/null
@@ -0,0 +1,65 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     udpa/annotations/status.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef UDPA_ANNOTATIONS_STATUS_PROTO_UPB_H_
+#define UDPA_ANNOTATIONS_STATUS_PROTO_UPB_H_
+
+#include "upb/generated_util.h"
+#include "upb/msg.h"
+#include "upb/decode.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct udpa_annotations_StatusAnnotation;
+typedef struct udpa_annotations_StatusAnnotation udpa_annotations_StatusAnnotation;
+extern const upb_msglayout udpa_annotations_StatusAnnotation_msginit;
+
+typedef enum {
+  udpa_annotations_UNKNOWN = 0,
+  udpa_annotations_FROZEN = 1,
+  udpa_annotations_ACTIVE = 2,
+  udpa_annotations_NEXT_MAJOR_VERSION_CANDIDATE = 3
+} udpa_annotations_PackageVersionStatus;
+
+
+/* udpa.annotations.StatusAnnotation */
+
+UPB_INLINE udpa_annotations_StatusAnnotation *udpa_annotations_StatusAnnotation_new(upb_arena *arena) {
+  return (udpa_annotations_StatusAnnotation *)upb_msg_new(&udpa_annotations_StatusAnnotation_msginit, arena);
+}
+UPB_INLINE udpa_annotations_StatusAnnotation *udpa_annotations_StatusAnnotation_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  udpa_annotations_StatusAnnotation *ret = udpa_annotations_StatusAnnotation_new(arena);
+  return (ret && upb_decode(buf, size, ret, &udpa_annotations_StatusAnnotation_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *udpa_annotations_StatusAnnotation_serialize(const udpa_annotations_StatusAnnotation *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &udpa_annotations_StatusAnnotation_msginit, arena, len);
+}
+
+UPB_INLINE bool udpa_annotations_StatusAnnotation_work_in_progress(const udpa_annotations_StatusAnnotation *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(8, 8)); }
+UPB_INLINE int32_t udpa_annotations_StatusAnnotation_package_version_status(const udpa_annotations_StatusAnnotation *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)); }
+
+UPB_INLINE void udpa_annotations_StatusAnnotation_set_work_in_progress(udpa_annotations_StatusAnnotation *msg, bool value) {
+  UPB_FIELD_AT(msg, bool, UPB_SIZE(8, 8)) = value;
+}
+UPB_INLINE void udpa_annotations_StatusAnnotation_set_package_version_status(udpa_annotations_StatusAnnotation *msg, int32_t value) {
+  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(0, 0)) = value;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* UDPA_ANNOTATIONS_STATUS_PROTO_UPB_H_ */
index 2fd97f5..1d6ab9b 100644 (file)
@@ -273,37 +273,38 @@ const upb_msglayout validate_BoolRules_msginit = {
   UPB_SIZE(2, 2), 1, false,
 };
 
-static const upb_msglayout_field validate_StringRules__fields[24] = {
-  {1, UPB_SIZE(56, 56), 7, 0, 9, 1},
+static const upb_msglayout_field validate_StringRules__fields[25] = {
+  {1, UPB_SIZE(60, 64), 8, 0, 9, 1},
   {2, UPB_SIZE(8, 8), 1, 0, 4, 1},
   {3, UPB_SIZE(16, 16), 2, 0, 4, 1},
   {4, UPB_SIZE(24, 24), 3, 0, 4, 1},
   {5, UPB_SIZE(32, 32), 4, 0, 4, 1},
-  {6, UPB_SIZE(64, 72), 8, 0, 9, 1},
-  {7, UPB_SIZE(72, 88), 9, 0, 9, 1},
-  {8, UPB_SIZE(80, 104), 10, 0, 9, 1},
-  {9, UPB_SIZE(88, 120), 11, 0, 9, 1},
-  {10, UPB_SIZE(104, 152), 0, 0, 9, 3},
-  {11, UPB_SIZE(108, 160), 0, 0, 9, 3},
-  {12, UPB_SIZE(112, 168), UPB_SIZE(-121, -177), 0, 8, 1},
-  {13, UPB_SIZE(112, 168), UPB_SIZE(-121, -177), 0, 8, 1},
-  {14, UPB_SIZE(112, 168), UPB_SIZE(-121, -177), 0, 8, 1},
-  {15, UPB_SIZE(112, 168), UPB_SIZE(-121, -177), 0, 8, 1},
-  {16, UPB_SIZE(112, 168), UPB_SIZE(-121, -177), 0, 8, 1},
-  {17, UPB_SIZE(112, 168), UPB_SIZE(-121, -177), 0, 8, 1},
-  {18, UPB_SIZE(112, 168), UPB_SIZE(-121, -177), 0, 8, 1},
+  {6, UPB_SIZE(68, 80), 9, 0, 9, 1},
+  {7, UPB_SIZE(76, 96), 10, 0, 9, 1},
+  {8, UPB_SIZE(84, 112), 11, 0, 9, 1},
+  {9, UPB_SIZE(92, 128), 12, 0, 9, 1},
+  {10, UPB_SIZE(108, 160), 0, 0, 9, 3},
+  {11, UPB_SIZE(112, 168), 0, 0, 9, 3},
+  {12, UPB_SIZE(120, 176), UPB_SIZE(-129, -185), 0, 8, 1},
+  {13, UPB_SIZE(120, 176), UPB_SIZE(-129, -185), 0, 8, 1},
+  {14, UPB_SIZE(120, 176), UPB_SIZE(-129, -185), 0, 8, 1},
+  {15, UPB_SIZE(120, 176), UPB_SIZE(-129, -185), 0, 8, 1},
+  {16, UPB_SIZE(120, 176), UPB_SIZE(-129, -185), 0, 8, 1},
+  {17, UPB_SIZE(120, 176), UPB_SIZE(-129, -185), 0, 8, 1},
+  {18, UPB_SIZE(120, 176), UPB_SIZE(-129, -185), 0, 8, 1},
   {19, UPB_SIZE(40, 40), 5, 0, 4, 1},
   {20, UPB_SIZE(48, 48), 6, 0, 4, 1},
-  {21, UPB_SIZE(112, 168), UPB_SIZE(-121, -177), 0, 8, 1},
-  {22, UPB_SIZE(112, 168), UPB_SIZE(-121, -177), 0, 8, 1},
-  {23, UPB_SIZE(96, 136), 12, 0, 9, 1},
-  {24, UPB_SIZE(112, 168), UPB_SIZE(-121, -177), 0, 14, 1},
+  {21, UPB_SIZE(120, 176), UPB_SIZE(-129, -185), 0, 8, 1},
+  {22, UPB_SIZE(120, 176), UPB_SIZE(-129, -185), 0, 8, 1},
+  {23, UPB_SIZE(100, 144), 13, 0, 9, 1},
+  {24, UPB_SIZE(120, 176), UPB_SIZE(-129, -185), 0, 14, 1},
+  {25, UPB_SIZE(56, 56), 7, 0, 8, 1},
 };
 
 const upb_msglayout validate_StringRules_msginit = {
   NULL,
   &validate_StringRules__fields[0],
-  UPB_SIZE(128, 192), 24, false,
+  UPB_SIZE(136, 192), 25, false,
 };
 
 static const upb_msglayout_field validate_BytesRules__fields[13] = {
index 1a1ba57..1d381d8 100644 (file)
@@ -1317,10 +1317,10 @@ typedef enum {
   validate_StringRules_well_known_well_known_regex = 24,
   validate_StringRules_well_known_NOT_SET = 0
 } validate_StringRules_well_known_oneofcases;
-UPB_INLINE validate_StringRules_well_known_oneofcases validate_StringRules_well_known_case(const validate_StringRules* msg) { return (validate_StringRules_well_known_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(120, 176)); }
+UPB_INLINE validate_StringRules_well_known_oneofcases validate_StringRules_well_known_case(const validate_StringRules* msg) { return (validate_StringRules_well_known_oneofcases)UPB_FIELD_AT(msg, int32_t, UPB_SIZE(128, 184)); }
 
-UPB_INLINE bool validate_StringRules_has_const(const validate_StringRules *msg) { return _upb_has_field(msg, 7); }
-UPB_INLINE upb_strview validate_StringRules_const(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 56)); }
+UPB_INLINE bool validate_StringRules_has_const(const validate_StringRules *msg) { return _upb_has_field(msg, 8); }
+UPB_INLINE upb_strview validate_StringRules_const(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 64)); }
 UPB_INLINE bool validate_StringRules_has_min_len(const validate_StringRules *msg) { return _upb_has_field(msg, 1); }
 UPB_INLINE uint64_t validate_StringRules_min_len(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)); }
 UPB_INLINE bool validate_StringRules_has_max_len(const validate_StringRules *msg) { return _upb_has_field(msg, 2); }
@@ -1329,46 +1329,48 @@ UPB_INLINE bool validate_StringRules_has_min_bytes(const validate_StringRules *m
 UPB_INLINE uint64_t validate_StringRules_min_bytes(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(24, 24)); }
 UPB_INLINE bool validate_StringRules_has_max_bytes(const validate_StringRules *msg) { return _upb_has_field(msg, 4); }
 UPB_INLINE uint64_t validate_StringRules_max_bytes(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(32, 32)); }
-UPB_INLINE bool validate_StringRules_has_pattern(const validate_StringRules *msg) { return _upb_has_field(msg, 8); }
-UPB_INLINE upb_strview validate_StringRules_pattern(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 72)); }
-UPB_INLINE bool validate_StringRules_has_prefix(const validate_StringRules *msg) { return _upb_has_field(msg, 9); }
-UPB_INLINE upb_strview validate_StringRules_prefix(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(72, 88)); }
-UPB_INLINE bool validate_StringRules_has_suffix(const validate_StringRules *msg) { return _upb_has_field(msg, 10); }
-UPB_INLINE upb_strview validate_StringRules_suffix(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(80, 104)); }
-UPB_INLINE bool validate_StringRules_has_contains(const validate_StringRules *msg) { return _upb_has_field(msg, 11); }
-UPB_INLINE upb_strview validate_StringRules_contains(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(88, 120)); }
-UPB_INLINE upb_strview const* validate_StringRules_in(const validate_StringRules *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(104, 152), len); }
-UPB_INLINE upb_strview const* validate_StringRules_not_in(const validate_StringRules *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(108, 160), len); }
-UPB_INLINE bool validate_StringRules_has_email(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 176), 12); }
-UPB_INLINE bool validate_StringRules_email(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(112, 168), UPB_SIZE(120, 176), 12, false); }
-UPB_INLINE bool validate_StringRules_has_hostname(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 176), 13); }
-UPB_INLINE bool validate_StringRules_hostname(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(112, 168), UPB_SIZE(120, 176), 13, false); }
-UPB_INLINE bool validate_StringRules_has_ip(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 176), 14); }
-UPB_INLINE bool validate_StringRules_ip(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(112, 168), UPB_SIZE(120, 176), 14, false); }
-UPB_INLINE bool validate_StringRules_has_ipv4(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 176), 15); }
-UPB_INLINE bool validate_StringRules_ipv4(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(112, 168), UPB_SIZE(120, 176), 15, false); }
-UPB_INLINE bool validate_StringRules_has_ipv6(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 176), 16); }
-UPB_INLINE bool validate_StringRules_ipv6(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(112, 168), UPB_SIZE(120, 176), 16, false); }
-UPB_INLINE bool validate_StringRules_has_uri(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 176), 17); }
-UPB_INLINE bool validate_StringRules_uri(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(112, 168), UPB_SIZE(120, 176), 17, false); }
-UPB_INLINE bool validate_StringRules_has_uri_ref(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 176), 18); }
-UPB_INLINE bool validate_StringRules_uri_ref(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(112, 168), UPB_SIZE(120, 176), 18, false); }
+UPB_INLINE bool validate_StringRules_has_pattern(const validate_StringRules *msg) { return _upb_has_field(msg, 9); }
+UPB_INLINE upb_strview validate_StringRules_pattern(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 80)); }
+UPB_INLINE bool validate_StringRules_has_prefix(const validate_StringRules *msg) { return _upb_has_field(msg, 10); }
+UPB_INLINE upb_strview validate_StringRules_prefix(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(76, 96)); }
+UPB_INLINE bool validate_StringRules_has_suffix(const validate_StringRules *msg) { return _upb_has_field(msg, 11); }
+UPB_INLINE upb_strview validate_StringRules_suffix(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(84, 112)); }
+UPB_INLINE bool validate_StringRules_has_contains(const validate_StringRules *msg) { return _upb_has_field(msg, 12); }
+UPB_INLINE upb_strview validate_StringRules_contains(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(92, 128)); }
+UPB_INLINE upb_strview const* validate_StringRules_in(const validate_StringRules *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(108, 160), len); }
+UPB_INLINE upb_strview const* validate_StringRules_not_in(const validate_StringRules *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(112, 168), len); }
+UPB_INLINE bool validate_StringRules_has_email(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(128, 184), 12); }
+UPB_INLINE bool validate_StringRules_email(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(120, 176), UPB_SIZE(128, 184), 12, false); }
+UPB_INLINE bool validate_StringRules_has_hostname(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(128, 184), 13); }
+UPB_INLINE bool validate_StringRules_hostname(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(120, 176), UPB_SIZE(128, 184), 13, false); }
+UPB_INLINE bool validate_StringRules_has_ip(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(128, 184), 14); }
+UPB_INLINE bool validate_StringRules_ip(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(120, 176), UPB_SIZE(128, 184), 14, false); }
+UPB_INLINE bool validate_StringRules_has_ipv4(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(128, 184), 15); }
+UPB_INLINE bool validate_StringRules_ipv4(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(120, 176), UPB_SIZE(128, 184), 15, false); }
+UPB_INLINE bool validate_StringRules_has_ipv6(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(128, 184), 16); }
+UPB_INLINE bool validate_StringRules_ipv6(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(120, 176), UPB_SIZE(128, 184), 16, false); }
+UPB_INLINE bool validate_StringRules_has_uri(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(128, 184), 17); }
+UPB_INLINE bool validate_StringRules_uri(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(120, 176), UPB_SIZE(128, 184), 17, false); }
+UPB_INLINE bool validate_StringRules_has_uri_ref(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(128, 184), 18); }
+UPB_INLINE bool validate_StringRules_uri_ref(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(120, 176), UPB_SIZE(128, 184), 18, false); }
 UPB_INLINE bool validate_StringRules_has_len(const validate_StringRules *msg) { return _upb_has_field(msg, 5); }
 UPB_INLINE uint64_t validate_StringRules_len(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(40, 40)); }
 UPB_INLINE bool validate_StringRules_has_len_bytes(const validate_StringRules *msg) { return _upb_has_field(msg, 6); }
 UPB_INLINE uint64_t validate_StringRules_len_bytes(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(48, 48)); }
-UPB_INLINE bool validate_StringRules_has_address(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 176), 21); }
-UPB_INLINE bool validate_StringRules_address(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(112, 168), UPB_SIZE(120, 176), 21, false); }
-UPB_INLINE bool validate_StringRules_has_uuid(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 176), 22); }
-UPB_INLINE bool validate_StringRules_uuid(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(112, 168), UPB_SIZE(120, 176), 22, false); }
-UPB_INLINE bool validate_StringRules_has_not_contains(const validate_StringRules *msg) { return _upb_has_field(msg, 12); }
-UPB_INLINE upb_strview validate_StringRules_not_contains(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(96, 136)); }
-UPB_INLINE bool validate_StringRules_has_well_known_regex(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(120, 176), 24); }
-UPB_INLINE int32_t validate_StringRules_well_known_regex(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, int32_t, UPB_SIZE(112, 168), UPB_SIZE(120, 176), 24, validate_UNKNOWN); }
+UPB_INLINE bool validate_StringRules_has_address(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(128, 184), 21); }
+UPB_INLINE bool validate_StringRules_address(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(120, 176), UPB_SIZE(128, 184), 21, false); }
+UPB_INLINE bool validate_StringRules_has_uuid(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(128, 184), 22); }
+UPB_INLINE bool validate_StringRules_uuid(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(120, 176), UPB_SIZE(128, 184), 22, false); }
+UPB_INLINE bool validate_StringRules_has_not_contains(const validate_StringRules *msg) { return _upb_has_field(msg, 13); }
+UPB_INLINE upb_strview validate_StringRules_not_contains(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(100, 144)); }
+UPB_INLINE bool validate_StringRules_has_well_known_regex(const validate_StringRules *msg) { return _upb_has_oneof_field(msg, UPB_SIZE(128, 184), 24); }
+UPB_INLINE int32_t validate_StringRules_well_known_regex(const validate_StringRules *msg) { return UPB_READ_ONEOF(msg, int32_t, UPB_SIZE(120, 176), UPB_SIZE(128, 184), 24, validate_UNKNOWN); }
+UPB_INLINE bool validate_StringRules_has_strict(const validate_StringRules *msg) { return _upb_has_field(msg, 7); }
+UPB_INLINE bool validate_StringRules_strict(const validate_StringRules *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(56, 56)); }
 
 UPB_INLINE void validate_StringRules_set_const(validate_StringRules *msg, upb_strview value) {
-  _upb_sethas(msg, 7);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 56)) = value;
+  _upb_sethas(msg, 8);
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 64)) = value;
 }
 UPB_INLINE void validate_StringRules_set_min_len(validate_StringRules *msg, uint64_t value) {
   _upb_sethas(msg, 1);
@@ -1387,61 +1389,61 @@ UPB_INLINE void validate_StringRules_set_max_bytes(validate_StringRules *msg, ui
   UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(32, 32)) = value;
 }
 UPB_INLINE void validate_StringRules_set_pattern(validate_StringRules *msg, upb_strview value) {
-  _upb_sethas(msg, 8);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 72)) = value;
+  _upb_sethas(msg, 9);
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 80)) = value;
 }
 UPB_INLINE void validate_StringRules_set_prefix(validate_StringRules *msg, upb_strview value) {
-  _upb_sethas(msg, 9);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(72, 88)) = value;
+  _upb_sethas(msg, 10);
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(76, 96)) = value;
 }
 UPB_INLINE void validate_StringRules_set_suffix(validate_StringRules *msg, upb_strview value) {
-  _upb_sethas(msg, 10);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(80, 104)) = value;
+  _upb_sethas(msg, 11);
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(84, 112)) = value;
 }
 UPB_INLINE void validate_StringRules_set_contains(validate_StringRules *msg, upb_strview value) {
-  _upb_sethas(msg, 11);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(88, 120)) = value;
+  _upb_sethas(msg, 12);
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(92, 128)) = value;
 }
 UPB_INLINE upb_strview* validate_StringRules_mutable_in(validate_StringRules *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(104, 152), len);
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(108, 160), len);
 }
 UPB_INLINE upb_strview* validate_StringRules_resize_in(validate_StringRules *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(104, 152), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(108, 160), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
 }
 UPB_INLINE bool validate_StringRules_add_in(validate_StringRules *msg, upb_strview val, upb_arena *arena) {
   return _upb_array_append_accessor(
-      msg, UPB_SIZE(104, 152), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+      msg, UPB_SIZE(108, 160), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
 }
 UPB_INLINE upb_strview* validate_StringRules_mutable_not_in(validate_StringRules *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(108, 160), len);
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(112, 168), len);
 }
 UPB_INLINE upb_strview* validate_StringRules_resize_not_in(validate_StringRules *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(108, 160), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(112, 168), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
 }
 UPB_INLINE bool validate_StringRules_add_not_in(validate_StringRules *msg, upb_strview val, upb_arena *arena) {
   return _upb_array_append_accessor(
-      msg, UPB_SIZE(108, 160), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
+      msg, UPB_SIZE(112, 168), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
 }
 UPB_INLINE void validate_StringRules_set_email(validate_StringRules *msg, bool value) {
-  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(112, 168), value, UPB_SIZE(120, 176), 12);
+  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(120, 176), value, UPB_SIZE(128, 184), 12);
 }
 UPB_INLINE void validate_StringRules_set_hostname(validate_StringRules *msg, bool value) {
-  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(112, 168), value, UPB_SIZE(120, 176), 13);
+  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(120, 176), value, UPB_SIZE(128, 184), 13);
 }
 UPB_INLINE void validate_StringRules_set_ip(validate_StringRules *msg, bool value) {
-  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(112, 168), value, UPB_SIZE(120, 176), 14);
+  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(120, 176), value, UPB_SIZE(128, 184), 14);
 }
 UPB_INLINE void validate_StringRules_set_ipv4(validate_StringRules *msg, bool value) {
-  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(112, 168), value, UPB_SIZE(120, 176), 15);
+  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(120, 176), value, UPB_SIZE(128, 184), 15);
 }
 UPB_INLINE void validate_StringRules_set_ipv6(validate_StringRules *msg, bool value) {
-  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(112, 168), value, UPB_SIZE(120, 176), 16);
+  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(120, 176), value, UPB_SIZE(128, 184), 16);
 }
 UPB_INLINE void validate_StringRules_set_uri(validate_StringRules *msg, bool value) {
-  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(112, 168), value, UPB_SIZE(120, 176), 17);
+  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(120, 176), value, UPB_SIZE(128, 184), 17);
 }
 UPB_INLINE void validate_StringRules_set_uri_ref(validate_StringRules *msg, bool value) {
-  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(112, 168), value, UPB_SIZE(120, 176), 18);
+  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(120, 176), value, UPB_SIZE(128, 184), 18);
 }
 UPB_INLINE void validate_StringRules_set_len(validate_StringRules *msg, uint64_t value) {
   _upb_sethas(msg, 5);
@@ -1452,17 +1454,21 @@ UPB_INLINE void validate_StringRules_set_len_bytes(validate_StringRules *msg, ui
   UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(48, 48)) = value;
 }
 UPB_INLINE void validate_StringRules_set_address(validate_StringRules *msg, bool value) {
-  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(112, 168), value, UPB_SIZE(120, 176), 21);
+  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(120, 176), value, UPB_SIZE(128, 184), 21);
 }
 UPB_INLINE void validate_StringRules_set_uuid(validate_StringRules *msg, bool value) {
-  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(112, 168), value, UPB_SIZE(120, 176), 22);
+  UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(120, 176), value, UPB_SIZE(128, 184), 22);
 }
 UPB_INLINE void validate_StringRules_set_not_contains(validate_StringRules *msg, upb_strview value) {
-  _upb_sethas(msg, 12);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(96, 136)) = value;
+  _upb_sethas(msg, 13);
+  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(100, 144)) = value;
 }
 UPB_INLINE void validate_StringRules_set_well_known_regex(validate_StringRules *msg, int32_t value) {
-  UPB_WRITE_ONEOF(msg, int32_t, UPB_SIZE(112, 168), value, UPB_SIZE(120, 176), 24);
+  UPB_WRITE_ONEOF(msg, int32_t, UPB_SIZE(120, 176), value, UPB_SIZE(128, 184), 24);
+}
+UPB_INLINE void validate_StringRules_set_strict(validate_StringRules *msg, bool value) {
+  _upb_sethas(msg, 7);
+  UPB_FIELD_AT(msg, bool, UPB_SIZE(56, 56)) = value;
 }
 
 /* validate.BytesRules */
index 10b185f..47cfd86 100644 (file)
 #include <limits.h>
 #include <string.h>
 
+#include <vector>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/grpc.h>
 #include <grpc/impl/codegen/grpc_types.h>
 #include <grpc/impl/codegen/log.h>
@@ -336,32 +341,28 @@ grpc_arg grpc_channel_arg_pointer_create(
   return arg;
 }
 
-char* grpc_channel_args_string(const grpc_channel_args* args) {
-  if (args == nullptr) return nullptr;
-  gpr_strvec v;
-  gpr_strvec_init(&v);
+std::string grpc_channel_args_string(const grpc_channel_args* args) {
+  if (args == nullptr) return "";
+  std::vector<std::string> arg_strings;
   for (size_t i = 0; i < args->num_args; ++i) {
     const grpc_arg& arg = args->args[i];
-    char* s;
+    std::string arg_string;
     switch (arg.type) {
       case GRPC_ARG_INTEGER:
-        gpr_asprintf(&s, "%s=%d", arg.key, arg.value.integer);
+        arg_string = absl::StrFormat("%s=%d", arg.key, arg.value.integer);
         break;
       case GRPC_ARG_STRING:
-        gpr_asprintf(&s, "%s=%s", arg.key, arg.value.string);
+        arg_string = absl::StrFormat("%s=%s", arg.key, arg.value.string);
         break;
       case GRPC_ARG_POINTER:
-        gpr_asprintf(&s, "%s=%p", arg.key, arg.value.pointer.p);
+        arg_string = absl::StrFormat("%s=%p", arg.key, arg.value.pointer.p);
         break;
       default:
-        gpr_asprintf(&s, "arg with unknown type");
+        arg_string = "arg with unknown type";
     }
-    gpr_strvec_add(&v, s);
+    arg_strings.push_back(arg_string);
   }
-  char* result =
-      gpr_strjoin_sep(const_cast<const char**>(v.strs), v.count, ", ", nullptr);
-  gpr_strvec_destroy(&v);
-  return result;
+  return absl::StrJoin(arg_strings, ", ");
 }
 
 namespace {
index df105fd..aed0089 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <grpc/support/port_platform.h>
 
+#include <string>
+
 #include <grpc/grpc.h>
 
 #include "src/core/lib/surface/channel_stack_type.h"
@@ -116,7 +118,7 @@ grpc_arg grpc_channel_arg_pointer_create(char* name, void* value,
 
 // Returns a string representing channel args in human-readable form.
 // Callers takes ownership of result.
-char* grpc_channel_args_string(const grpc_channel_args* args);
+std::string grpc_channel_args_string(const grpc_channel_args* args);
 
 // Takes ownership of the old_args
 typedef grpc_channel_args* (*grpc_channel_args_client_channel_creation_mutator)(
index 87e6759..e297df9 100644 (file)
@@ -65,16 +65,15 @@ typedef struct grpc_call_element grpc_call_element;
 typedef struct grpc_channel_stack grpc_channel_stack;
 typedef struct grpc_call_stack grpc_call_stack;
 
-typedef struct {
+struct grpc_channel_element_args {
   grpc_channel_stack* channel_stack;
   const grpc_channel_args* channel_args;
   /** Transport, iff it is known */
   grpc_transport* optional_transport;
   int is_first;
   int is_last;
-} grpc_channel_element_args;
-
-typedef struct {
+};
+struct grpc_call_element_args {
   grpc_call_stack* call_stack;
   const void* server_transport_data;
   grpc_call_context_element* context;
@@ -83,13 +82,11 @@ typedef struct {
   grpc_millis deadline;
   grpc_core::Arena* arena;
   grpc_core::CallCombiner* call_combiner;
-} grpc_call_element_args;
-
-typedef struct {
+};
+struct grpc_call_stats {
   grpc_transport_stream_stats transport_stream_stats;
   gpr_timespec latency; /* From call creating to enqueing of received status */
-} grpc_call_stats;
-
+};
 /** Information about the call upon completion. */
 struct grpc_call_final_info {
   grpc_call_stats stats;
@@ -107,7 +104,7 @@ struct grpc_call_final_info {
    4. a name, which is useful when debugging
 
    Members are laid out in approximate frequency of use order. */
-typedef struct {
+struct grpc_channel_filter {
   /* Called to eg. send/receive data on a call.
      See grpc_call_next_op on how to call the next element in the stack */
   void (*start_transport_stream_op_batch)(grpc_call_element* elem,
@@ -163,8 +160,7 @@ typedef struct {
 
   /* The name of this filter */
   const char* name;
-} grpc_channel_filter;
-
+};
 /* A channel_element tracks its filter and the filter requested memory within
    a channel allocation */
 struct grpc_channel_element {
index ff6b7a7..fab9dd8 100644 (file)
@@ -387,15 +387,14 @@ void PopulateSocketAddressJson(Json::Object* json, const char* name,
                            (strcmp(uri->scheme, "ipv6") == 0))) {
     const char* host_port = uri->path;
     if (*host_port == '/') ++host_port;
-    grpc_core::UniquePtr<char> host;
-    grpc_core::UniquePtr<char> port;
+    std::string host;
+    std::string port;
     GPR_ASSERT(SplitHostPort(host_port, &host, &port));
     int port_num = -1;
-    if (port != nullptr) {
-      port_num = atoi(port.get());
+    if (!port.empty()) {
+      port_num = atoi(port.data());
     }
-    char* b64_host =
-        grpc_base64_encode(host.get(), strlen(host.get()), false, false);
+    char* b64_host = grpc_base64_encode(host.data(), host.size(), false, false);
     data["tcpip_address"] = Json::Object{
         {"port", port_num},
         {"ip_address", b64_host},
index 73a9b57..6350203 100644 (file)
 
 #include <string>
 
+#include "absl/container/inlined_vector.h"
+
 #include "src/core/lib/channel/channel_trace.h"
 #include "src/core/lib/gpr/time_precise.h"
 #include "src/core/lib/gprpp/atomic.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/manual_constructor.h"
 #include "src/core/lib/gprpp/map.h"
 #include "src/core/lib/gprpp/ref_counted.h"
@@ -167,7 +168,7 @@ class CallCountingHelper {
   void CollectData(CounterData* out);
 
   // Really zero-sized, but 0-sized arrays are illegal on MSVC.
-  InlinedVector<AtomicCounterData, 1> per_cpu_counter_data_storage_;
+  absl::InlinedVector<AtomicCounterData, 1> per_cpu_counter_data_storage_;
   size_t num_cores_ = 0;
 };
 
index 0964ffc..4343936 100644 (file)
@@ -21,6 +21,8 @@
 #include <algorithm>
 #include <cstring>
 
+#include "absl/container/inlined_vector.h"
+
 #include "src/core/lib/channel/channel_trace.h"
 #include "src/core/lib/channel/channelz.h"
 #include "src/core/lib/channel/channelz_registry.h"
@@ -82,7 +84,7 @@ RefCountedPtr<BaseNode> ChannelzRegistry::InternalGet(intptr_t uuid) {
 
 std::string ChannelzRegistry::InternalGetTopChannels(
     intptr_t start_channel_id) {
-  InlinedVector<RefCountedPtr<BaseNode>, 10> top_level_channels;
+  absl::InlinedVector<RefCountedPtr<BaseNode>, 10> top_level_channels;
   RefCountedPtr<BaseNode> node_after_pagination_limit;
   {
     MutexLock lock(&mu_);
@@ -120,7 +122,7 @@ std::string ChannelzRegistry::InternalGetTopChannels(
 }
 
 std::string ChannelzRegistry::InternalGetServers(intptr_t start_server_id) {
-  InlinedVector<RefCountedPtr<BaseNode>, 10> servers;
+  absl::InlinedVector<RefCountedPtr<BaseNode>, 10> servers;
   RefCountedPtr<BaseNode> node_after_pagination_limit;
   {
     MutexLock lock(&mu_);
@@ -158,7 +160,7 @@ std::string ChannelzRegistry::InternalGetServers(intptr_t start_server_id) {
 }
 
 void ChannelzRegistry::InternalLogAllEntities() {
-  InlinedVector<RefCountedPtr<BaseNode>, 10> nodes;
+  absl::InlinedVector<RefCountedPtr<BaseNode>, 10> nodes;
   {
     MutexLock lock(&mu_);
     for (auto& p : node_map_) {
index 23ff63b..be74d9e 100644 (file)
@@ -38,13 +38,12 @@ typedef struct connected_channel_channel_data {
   grpc_transport* transport;
 } channel_data;
 
-typedef struct {
+struct callback_state {
   grpc_closure closure;
   grpc_closure* original_closure;
   grpc_core::CallCombiner* call_combiner;
   const char* reason;
-} callback_state;
-
+};
 typedef struct connected_channel_call_data {
   grpc_core::CallCombiner* call_combiner;
   // Closures used for returning results on the call combiner.
@@ -91,9 +90,12 @@ static callback_state* get_state_for_batch(
 /* We perform a small hack to locate transport data alongside the connected
    channel data in call allocations, to allow everything to be pulled in minimal
    cache line requests */
-#define TRANSPORT_STREAM_FROM_CALL_DATA(calld) ((grpc_stream*)((calld) + 1))
+#define TRANSPORT_STREAM_FROM_CALL_DATA(calld) \
+  ((grpc_stream*)(((char*)(calld)) +           \
+                  GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(call_data))))
 #define CALL_DATA_FROM_TRANSPORT_STREAM(transport_stream) \
-  (((call_data*)(transport_stream)) - 1)
+  ((call_data*)(((char*)(transport_stream)) -             \
+                GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(call_data))))
 
 /* Intercept a call operation and either push it directly up or translate it
    into transport stream operations */
index e8a0245..bd7fd49 100644 (file)
@@ -35,7 +35,7 @@ typedef enum {
   /// Reserved for traffic_class_context.
   GRPC_CONTEXT_TRAFFIC,
 
-  /// Holds a pointer to ServiceConfig::CallData associated with this call.
+  /// Holds a pointer to ServiceConfigCallData associated with this call.
   GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA,
 
   GRPC_CONTEXT_COUNT
index 2bcc60a..461a21d 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <string.h>
 
+#include "absl/strings/str_format.h"
+
 #include <grpc/impl/codegen/slice.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -37,19 +39,16 @@ TraceFlag grpc_handshaker_trace(false, "handshaker");
 
 namespace {
 
-char* HandshakerArgsString(HandshakerArgs* args) {
-  char* args_str = grpc_channel_args_string(args->args);
+std::string HandshakerArgsString(HandshakerArgs* args) {
   size_t num_args = args->args != nullptr ? args->args->num_args : 0;
   size_t read_buffer_length =
       args->read_buffer != nullptr ? args->read_buffer->length : 0;
-  char* str;
-  gpr_asprintf(&str,
-               "{endpoint=%p, args=%p {size=%" PRIuPTR
-               ": %s}, read_buffer=%p (length=%" PRIuPTR "), exit_early=%d}",
-               args->endpoint, args->args, num_args, args_str,
-               args->read_buffer, read_buffer_length, args->exit_early);
-  gpr_free(args_str);
-  return str;
+  return absl::StrFormat(
+      "{endpoint=%p, args=%p {size=%" PRIuPTR
+      ": %s}, read_buffer=%p (length=%" PRIuPTR "), exit_early=%d}",
+      args->endpoint, args->args, num_args,
+      grpc_channel_args_string(args->args), args->read_buffer,
+      read_buffer_length, args->exit_early);
 }
 
 }  // namespace
@@ -127,12 +126,11 @@ void HandshakeManager::Shutdown(grpc_error* why) {
 // Returns true if we've scheduled the on_handshake_done callback.
 bool HandshakeManager::CallNextHandshakerLocked(grpc_error* error) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_handshaker_trace)) {
-    char* args_str = HandshakerArgsString(&args_);
     gpr_log(GPR_INFO,
             "handshake_manager %p: error=%s shutdown=%d index=%" PRIuPTR
             ", args=%s",
-            this, grpc_error_string(error), is_shutdown_, index_, args_str);
-    gpr_free(args_str);
+            this, grpc_error_string(error), is_shutdown_, index_,
+            HandshakerArgsString(&args_).c_str());
   }
   GPR_ASSERT(index_ <= handshakers_.size());
   // If we got an error or we've been shut down or we're exiting early or
index 4f064d9..10b0631 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include <grpc/support/string_util.h>
 
 #include <grpc/impl/codegen/grpc_types.h>
 
 #include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/sync.h"
 #include "src/core/lib/iomgr/closure.h"
@@ -146,7 +147,8 @@ class HandshakeManager : public RefCounted<HandshakeManager> {
   gpr_mu mu_;
   bool is_shutdown_ = false;
   // An array of handshakers added via grpc_handshake_manager_add().
-  InlinedVector<RefCountedPtr<Handshaker>, HANDSHAKERS_INIT_SIZE> handshakers_;
+  absl::InlinedVector<RefCountedPtr<Handshaker>, HANDSHAKERS_INIT_SIZE>
+      handshakers_;
   // The index of the handshaker to invoke next and closure to invoke it.
   size_t index_ = 0;
   grpc_closure call_next_handshaker_;
index 9ec458b..c2a8373 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include "src/core/lib/channel/handshaker_registry.h"
 #include "src/core/lib/gpr/alloc.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/memory.h"
 
 #include <string.h>
@@ -44,7 +45,7 @@ class HandshakerFactoryList {
                       HandshakeManager* handshake_mgr);
 
  private:
-  InlinedVector<std::unique_ptr<HandshakerFactory>, 2> factories_;
+  absl::InlinedVector<std::unique_ptr<HandshakerFactory>, 2> factories_;
 };
 
 HandshakerFactoryList* g_handshaker_factory_lists = nullptr;
@@ -75,25 +76,12 @@ void HandshakerFactoryList::AddHandshakers(const grpc_channel_args* args,
 
 void HandshakerRegistry::Init() {
   GPR_ASSERT(g_handshaker_factory_lists == nullptr);
-  g_handshaker_factory_lists =
-      static_cast<HandshakerFactoryList*>(gpr_malloc_aligned(
-          sizeof(*g_handshaker_factory_lists) * NUM_HANDSHAKER_TYPES,
-          GPR_MAX_ALIGNMENT));
-
-  GPR_ASSERT(g_handshaker_factory_lists != nullptr);
-  for (auto idx = 0; idx < NUM_HANDSHAKER_TYPES; ++idx) {
-    auto factory_list = g_handshaker_factory_lists + idx;
-    new (factory_list) HandshakerFactoryList();
-  }
+  g_handshaker_factory_lists = new HandshakerFactoryList[NUM_HANDSHAKER_TYPES];
 }
 
 void HandshakerRegistry::Shutdown() {
   GPR_ASSERT(g_handshaker_factory_lists != nullptr);
-  for (auto idx = 0; idx < NUM_HANDSHAKER_TYPES; ++idx) {
-    auto factory_list = g_handshaker_factory_lists + idx;
-    factory_list->~HandshakerFactoryList();
-  }
-  gpr_free_aligned(g_handshaker_factory_lists);
+  delete[] g_handshaker_factory_lists;
   g_handshaker_factory_lists = nullptr;
 }
 
index 563db40..39f310a 100644 (file)
 
 #include "src/core/lib/gpr/useful.h"
 
-typedef struct {
+struct status_string_entry {
   const char* str;
   grpc_status_code status;
-} status_string_entry;
-
+};
 static const status_string_entry g_status_string_entries[] = {
     {"OK", GRPC_STATUS_OK},
     {"CANCELLED", GRPC_STATUS_CANCELLED},
index 7faa1dc..7c2a70b 100644 (file)
@@ -34,7 +34,7 @@
 static int zlib_body(z_stream* zs, grpc_slice_buffer* input,
                      grpc_slice_buffer* output,
                      int (*flate)(z_stream* zs, int flush)) {
-  int r;
+  int r = Z_STREAM_END; /* Do not fail on an empty input. */
   int flush;
   size_t i;
   grpc_slice outbuf = GRPC_SLICE_MALLOC(OUTPUT_BLOCK_SIZE);
@@ -68,6 +68,10 @@ static int zlib_body(z_stream* zs, grpc_slice_buffer* input,
       goto error;
     }
   }
+  if (r != Z_STREAM_END) {
+    gpr_log(GPR_INFO, "zlib: Data error");
+    goto error;
+  }
 
   GPR_ASSERT(outbuf.refcount);
   outbuf.data.refcounted.length -= zs->avail_out;
index d8ddf03..7f602b6 100644 (file)
 #include <inttypes.h>
 #include <string.h>
 
+#include <vector>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
 
@@ -140,39 +145,28 @@ double grpc_stats_histo_percentile(const grpc_stats_data* stats,
       static_cast<double>(count) * percentile / 100.0);
 }
 
-char* grpc_stats_data_as_json(const grpc_stats_data* data) {
-  gpr_strvec v;
-  char* tmp;
-  bool is_first = true;
-  gpr_strvec_init(&v);
-  gpr_strvec_add(&v, gpr_strdup("{"));
+std::string grpc_stats_data_as_json(const grpc_stats_data* data) {
+  std::vector<std::string> parts;
+  parts.push_back("{");
   for (size_t i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) {
-    gpr_asprintf(&tmp, "%s\"%s\": %" PRIdPTR, is_first ? "" : ", ",
-                 grpc_stats_counter_name[i], data->counters[i]);
-    gpr_strvec_add(&v, tmp);
-    is_first = false;
+    parts.push_back(absl::StrFormat(
+        "\"%s\": %" PRIdPTR, grpc_stats_counter_name[i], data->counters[i]));
   }
   for (size_t i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) {
-    gpr_asprintf(&tmp, "%s\"%s\": [", is_first ? "" : ", ",
-                 grpc_stats_histogram_name[i]);
-    gpr_strvec_add(&v, tmp);
+    parts.push_back(absl::StrFormat("\"%s\": [", grpc_stats_histogram_name[i]));
     for (int j = 0; j < grpc_stats_histo_buckets[i]; j++) {
-      gpr_asprintf(&tmp, "%s%" PRIdPTR, j == 0 ? "" : ",",
-                   data->histograms[grpc_stats_histo_start[i] + j]);
-      gpr_strvec_add(&v, tmp);
+      parts.push_back(
+          absl::StrFormat("%s%" PRIdPTR, j == 0 ? "" : ",",
+                          data->histograms[grpc_stats_histo_start[i] + j]));
     }
-    gpr_asprintf(&tmp, "], \"%s_bkt\": [", grpc_stats_histogram_name[i]);
-    gpr_strvec_add(&v, tmp);
+    parts.push_back(
+        absl::StrFormat("], \"%s_bkt\": [", grpc_stats_histogram_name[i]));
     for (int j = 0; j < grpc_stats_histo_buckets[i]; j++) {
-      gpr_asprintf(&tmp, "%s%d", j == 0 ? "" : ",",
-                   grpc_stats_histo_bucket_boundaries[i][j]);
-      gpr_strvec_add(&v, tmp);
+      parts.push_back(absl::StrFormat(
+          "%s%d", j == 0 ? "" : ",", grpc_stats_histo_bucket_boundaries[i][j]));
     }
-    gpr_strvec_add(&v, gpr_strdup("]"));
-    is_first = false;
+    parts.push_back("]");
   }
-  gpr_strvec_add(&v, gpr_strdup("}"));
-  tmp = gpr_strvec_flatten(&v, nullptr);
-  gpr_strvec_destroy(&v);
-  return tmp;
+  parts.push_back("}");
+  return absl::StrJoin(parts, "");
 }
index 9e88ad7..3d82886 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <grpc/support/port_platform.h>
 
+#include <string>
+
 #include <grpc/support/atm.h>
 #include "src/core/lib/debug/stats_data.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
@@ -56,7 +58,7 @@ void grpc_stats_collect(grpc_stats_data* output);
 // c = b-a
 void grpc_stats_diff(const grpc_stats_data* b, const grpc_stats_data* a,
                      grpc_stats_data* c);
-char* grpc_stats_data_as_json(const grpc_stats_data* data);
+std::string grpc_stats_data_as_json(const grpc_stats_data* data);
 int grpc_stats_histo_find_bucket_slow(int value, const int* table,
                                       int table_size);
 double grpc_stats_histo_percentile(const grpc_stats_data* data,
index 9f35530..a9c0e62 100644 (file)
 
 /* Simple spinlock. No backoff strategy, gpr_spinlock_lock is almost always
    a concurrency code smell. */
-typedef struct {
+struct gpr_spinlock {
   gpr_atm atm;
-} gpr_spinlock;
-
+};
 #ifdef __cplusplus
 #define GPR_SPINLOCK_INITIALIZER (gpr_spinlock{0})
 #else
index 14436ec..d2c93c6 100644 (file)
@@ -50,12 +50,11 @@ char* gpr_strdup(const char* src) {
   return dst;
 }
 
-typedef struct {
+struct dump_out {
   size_t capacity;
   size_t length;
   char* data;
-} dump_out;
-
+};
 char* gpr_format_timespec(gpr_timespec tm) {
   char time_buffer[35];
   char ns_buffer[11];  // '.' + 9 digits of precision
@@ -266,29 +265,6 @@ char* gpr_strjoin_sep(const char** strs, size_t nstrs, const char* sep,
   return out;
 }
 
-void gpr_strvec_init(gpr_strvec* sv) { memset(sv, 0, sizeof(*sv)); }
-
-void gpr_strvec_destroy(gpr_strvec* sv) {
-  size_t i;
-  for (i = 0; i < sv->count; i++) {
-    gpr_free(sv->strs[i]);
-  }
-  gpr_free(sv->strs);
-}
-
-void gpr_strvec_add(gpr_strvec* sv, char* str) {
-  if (sv->count == sv->capacity) {
-    sv->capacity = GPR_MAX(sv->capacity + 8, sv->capacity * 2);
-    sv->strs = static_cast<char**>(
-        gpr_realloc(sv->strs, sizeof(char*) * sv->capacity));
-  }
-  sv->strs[sv->count++] = str;
-}
-
-char* gpr_strvec_flatten(gpr_strvec* sv, size_t* final_length) {
-  return gpr_strjoin((const char**)sv->strs, sv->count, final_length);
-}
-
 int gpr_strincmp(const char* a, const char* b, size_t n) {
   int ca, cb;
   do {
index fcccf5e..b7d7698 100644 (file)
@@ -96,22 +96,6 @@ void gpr_string_split(const char* input, const char* sep, char*** strs,
    0, 3, 6 or 9 fractional digits. */
 char* gpr_format_timespec(gpr_timespec);
 
-/* A vector of strings... for building up a final string one piece at a time */
-typedef struct {
-  char** strs;
-  size_t count;
-  size_t capacity;
-} gpr_strvec;
-
-/* Initialize/destroy */
-void gpr_strvec_init(gpr_strvec* strs);
-void gpr_strvec_destroy(gpr_strvec* strs);
-/* Add a string to a strvec, takes ownership of the string */
-void gpr_strvec_add(gpr_strvec* strs, char* add);
-/* Return a joined string with all added substrings, optionally setting
-   total_length as per gpr_strjoin */
-char* gpr_strvec_flatten(gpr_strvec* strs, size_t* total_length);
-
 /** Case insensitive string comparison... return <0 if lower(a)<lower(b), ==0 if
     lower(a)==lower(b), >0 if lower(a)>lower(b) */
 int gpr_stricmp(const char* a, const char* b);
index 2a1ca05..56b1cc7 100644 (file)
@@ -108,6 +108,8 @@ void gpr_cv_broadcast(gpr_cv* cv) {
 /*----------------------------------------*/
 
 void gpr_once_init(gpr_once* once, void (*init_function)(void)) {
+  static_assert(sizeof(gpr_once) == sizeof(absl::once_flag),
+                "gpr_once and absl::once_flag must be the same size");
   absl::call_once(*reinterpret_cast<absl::once_flag*>(once), init_function);
 }
 
index 8927dab..db5a7f6 100644 (file)
@@ -254,6 +254,10 @@ gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type) {
     return gpr_time_add(gpr_now(clock_type), t);
   }
 
+  // If the given input hits this code, the same result is not guaranteed for
+  // the same input because it relies on `gpr_now` to calculate the difference
+  // between two different clocks. Please be careful when you want to use this
+  // function in unit tests. (e.g. https://github.com/grpc/grpc/pull/22655)
   return gpr_time_add(gpr_now(clock_type),
                       gpr_time_sub(t, gpr_now(t.clock_type)));
 }
index 095ebf1..4a53d2c 100644 (file)
 namespace grpc_core {
 
 enum class MemoryOrder {
-  RELAXED = std::memory_order_relaxed,
-  CONSUME = std::memory_order_consume,
-  ACQUIRE = std::memory_order_acquire,
-  RELEASE = std::memory_order_release,
-  ACQ_REL = std::memory_order_acq_rel,
-  SEQ_CST = std::memory_order_seq_cst
+  RELAXED = static_cast<int>(std::memory_order_relaxed),
+  CONSUME = static_cast<int>(std::memory_order_consume),
+  ACQUIRE = static_cast<int>(std::memory_order_acquire),
+  RELEASE = static_cast<int>(std::memory_order_release),
+  ACQ_REL = static_cast<int>(std::memory_order_acq_rel),
+  SEQ_CST = static_cast<int>(std::memory_order_seq_cst)
 };
 
 template <typename T>
index d5aa6e1..77eb174 100644 (file)
 
 #include "src/core/lib/gprpp/host_port.h"
 
-#include <string.h>
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
 
-#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gprpp/string_view.h"
 
 namespace grpc_core {
-int JoinHostPort(grpc_core::UniquePtr<char>* out, const char* host, int port) {
-  char* tmp;
-  int ret;
-  if (host[0] != '[' && strchr(host, ':') != nullptr) {
-    /* IPv6 literals must be enclosed in brackets. */
-    ret = gpr_asprintf(&tmp, "[%s]:%d", host, port);
-  } else {
-    /* Ordinary non-bracketed host:port. */
-    ret = gpr_asprintf(&tmp, "%s:%d", host, port);
+
+std::string JoinHostPort(absl::string_view host, int port) {
+  if (!host.empty() && host[0] != '[' && host.rfind(':') != host.npos) {
+    // IPv6 literals must be enclosed in brackets.
+    return absl::StrFormat("[%s]:%d", host, port);
   }
-  out->reset(tmp);
-  return ret;
+  // Ordinary non-bracketed host:port.
+  return absl::StrFormat("%s:%d", host, port);
 }
 
 namespace {
-bool DoSplitHostPort(StringView name, StringView* host, StringView* port,
-                     bool* has_port) {
+bool DoSplitHostPort(absl::string_view name, absl::string_view* host,
+                     absl::string_view* port, bool* has_port) {
   *has_port = false;
   if (!name.empty() && name[0] == '[') {
     /* Parse a bracketed host, typically an IPv6 literal. */
     const size_t rbracket = name.find(']', 1);
-    if (rbracket == grpc_core::StringView::npos) {
+    if (rbracket == absl::string_view::npos) {
       /* Unmatched [ */
       return false;
     }
     if (rbracket == name.size() - 1) {
       /* ]<end> */
-      *port = StringView();
+      *port = absl::string_view();
     } else if (name[rbracket + 1] == ':') {
       /* ]:<port?> */
       *port = name.substr(rbracket + 2, name.size() - rbracket - 2);
@@ -67,16 +59,16 @@ bool DoSplitHostPort(StringView name, StringView* host, StringView* port,
       return false;
     }
     *host = name.substr(1, rbracket - 1);
-    if (host->find(':') == grpc_core::StringView::npos) {
+    if (host->find(':') == absl::string_view::npos) {
       /* Require all bracketed hosts to contain a colon, because a hostname or
          IPv4 address should never use brackets. */
-      *host = StringView();
+      *host = absl::string_view();
       return false;
     }
   } else {
     size_t colon = name.find(':');
-    if (colon != grpc_core::StringView::npos &&
-        name.find(':', colon + 1) == grpc_core::StringView::npos) {
+    if (colon != absl::string_view::npos &&
+        name.find(':', colon + 1) == absl::string_view::npos) {
       /* Exactly 1 colon.  Split into host:port. */
       *host = name.substr(0, colon);
       *port = name.substr(colon + 1, name.size() - colon - 1);
@@ -84,35 +76,37 @@ bool DoSplitHostPort(StringView name, StringView* host, StringView* port,
     } else {
       /* 0 or 2+ colons.  Bare hostname or IPv6 litearal. */
       *host = name;
-      *port = StringView();
+      *port = absl::string_view();
     }
   }
   return true;
 }
 }  // namespace
 
-bool SplitHostPort(StringView name, StringView* host, StringView* port) {
+bool SplitHostPort(absl::string_view name, absl::string_view* host,
+                   absl::string_view* port) {
   bool unused;
   return DoSplitHostPort(name, host, port, &unused);
 }
 
-bool SplitHostPort(StringView name, grpc_core::UniquePtr<char>* host,
-                   grpc_core::UniquePtr<char>* port) {
-  GPR_DEBUG_ASSERT(host != nullptr && *host == nullptr);
-  GPR_DEBUG_ASSERT(port != nullptr && *port == nullptr);
-  StringView host_view;
-  StringView port_view;
+bool SplitHostPort(absl::string_view name, std::string* host,
+                   std::string* port) {
+  GPR_DEBUG_ASSERT(host != nullptr && host->empty());
+  GPR_DEBUG_ASSERT(port != nullptr && port->empty());
+  absl::string_view host_view;
+  absl::string_view port_view;
   bool has_port;
   const bool ret = DoSplitHostPort(name, &host_view, &port_view, &has_port);
   if (ret) {
     // We always set the host, but port is set only when DoSplitHostPort find a
     // port in the string, to remain backward compatible with the old
     // gpr_split_host_port API.
-    *host = StringViewToCString(host_view);
+    *host = std::string(host_view);
     if (has_port) {
-      *port = StringViewToCString(port_view);
+      *port = std::string(port_view);
     }
   }
   return ret;
 }
+
 }  // namespace grpc_core
index c692f99..2d59335 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
-#include "src/core/lib/gprpp/memory.h"
-#include "src/core/lib/gprpp/string_view.h"
+#include <string>
 
-namespace grpc_core {
-
-/** Given a host and port, creates a newly-allocated string of the form
-   "host:port" or "[ho:st]:port", depending on whether the host contains colons
-   like an IPv6 literal.  If the host is already bracketed, then additional
-   brackets will not be added.
+#include "absl/strings/string_view.h"
 
-   Usage is similar to gpr_asprintf: returns the number of bytes written
-   (excluding the final '\0'), and *out points to a string.
+namespace grpc_core {
 
-   In the unlikely event of an error, returns -1 and sets *out to NULL. */
-int JoinHostPort(grpc_core::UniquePtr<char>* out, const char* host, int port);
+// Given a host and port, creates a newly-allocated string of the form
+// "host:port" or "[ho:st]:port", depending on whether the host contains colons
+// like an IPv6 literal.  If the host is already bracketed, then additional
+// brackets will not be added.
+std::string JoinHostPort(absl::string_view host, int port);
 
 /** Given a name in the form "host:port" or "[ho:st]:port", split into hostname
    and port number.
 
    There are two variants of this method:
-   1) StringView output: port and host are returned as views on name.
-   2) char* output: port and host are copied into newly allocated strings.
+   1) absl::string_view output: port and host are returned as views on name.
+   2) std::string output: port and host are copied into newly allocated strings.
 
    Prefer variant (1) over (2), because no allocation or copy is performed in
    variant (1).  Use (2) only when interacting with C API that mandate
@@ -50,9 +46,10 @@ int JoinHostPort(grpc_core::UniquePtr<char>* out, const char* host, int port);
 
    Return true on success, false on failure. Guarantees *host and *port are
    cleared on failure. */
-bool SplitHostPort(StringView name, StringView* host, StringView* port);
-bool SplitHostPort(StringView name, grpc_core::UniquePtr<char>* host,
-                   grpc_core::UniquePtr<char>* port);
+bool SplitHostPort(absl::string_view name, absl::string_view* host,
+                   absl::string_view* port);
+bool SplitHostPort(absl::string_view name, std::string* host,
+                   std::string* port);
 
 }  // namespace grpc_core
 
diff --git a/src/core/lib/gprpp/inlined_vector.h b/src/core/lib/gprpp/inlined_vector.h
deleted file mode 100644 (file)
index 3cad99d..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *
- * Copyright 2017 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPC_CORE_LIB_GPRPP_INLINED_VECTOR_H
-#define GRPC_CORE_LIB_GPRPP_INLINED_VECTOR_H
-
-#include <grpc/support/port_platform.h>
-
-#include <cassert>
-#include <cstring>
-
-#include "absl/container/inlined_vector.h"
-#include "src/core/lib/gprpp/memory.h"
-
-namespace grpc_core {
-
-template <typename T, size_t N, typename A = std::allocator<T>>
-using InlinedVector = absl::InlinedVector<T, N, A>;
-
-}  // namespace grpc_core
-
-#endif /* GRPC_CORE_LIB_GPRPP_INLINED_VECTOR_H */
index 033b861..47fcddd 100644 (file)
@@ -25,8 +25,9 @@
 
 #include <map>
 
-#include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/gprpp/string_view.h"
+#include "absl/strings/string_view.h"
+
+#include "src/core/lib/gprpp/memory.h"
 
 namespace grpc_core {
 
@@ -38,7 +39,8 @@ struct StringLess {
                   const grpc_core::UniquePtr<char>& b) const {
     return strcmp(a.get(), b.get()) < 0;
   }
-  bool operator()(const StringView& a, const StringView& b) const {
+  bool operator()(const absl::string_view& a,
+                  const absl::string_view& b) const {
     const size_t min_size = std::min(a.size(), b.size());
     int c = strncmp(a.data(), b.data(), min_size);
     if (c != 0) return c < 0;
@@ -46,14 +48,6 @@ struct StringLess {
   }
 };
 
-template <typename T>
-struct RefCountedPtrLess {
-  bool operator()(const RefCountedPtr<T>& p1,
-                  const RefCountedPtr<T>& p2) const {
-    return p1.get() < p2.get();
-  }
-};
-
 }  // namespace grpc_core
 
 #endif /* GRPC_CORE_LIB_GPRPP_MAP_H */
index 4c5b465..179491b 100644 (file)
@@ -182,6 +182,11 @@ inline RefCountedPtr<T> MakeRefCounted(Args&&... args) {
   return RefCountedPtr<T>(new T(std::forward<Args>(args)...));
 }
 
+template <typename T>
+bool operator<(const RefCountedPtr<T>& p1, const RefCountedPtr<T>& p2) {
+  return p1.get() < p2.get();
+}
+
 }  // namespace grpc_core
 
 #endif /* GRPC_CORE_LIB_GPRPP_REF_COUNTED_PTR_H */
diff --git a/src/core/lib/gprpp/string_view.h b/src/core/lib/gprpp/string_view.h
deleted file mode 100644 (file)
index bd4724b..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *
- * Copyright 2019 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-#ifndef GRPC_CORE_LIB_GPRPP_STRING_VIEW_H
-#define GRPC_CORE_LIB_GPRPP_STRING_VIEW_H
-
-#include <grpc/support/port_platform.h>
-
-#include <grpc/impl/codegen/slice.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include <algorithm>
-#include <cstdint>
-#include <cstring>
-#include <limits>
-#include <string>
-
-#include "absl/strings/string_view.h"
-#include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/useful.h"
-#include "src/core/lib/gprpp/memory.h"
-
-namespace grpc_core {
-
-using StringView = absl::string_view;
-
-// Converts grpc_slice to StringView.
-inline absl::string_view StringViewFromSlice(const grpc_slice& slice) {
-  return absl::string_view(
-      reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(slice)),
-      GRPC_SLICE_LENGTH(slice));
-}
-
-// Creates a dup of the string viewed by this class.
-// Return value is null-terminated and never nullptr.
-inline grpc_core::UniquePtr<char> StringViewToCString(const StringView sv) {
-  char* str = static_cast<char*>(gpr_malloc(sv.size() + 1));
-  if (sv.size() > 0) memcpy(str, sv.data(), sv.size());
-  str[sv.size()] = '\0';
-  return grpc_core::UniquePtr<char>(str);
-}
-
-}  // namespace grpc_core
-
-#endif /* GRPC_CORE_LIB_GPRPP_STRING_VIEW_H */
index 1712344..947b19c 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
+#include <vector>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/slice.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
 #include "src/core/lib/gpr/string.h"
 
 static void fill_common_header(const grpc_httpcli_request* request,
-                               gpr_strvec* buf, bool connection_close) {
-  size_t i;
-  gpr_strvec_add(buf, gpr_strdup(request->http.path));
-  gpr_strvec_add(buf, gpr_strdup(" HTTP/1.0\r\n"));
+                               bool connection_close,
+                               std::vector<std::string>* buf) {
+  buf->push_back(request->http.path);
+  buf->push_back(" HTTP/1.0\r\n");
   /* just in case some crazy server really expects HTTP/1.1 */
-  gpr_strvec_add(buf, gpr_strdup("Host: "));
-  gpr_strvec_add(buf, gpr_strdup(request->host));
-  gpr_strvec_add(buf, gpr_strdup("\r\n"));
-  if (connection_close)
-    gpr_strvec_add(buf, gpr_strdup("Connection: close\r\n"));
-  gpr_strvec_add(buf,
-                 gpr_strdup("User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n"));
+  buf->push_back("Host: ");
+  buf->push_back(request->host);
+  buf->push_back("\r\n");
+  if (connection_close) buf->push_back("Connection: close\r\n");
+  buf->push_back("User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n");
   /* user supplied headers */
-  for (i = 0; i < request->http.hdr_count; i++) {
-    gpr_strvec_add(buf, gpr_strdup(request->http.hdrs[i].key));
-    gpr_strvec_add(buf, gpr_strdup(": "));
-    gpr_strvec_add(buf, gpr_strdup(request->http.hdrs[i].value));
-    gpr_strvec_add(buf, gpr_strdup("\r\n"));
+  for (size_t i = 0; i < request->http.hdr_count; i++) {
+    buf->push_back(request->http.hdrs[i].key);
+    buf->push_back(": ");
+    buf->push_back(request->http.hdrs[i].value);
+    buf->push_back("\r\n");
   }
 }
 
 grpc_slice grpc_httpcli_format_get_request(
     const grpc_httpcli_request* request) {
-  gpr_strvec out;
-  char* flat;
-  size_t flat_len;
-
-  gpr_strvec_init(&out);
-  gpr_strvec_add(&out, gpr_strdup("GET "));
-  fill_common_header(request, &out, true);
-  gpr_strvec_add(&out, gpr_strdup("\r\n"));
-
-  flat = gpr_strvec_flatten(&out, &flat_len);
-  gpr_strvec_destroy(&out);
-
-  return grpc_slice_new(flat, flat_len, gpr_free);
+  std::vector<std::string> out;
+  out.push_back("GET ");
+  fill_common_header(request, true, &out);
+  out.push_back("\r\n");
+  std::string req = absl::StrJoin(out, "");
+  return grpc_slice_from_copied_buffer(req.data(), req.size());
 }
 
 grpc_slice grpc_httpcli_format_post_request(const grpc_httpcli_request* request,
                                             const char* body_bytes,
                                             size_t body_size) {
-  gpr_strvec out;
-  char* tmp;
-  size_t out_len;
-  size_t i;
-
-  gpr_strvec_init(&out);
-
-  gpr_strvec_add(&out, gpr_strdup("POST "));
-  fill_common_header(request, &out, true);
-  if (body_bytes) {
-    uint8_t has_content_type = 0;
-    for (i = 0; i < request->http.hdr_count; i++) {
+  std::vector<std::string> out;
+  out.push_back("POST ");
+  fill_common_header(request, true, &out);
+  if (body_bytes != nullptr) {
+    bool has_content_type = false;
+    for (size_t i = 0; i < request->http.hdr_count; i++) {
       if (strcmp(request->http.hdrs[i].key, "Content-Type") == 0) {
-        has_content_type = 1;
+        has_content_type = true;
         break;
       }
     }
     if (!has_content_type) {
-      gpr_strvec_add(&out, gpr_strdup("Content-Type: text/plain\r\n"));
+      out.push_back("Content-Type: text/plain\r\n");
     }
-    gpr_asprintf(&tmp, "Content-Length: %lu\r\n",
-                 static_cast<unsigned long>(body_size));
-    gpr_strvec_add(&out, tmp);
+    out.push_back(absl::StrFormat("Content-Length: %lu\r\n",
+                                  static_cast<unsigned long>(body_size)));
   }
-  gpr_strvec_add(&out, gpr_strdup("\r\n"));
-  tmp = gpr_strvec_flatten(&out, &out_len);
-  gpr_strvec_destroy(&out);
-
-  if (body_bytes) {
-    tmp = static_cast<char*>(gpr_realloc(tmp, out_len + body_size));
-    memcpy(tmp + out_len, body_bytes, body_size);
-    out_len += body_size;
+  out.push_back("\r\n");
+  std::string req = absl::StrJoin(out, "");
+  if (body_bytes != nullptr) {
+    absl::StrAppend(&req, absl::string_view(body_bytes, body_size));
   }
-
-  return grpc_slice_new(tmp, out_len, gpr_free);
+  return grpc_slice_from_copied_buffer(req.data(), req.size());
 }
 
 grpc_slice grpc_httpcli_format_connect_request(
     const grpc_httpcli_request* request) {
-  gpr_strvec out;
-  gpr_strvec_init(&out);
-  gpr_strvec_add(&out, gpr_strdup("CONNECT "));
-  fill_common_header(request, &out, false);
-  gpr_strvec_add(&out, gpr_strdup("\r\n"));
-  size_t flat_len;
-  char* flat = gpr_strvec_flatten(&out, &flat_len);
-  gpr_strvec_destroy(&out);
-  return grpc_slice_new(flat, flat_len, gpr_free);
+  std::vector<std::string> out;
+  out.push_back("CONNECT ");
+  fill_common_header(request, false, &out);
+  out.push_back("\r\n");
+  std::string req = absl::StrJoin(out, "");
+  return grpc_slice_from_copied_buffer(req.data(), req.size());
 }
index 7edcdcc..5e723bc 100644 (file)
@@ -38,7 +38,7 @@
 #include "src/core/lib/iomgr/tcp_client.h"
 #include "src/core/lib/slice/slice_internal.h"
 
-typedef struct {
+struct internal_request {
   grpc_slice request_text;
   grpc_http_parser parser;
   grpc_resolved_addresses* addresses;
@@ -60,8 +60,7 @@ typedef struct {
   grpc_closure connected;
   grpc_error* overall_error;
   grpc_resource_quota* resource_quota;
-} internal_request;
-
+};
 static grpc_httpcli_get_override g_get_override = nullptr;
 static grpc_httpcli_post_override g_post_override = nullptr;
 
index b073508..16a160c 100644 (file)
@@ -41,13 +41,12 @@ typedef struct grpc_httpcli_context {
   grpc_pollset_set* pollset_set;
 } grpc_httpcli_context;
 
-typedef struct {
+struct grpc_httpcli_handshaker {
   const char* default_port;
   void (*handshake)(void* arg, grpc_endpoint* endpoint, const char* host,
                     grpc_millis deadline,
                     void (*on_done)(void* arg, grpc_endpoint* endpoint));
-} grpc_httpcli_handshaker;
-
+};
 extern const grpc_httpcli_handshaker grpc_httpcli_plaintext;
 extern const grpc_httpcli_handshaker grpc_httpcli_ssl;
 
index 3d95cdf..6338bfd 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <string.h>
 
+#include "absl/strings/string_view.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -30,7 +32,6 @@
 #include "src/core/lib/channel/handshaker_registry.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/gprpp/string_view.h"
 #include "src/core/lib/iomgr/pollset.h"
 #include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/security/security_connector/ssl_utils.h"
@@ -111,7 +112,7 @@ class grpc_httpcli_ssl_channel_security_connector final
     return strcmp(secure_peer_name_, other->secure_peer_name_);
   }
 
-  bool check_call_host(grpc_core::StringView /*host*/,
+  bool check_call_host(absl::string_view /*host*/,
                        grpc_auth_context* /*auth_context*/,
                        grpc_closure* /*on_call_host_checked*/,
                        grpc_error** error) override {
@@ -154,12 +155,11 @@ httpcli_ssl_channel_security_connector_create(
 
 /* handshaker */
 
-typedef struct {
+struct on_done_closure {
   void (*func)(void* arg, grpc_endpoint* endpoint);
   void* arg;
   grpc_core::RefCountedPtr<grpc_core::HandshakeManager> handshake_mgr;
-} on_done_closure;
-
+};
 static void on_handshake_done(void* arg, grpc_error* error) {
   auto* args = static_cast<grpc_core::HandshakerArgs*>(arg);
   on_done_closure* c = static_cast<on_done_closure*>(args->user_data);
index b51fd5a..2da2190 100644 (file)
@@ -79,7 +79,7 @@ typedef struct grpc_http_response {
   char* body = nullptr;
 } grpc_http_response;
 
-typedef struct {
+struct grpc_http_parser {
   grpc_http_parser_state state;
   grpc_http_type type;
 
@@ -94,8 +94,7 @@ typedef struct {
   uint8_t cur_line[GRPC_HTTP_PARSER_MAX_HEADER_LENGTH];
   size_t cur_line_length;
   size_t cur_line_end_length;
-} grpc_http_parser;
-
+};
 void grpc_http_parser_init(grpc_http_parser* parser, grpc_http_type type,
                            void* request_or_response);
 void grpc_http_parser_destroy(grpc_http_parser* parser);
index c2552ca..f804f02 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
+#include "absl/types/optional.h"
+
 #include "src/core/lib/iomgr/port.h"
 
 #include <grpc/support/time.h>
 
 #include "src/core/lib/gprpp/memory.h"
-#include "src/core/lib/gprpp/optional.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/internal_errqueue.h"
 
@@ -34,52 +35,52 @@ namespace grpc_core {
 
 struct ConnectionMetrics {
   /* Delivery rate in Bytes/s. */
-  Optional<uint64_t> delivery_rate;
+  absl::optional<uint64_t> delivery_rate;
   /* If the delivery rate is limited by the application, this is set to true. */
-  Optional<bool> is_delivery_rate_app_limited;
+  absl::optional<bool> is_delivery_rate_app_limited;
   /* Total packets retransmitted. */
-  Optional<uint32_t> packet_retx;
+  absl::optional<uint32_t> packet_retx;
   /* Total packets retransmitted spuriously. This metric is smaller than or
   equal to packet_retx. */
-  Optional<uint32_t> packet_spurious_retx;
+  absl::optional<uint32_t> packet_spurious_retx;
   /* Total packets sent. */
-  Optional<uint32_t> packet_sent;
+  absl::optional<uint32_t> packet_sent;
   /* Total packets delivered. */
-  Optional<uint32_t> packet_delivered;
+  absl::optional<uint32_t> packet_delivered;
   /* Total packets delivered with ECE marked. This metric is smaller than or
   equal to packet_delivered. */
-  Optional<uint32_t> packet_delivered_ce;
+  absl::optional<uint32_t> packet_delivered_ce;
   /* Total bytes lost so far. */
-  Optional<uint64_t> data_retx;
+  absl::optional<uint64_t> data_retx;
   /* Total bytes sent so far. */
-  Optional<uint64_t> data_sent;
+  absl::optional<uint64_t> data_sent;
   /* Total bytes in write queue but not sent. */
-  Optional<uint64_t> data_notsent;
+  absl::optional<uint64_t> data_notsent;
   /* Pacing rate of the connection in Bps */
-  Optional<uint64_t> pacing_rate;
+  absl::optional<uint64_t> pacing_rate;
   /* Minimum RTT observed in usec. */
-  Optional<uint32_t> min_rtt;
+  absl::optional<uint32_t> min_rtt;
   /* Smoothed RTT in usec */
-  Optional<uint32_t> srtt;
+  absl::optional<uint32_t> srtt;
   /* Send congestion window. */
-  Optional<uint32_t> congestion_window;
+  absl::optional<uint32_t> congestion_window;
   /* Slow start threshold in packets. */
-  Optional<uint32_t> snd_ssthresh;
+  absl::optional<uint32_t> snd_ssthresh;
   /* Maximum degree of reordering (i.e., maximum number of packets reodered)
    on the connection. */
-  Optional<uint32_t> reordering;
+  absl::optional<uint32_t> reordering;
   /* Represents the number of recurring retransmissions of the first sequence
   that is not acknowledged yet. */
-  Optional<uint8_t> recurring_retrans;
+  absl::optional<uint8_t> recurring_retrans;
   /* The cumulative time (in usec) that the transport protocol was busy
    sending data. */
-  Optional<uint64_t> busy_usec;
+  absl::optional<uint64_t> busy_usec;
   /* The cumulative time (in usec) that the transport protocol was limited by
    the receive window size. */
-  Optional<uint64_t> rwnd_limited_usec;
+  absl::optional<uint64_t> rwnd_limited_usec;
   /* The cumulative time (in usec) that the transport protocol was limited by
    the send buffer size. */
-  Optional<uint64_t> sndbuf_limited_usec;
+  absl::optional<uint64_t> sndbuf_limited_usec;
 };
 
 struct Timestamp {
index d3f43cf..44acd9f 100644 (file)
 
 #include <stddef.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include <grpc/support/atm.h>
 
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/mpscq.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
@@ -208,7 +209,7 @@ class CallCombinerClosureList {
 
   // There are generally a maximum of 6 closures to run in the call
   // combiner, one for each pending op.
-  InlinedVector<CallCombinerClosure, 6> closures_;
+  absl::InlinedVector<CallCombinerClosure, 6> closures_;
 };
 
 }  // namespace grpc_core
index aae932e..6bb6534 100644 (file)
@@ -121,12 +121,11 @@ inline grpc_closure* grpc_closure_init(grpc_closure* closure,
 
 namespace closure_impl {
 
-typedef struct {
+struct wrapped_closure {
   grpc_iomgr_cb_func cb;
   void* cb_arg;
   grpc_closure wrapper;
-} wrapped_closure;
-
+};
 inline void closure_wrapper(void* arg, grpc_error* error) {
   wrapped_closure* wc = static_cast<wrapped_closure*>(arg);
   grpc_iomgr_cb_func cb = wc->cb;
index 987f2d2..f9ee1c9 100644 (file)
@@ -39,7 +39,7 @@
 
 extern grpc_core::TraceFlag grpc_tcp_trace;
 
-typedef struct {
+struct CFStreamEndpoint {
   grpc_endpoint base;
   gpr_refcount refcount;
 
@@ -58,8 +58,7 @@ typedef struct {
   char* peer_string;
   grpc_resource_user* resource_user;
   grpc_resource_user_slice_allocator slice_allocator;
-} CFStreamEndpoint;
-
+};
 static void CFStreamFree(CFStreamEndpoint* ep) {
   grpc_resource_user_unref(ep->resource_user);
   CFRelease(ep->read_stream);
index 08f9e3c..e01185b 100644 (file)
 
 #include "src/core/lib/iomgr/endpoint.h"
 
-typedef struct {
+struct grpc_endpoint_pair {
   grpc_endpoint* client;
   grpc_endpoint* server;
-} grpc_endpoint_pair;
-
+};
 grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char* name,
                                                    grpc_channel_args* args);
 
index dedc837..6ffadd5 100644 (file)
@@ -446,12 +446,11 @@ grpc_error* grpc_error_set_int(grpc_error* src, grpc_error_ints which,
   return new_err;
 }
 
-typedef struct {
+struct special_error_status_map {
   grpc_status_code code;
   const char* msg;
   size_t len;
-} special_error_status_map;
-
+};
 const special_error_status_map error_status_map[] = {
     {GRPC_STATUS_OK, "", 0},                // GRPC_ERROR_NONE
     {GRPC_STATUS_INVALID_ARGUMENT, "", 0},  // GRPC_ERROR_RESERVED_1
@@ -532,17 +531,15 @@ static const char* no_error_string = "\"No Error\"";
 static const char* oom_error_string = "\"Out of memory\"";
 static const char* cancelled_error_string = "\"Cancelled\"";
 
-typedef struct {
+struct kv_pair {
   char* key;
   char* value;
-} kv_pair;
-
-typedef struct {
+};
+struct kv_pairs {
   kv_pair* kvs;
   size_t num_kvs;
   size_t cap_kvs;
-} kv_pairs;
-
+};
 static void append_chr(char c, char** s, size_t* sz, size_t* cap) {
   if (*sz == *cap) {
     *cap = GPR_MAX(8, 3 * *cap / 2);
index 5c79aa7..ac3ff87 100644 (file)
@@ -30,7 +30,6 @@
 #include <grpc/support/time.h>
 
 #include "src/core/lib/debug/trace.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 
 /// Opaque representation of an error.
 /// See https://github.com/grpc/grpc/blob/master/doc/core/grpc-error.md for a
index 392d38b..04955e1 100644 (file)
 #include <sys/socket.h>
 #include <unistd.h>
 
+#include <vector>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/cpu.h>
 #include <grpc/support/string_util.h>
@@ -1064,30 +1069,23 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
   GRPC_STATS_INC_POLLSET_KICK();
   grpc_error* ret_err = GRPC_ERROR_NONE;
   if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
-    gpr_strvec log;
-    gpr_strvec_init(&log);
-    char* tmp;
-    gpr_asprintf(&tmp, "PS:%p KICK:%p curps=%p curworker=%p root=%p", pollset,
-                 specific_worker, (void*)gpr_tls_get(&g_current_thread_pollset),
-                 (void*)gpr_tls_get(&g_current_thread_worker),
-                 pollset->root_worker);
-    gpr_strvec_add(&log, tmp);
+    std::vector<std::string> log;
+    log.push_back(absl::StrFormat(
+        "PS:%p KICK:%p curps=%p curworker=%p root=%p", pollset, specific_worker,
+        (void*)gpr_tls_get(&g_current_thread_pollset),
+        (void*)gpr_tls_get(&g_current_thread_worker), pollset->root_worker));
     if (pollset->root_worker != nullptr) {
-      gpr_asprintf(&tmp, " {kick_state=%s next=%p {kick_state=%s}}",
-                   kick_state_string(pollset->root_worker->state),
-                   pollset->root_worker->next,
-                   kick_state_string(pollset->root_worker->next->state));
-      gpr_strvec_add(&log, tmp);
+      log.push_back(absl::StrFormat(
+          " {kick_state=%s next=%p {kick_state=%s}}",
+          kick_state_string(pollset->root_worker->state),
+          pollset->root_worker->next,
+          kick_state_string(pollset->root_worker->next->state)));
     }
     if (specific_worker != nullptr) {
-      gpr_asprintf(&tmp, " worker_kick_state=%s",
-                   kick_state_string(specific_worker->state));
-      gpr_strvec_add(&log, tmp);
+      log.push_back(absl::StrFormat(" worker_kick_state=%s",
+                                    kick_state_string(specific_worker->state)));
     }
-    tmp = gpr_strvec_flatten(&log, nullptr);
-    gpr_strvec_destroy(&log);
-    gpr_log(GPR_DEBUG, "%s", tmp);
-    gpr_free(tmp);
+    gpr_log(GPR_DEBUG, "%s", absl::StrJoin(log, "").c_str());
   }
 
   if (specific_worker == nullptr) {
index f2fab7c..ac7233e 100644 (file)
@@ -263,11 +263,10 @@ static void fd_global_shutdown(void);
  * Pollset Declarations
  */
 
-typedef struct {
+struct pwlink {
   grpc_pollset_worker* next;
   grpc_pollset_worker* prev;
-} pwlink;
-
+};
 typedef enum { PWLINK_POLLABLE = 0, PWLINK_POLLSET, PWLINK_COUNT } pwlinks;
 
 struct grpc_pollset_worker {
index 02e4da1..3d32359 100644 (file)
@@ -81,11 +81,10 @@ static const char* g_poll_strategy_name = nullptr;
 typedef const grpc_event_engine_vtable* (*event_engine_factory_fn)(
     bool explicit_request);
 
-typedef struct {
+struct event_engine_factory {
   const char* name;
   event_engine_factory_fn factory;
-} event_engine_factory;
-
+};
 namespace {
 
 grpc_poll_function_type real_poll_function;
index 4e746bc..0079946 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <grpc/support/port_platform.h>
 
+#include <limits>
+
 #include <grpc/impl/codegen/grpc_types.h>
 #include <grpc/support/atm.h>
 #include <grpc/support/cpu.h>
@@ -132,7 +134,12 @@ class ExecCtx {
   ExecCtx(const ExecCtx&) = delete;
   ExecCtx& operator=(const ExecCtx&) = delete;
 
-  unsigned starting_cpu() const { return starting_cpu_; }
+  unsigned starting_cpu() {
+    if (starting_cpu_ == std::numeric_limits<unsigned>::max()) {
+      starting_cpu_ = gpr_cpu_current_cpu();
+    }
+    return starting_cpu_;
+  }
 
   struct CombinerData {
     /* currently active combiner: updated only via combiner.c */
@@ -239,7 +246,7 @@ class ExecCtx {
   CombinerData combiner_data_ = {nullptr, nullptr};
   uintptr_t flags_;
 
-  unsigned starting_cpu_ = gpr_cpu_current_cpu();
+  unsigned starting_cpu_ = std::numeric_limits<unsigned>::max();
 
   bool now_is_valid_ = false;
   grpc_millis now_ = 0;
@@ -357,6 +364,11 @@ class ApplicationCallbackExecCtx {
   /** Global shutdown for ApplicationCallbackExecCtx. Called by init. */
   static void GlobalShutdown(void) { gpr_tls_destroy(&callback_exec_ctx_); }
 
+  static bool Available() {
+    return reinterpret_cast<ApplicationCallbackExecCtx*>(
+               gpr_tls_get(&callback_exec_ctx_)) != nullptr;
+  }
+
  private:
   uintptr_t flags_{0u};
   grpc_experimental_completion_queue_functor* head_{nullptr};
index 7016ffc..025a141 100644 (file)
 
 #define GRPC_MAX_SOCKADDR_SIZE 128
 
-typedef struct {
+struct grpc_resolved_address {
   char addr[GRPC_MAX_SOCKADDR_SIZE];
   socklen_t len;
-} grpc_resolved_address;
-
-typedef struct {
+};
+struct grpc_resolved_addresses {
   size_t naddrs;
   grpc_resolved_address* addrs;
-} grpc_resolved_addresses;
-
+};
 typedef struct grpc_address_resolver_vtable {
   void (*resolve_address)(const char* addr, const char* default_port,
                           grpc_pollset_set* interested_parties,
index 1d5230d..a19c5a7 100644 (file)
 
 #include <string.h>
 
-typedef struct grpc_custom_resolver {
-  grpc_closure* on_done;
-  grpc_resolved_addresses** addresses;
-  char* host;
-  char* port;
-} grpc_custom_resolver;
+struct grpc_custom_resolver {
+  grpc_closure* on_done = nullptr;
+  grpc_resolved_addresses** addresses = nullptr;
+  std::string host;
+  std::string port;
+};
 
 static grpc_custom_resolver_vtable* resolve_address_vtable = nullptr;
 
@@ -48,18 +48,18 @@ static int retry_named_port_failure(grpc_custom_resolver* r,
   // This loop is copied from resolve_address_posix.c
   const char* svc[][2] = {{"http", "80"}, {"https", "443"}};
   for (size_t i = 0; i < GPR_ARRAY_SIZE(svc); i++) {
-    if (strcmp(r->port, svc[i][0]) == 0) {
-      gpr_free(r->port);
-      r->port = gpr_strdup(svc[i][1]);
+    if (r->port == svc[i][0]) {
+      r->port = svc[i][1];
       if (res) {
-        grpc_error* error =
-            resolve_address_vtable->resolve(r->host, r->port, res);
+        grpc_error* error = resolve_address_vtable->resolve(
+            r->host.c_str(), r->port.c_str(), res);
         if (error != GRPC_ERROR_NONE) {
           GRPC_ERROR_UNREF(error);
           return 0;
         }
       } else {
-        resolve_address_vtable->resolve_async(r, r->host, r->port);
+        resolve_address_vtable->resolve_async(r, r->host.c_str(),
+                                              r->port.c_str());
       }
       return 1;
     }
@@ -81,26 +81,23 @@ void grpc_custom_resolve_callback(grpc_custom_resolver* r,
   if (r->on_done) {
     grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, error);
   }
-  gpr_free(r->host);
-  gpr_free(r->port);
-  gpr_free(r);
+  delete r;
 }
 
 static grpc_error* try_split_host_port(const char* name,
                                        const char* default_port,
-                                       grpc_core::UniquePtr<char>* host,
-                                       grpc_core::UniquePtr<char>* port) {
+                                       std::string* host, std::string* port) {
   /* parse name, splitting it into host and port parts */
   grpc_error* error;
   grpc_core::SplitHostPort(name, host, port);
-  if (*host == nullptr) {
+  if (host->empty()) {
     char* msg;
     gpr_asprintf(&msg, "unparseable host:port: '%s'", name);
     error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
     gpr_free(msg);
     return error;
   }
-  if (*port == nullptr) {
+  if (port->empty()) {
     // TODO(murgatroid99): add tests for this case
     if (default_port == nullptr) {
       char* msg;
@@ -109,7 +106,7 @@ static grpc_error* try_split_host_port(const char* name,
       gpr_free(msg);
       return error;
     }
-    port->reset(gpr_strdup(default_port));
+    *port = default_port;
   }
   return GRPC_ERROR_NONE;
 }
@@ -117,26 +114,21 @@ static grpc_error* try_split_host_port(const char* name,
 static grpc_error* blocking_resolve_address_impl(
     const char* name, const char* default_port,
     grpc_resolved_addresses** addresses) {
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
-  grpc_error* err;
-
   GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
 
-  err = try_split_host_port(name, default_port, &host, &port);
+  grpc_custom_resolver resolver;
+  grpc_error* err =
+      try_split_host_port(name, default_port, &resolver.host, &resolver.port);
   if (err != GRPC_ERROR_NONE) {
     return err;
   }
 
   /* Call getaddrinfo */
-  grpc_custom_resolver resolver;
-  resolver.host = host.get();
-  resolver.port = port.get();
-
   grpc_resolved_addresses* addrs;
   grpc_core::ExecCtx* curr = grpc_core::ExecCtx::Get();
   grpc_core::ExecCtx::Set(nullptr);
-  err = resolve_address_vtable->resolve(host.get(), port.get(), &addrs);
+  err = resolve_address_vtable->resolve(resolver.host.c_str(),
+                                        resolver.port.c_str(), &addrs);
   if (err != GRPC_ERROR_NONE) {
     if (retry_named_port_failure(&resolver, &addrs)) {
       GRPC_ERROR_UNREF(err);
@@ -154,24 +146,22 @@ static void resolve_address_impl(const char* name, const char* default_port,
                                  grpc_pollset_set* /*interested_parties*/,
                                  grpc_closure* on_done,
                                  grpc_resolved_addresses** addrs) {
-  grpc_custom_resolver* r = nullptr;
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
-  grpc_error* err;
   GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
-  err = try_split_host_port(name, default_port, &host, &port);
+  std::string host;
+  std::string port;
+  grpc_error* err = try_split_host_port(name, default_port, &host, &port);
   if (err != GRPC_ERROR_NONE) {
     grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, err);
     return;
   }
-  r = (grpc_custom_resolver*)gpr_malloc(sizeof(grpc_custom_resolver));
+  grpc_custom_resolver* r = new grpc_custom_resolver();
   r->on_done = on_done;
   r->addresses = addrs;
-  r->host = host.release();
-  r->port = port.release();
+  r->host = std::move(host);
+  r->port = std::move(port);
 
   /* Call getaddrinfo */
-  resolve_address_vtable->resolve_async(r, r->host, r->port);
+  resolve_address_vtable->resolve_async(r, r->host.c_str(), r->port.c_str());
 }
 
 static grpc_address_resolver_vtable custom_resolver_vtable = {
index e0c6714..f5f68ca 100644 (file)
 typedef struct grpc_custom_resolver grpc_custom_resolver;
 
 typedef struct grpc_custom_resolver_vtable {
-  grpc_error* (*resolve)(char* host, char* port, grpc_resolved_addresses** res);
-  void (*resolve_async)(grpc_custom_resolver* resolver, char* host, char* port);
+  grpc_error* (*resolve)(const char* host, const char* port,
+                         grpc_resolved_addresses** res);
+  void (*resolve_async)(grpc_custom_resolver* resolver, const char* host,
+                        const char* port);
 } grpc_custom_resolver_vtable;
 
 void grpc_custom_resolve_callback(grpc_custom_resolver* resolver,
index 1d2a79f..1558dd5 100644 (file)
@@ -57,24 +57,24 @@ static grpc_error* posix_blocking_resolve_address(
     return grpc_resolve_unix_domain_address(name + 5, addresses);
   }
 
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
+  std::string host;
+  std::string port;
   /* parse name, splitting it into host and port parts */
   grpc_core::SplitHostPort(name, &host, &port);
-  if (host == nullptr) {
+  if (host.empty()) {
     err = grpc_error_set_str(
         GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
         GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
     goto done;
   }
-  if (port == nullptr) {
+  if (port.empty()) {
     if (default_port == nullptr) {
       err = grpc_error_set_str(
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
       goto done;
     }
-    port.reset(gpr_strdup(default_port));
+    port = default_port;
   }
 
   /* Call getaddrinfo */
@@ -84,16 +84,16 @@ static grpc_error* posix_blocking_resolve_address(
   hints.ai_flags = AI_PASSIVE;     /* for wildcard IP address */
 
   GRPC_SCHEDULING_START_BLOCKING_REGION;
-  s = getaddrinfo(host.get(), port.get(), &hints, &result);
+  s = getaddrinfo(host.c_str(), port.c_str(), &hints, &result);
   GRPC_SCHEDULING_END_BLOCKING_REGION;
 
   if (s != 0) {
     /* Retry if well-known service name is recognized */
     const char* svc[][2] = {{"http", "80"}, {"https", "443"}};
     for (i = 0; i < GPR_ARRAY_SIZE(svc); i++) {
-      if (strcmp(port.get(), svc[i][0]) == 0) {
+      if (port == svc[i][0]) {
         GRPC_SCHEDULING_START_BLOCKING_REGION;
-        s = getaddrinfo(host.get(), svc[i][1], &hints, &result);
+        s = getaddrinfo(host.c_str(), svc[i][1], &hints, &result);
         GRPC_SCHEDULING_END_BLOCKING_REGION;
         break;
       }
@@ -139,15 +139,14 @@ done:
   return err;
 }
 
-typedef struct {
+struct request {
   char* name;
   char* default_port;
   grpc_closure* on_done;
   grpc_resolved_addresses** addrs_out;
   grpc_closure request_closure;
   void* arg;
-} request;
-
+};
 /* Callback to be passed to grpc Executor to asynch-ify
  * grpc_blocking_resolve_address */
 static void do_request_thread(void* rp, grpc_error* /*error*/) {
index 5a9d442..faf0f78 100644 (file)
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 
-typedef struct {
+struct request {
   char* name;
   char* default_port;
   grpc_closure request_closure;
   grpc_closure* on_done;
   grpc_resolved_addresses** addresses;
-} request;
-
+};
 static grpc_error* windows_blocking_resolve_address(
     const char* name, const char* default_port,
     grpc_resolved_addresses** addresses) {
@@ -62,17 +61,17 @@ static grpc_error* windows_blocking_resolve_address(
   grpc_error* error = GRPC_ERROR_NONE;
 
   /* parse name, splitting it into host and port parts */
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
+  std::string host;
+  std::string port;
   grpc_core::SplitHostPort(name, &host, &port);
-  if (host == NULL) {
+  if (host.empty()) {
     char* msg;
     gpr_asprintf(&msg, "unparseable host:port: '%s'", name);
     error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
     gpr_free(msg);
     goto done;
   }
-  if (port == NULL) {
+  if (port.empty()) {
     if (default_port == NULL) {
       char* msg;
       gpr_asprintf(&msg, "no port in name '%s'", name);
@@ -80,7 +79,7 @@ static grpc_error* windows_blocking_resolve_address(
       gpr_free(msg);
       goto done;
     }
-    port.reset(gpr_strdup(default_port));
+    port = default_port;
   }
 
   /* Call getaddrinfo */
@@ -90,7 +89,7 @@ static grpc_error* windows_blocking_resolve_address(
   hints.ai_flags = AI_PASSIVE;     /* for wildcard IP address */
 
   GRPC_SCHEDULING_START_BLOCKING_REGION;
-  s = getaddrinfo(host.get(), port.get(), &hints, &result);
+  s = getaddrinfo(host.c_str(), port.c_str(), &hints, &result);
   GRPC_SCHEDULING_END_BLOCKING_REGION;
   if (s != 0) {
     error = GRPC_WSA_ERROR(WSAGetLastError(), "getaddrinfo");
@@ -113,14 +112,6 @@ static grpc_error* windows_blocking_resolve_address(
     i++;
   }
 
-  {
-    for (i = 0; i < (*addresses)->naddrs; i++) {
-      char* buf;
-      grpc_sockaddr_to_string(&buf, &(*addresses)->addrs[i], 0);
-      gpr_free(buf);
-    }
-  }
-
 done:
   if (result) {
     freeaddrinfo(result);
index 0fc0279..b5df53e 100644 (file)
@@ -39,11 +39,10 @@ grpc_core::TraceFlag grpc_resource_quota_trace(false, "resource_quota");
 #define MEMORY_USAGE_ESTIMATION_MAX 65536
 
 /* Internal linked list pointers for a resource user */
-typedef struct {
+struct grpc_resource_user_link {
   grpc_resource_user* next;
   grpc_resource_user* prev;
-} grpc_resource_user_link;
-
+};
 /* Resource users are kept in (potentially) several intrusive linked lists
    at once. These are the list names. */
 typedef enum {
@@ -610,12 +609,11 @@ static void ru_allocated_slices(void* arg, grpc_error* error) {
  * combiner
  */
 
-typedef struct {
+struct rq_resize_args {
   int64_t size;
   grpc_resource_quota* resource_quota;
   grpc_closure closure;
-} rq_resize_args;
-
+};
 static void rq_resize(void* args, grpc_error* /*error*/) {
   rq_resize_args* a = static_cast<rq_resize_args*>(args);
   int64_t delta = a->size - a->resource_quota->size;
index 2f8ed22..c144750 100644 (file)
@@ -24,6 +24,8 @@
 #include <inttypes.h>
 #include <string.h>
 
+#include "absl/strings/str_format.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -150,23 +152,18 @@ void grpc_sockaddr_make_wildcard6(int port,
   resolved_wild_out->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
 }
 
-int grpc_sockaddr_to_string(char** out,
-                            const grpc_resolved_address* resolved_addr,
-                            int normalize) {
-  const grpc_sockaddr* addr;
+std::string grpc_sockaddr_to_string(const grpc_resolved_address* resolved_addr,
+                                    bool normalize) {
   const int save_errno = errno;
   grpc_resolved_address addr_normalized;
-  char ntop_buf[GRPC_INET6_ADDRSTRLEN];
-  const void* ip = nullptr;
-  int port = 0;
-  uint32_t sin6_scope_id = 0;
-  int ret;
-
-  *out = nullptr;
   if (normalize && grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
     resolved_addr = &addr_normalized;
   }
-  addr = reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
+  const grpc_sockaddr* addr =
+      reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
+  const void* ip = nullptr;
+  int port = 0;
+  uint32_t sin6_scope_id = 0;
   if (addr->sa_family == GRPC_AF_INET) {
     const grpc_sockaddr_in* addr4 =
         reinterpret_cast<const grpc_sockaddr_in*>(addr);
@@ -179,25 +176,24 @@ int grpc_sockaddr_to_string(char** out,
     port = grpc_ntohs(addr6->sin6_port);
     sin6_scope_id = addr6->sin6_scope_id;
   }
+  char ntop_buf[GRPC_INET6_ADDRSTRLEN];
+  std::string out;
   if (ip != nullptr && grpc_inet_ntop(addr->sa_family, ip, ntop_buf,
                                       sizeof(ntop_buf)) != nullptr) {
-    grpc_core::UniquePtr<char> tmp_out;
     if (sin6_scope_id != 0) {
-      char* host_with_scope;
-      /* Enclose sin6_scope_id with the format defined in RFC 6784 section 2. */
-      gpr_asprintf(&host_with_scope, "%s%%25%" PRIu32, ntop_buf, sin6_scope_id);
-      ret = grpc_core::JoinHostPort(&tmp_out, host_with_scope, port);
-      gpr_free(host_with_scope);
+      // Enclose sin6_scope_id with the format defined in RFC 6784 section 2.
+      std::string host_with_scope =
+          absl::StrFormat("%s%%25%" PRIu32, ntop_buf, sin6_scope_id);
+      out = grpc_core::JoinHostPort(host_with_scope, port);
     } else {
-      ret = grpc_core::JoinHostPort(&tmp_out, ntop_buf, port);
+      out = grpc_core::JoinHostPort(ntop_buf, port);
     }
-    *out = tmp_out.release();
   } else {
-    ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);
+    out = absl::StrFormat("(sockaddr family=%d)", addr->sa_family);
   }
   /* This is probably redundant, but we wouldn't want to log the wrong error. */
   errno = save_errno;
-  return ret;
+  return out;
 }
 
 void grpc_string_to_sockaddr(grpc_resolved_address* out, char* addr, int port) {
@@ -226,15 +222,13 @@ char* grpc_sockaddr_to_uri(const grpc_resolved_address* resolved_addr) {
   if (scheme == nullptr || strcmp("unix", scheme) == 0) {
     return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
   }
-  char* path = nullptr;
+  std::string path =
+      grpc_sockaddr_to_string(resolved_addr, false /* normalize */);
   char* uri_str = nullptr;
-  if (grpc_sockaddr_to_string(&path, resolved_addr,
-                              false /* suppress errors */) &&
-      scheme != nullptr) {
-    gpr_asprintf(&uri_str, "%s:%s", scheme, path);
+  if (scheme != nullptr) {
+    gpr_asprintf(&uri_str, "%s:%s", scheme, path.c_str());
   }
-  gpr_free(path);
-  return uri_str != nullptr ? uri_str : nullptr;
+  return uri_str;
 }
 
 const char* grpc_sockaddr_get_uri_scheme(
index a4e90a7..4a844e9 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <grpc/support/port_platform.h>
 
+#include <string>
+
 #include "src/core/lib/iomgr/resolve_address.h"
 
 /* Returns true if addr is an IPv4-mapped IPv6 address within the
@@ -56,20 +58,13 @@ int grpc_sockaddr_get_port(const grpc_resolved_address* addr);
 /* Set IP port number of a sockaddr */
 int grpc_sockaddr_set_port(const grpc_resolved_address* addr, int port);
 
-/* Converts a sockaddr into a newly-allocated human-readable string.
-
-   Currently, only the AF_INET and AF_INET6 families are recognized.
-   If the normalize flag is enabled, ::ffff:0.0.0.0/96 IPv6 addresses are
-   displayed as plain IPv4.
-
-   Usage is similar to gpr_asprintf: returns the number of bytes written
-   (excluding the final '\0'), and *out points to a string which must later be
-   destroyed using gpr_free().
-
-   In the unlikely event of an error, returns -1 and sets *out to NULL.
-   The existing value of errno is always preserved. */
-int grpc_sockaddr_to_string(char** out, const grpc_resolved_address* addr,
-                            int normalize);
+// Converts a sockaddr into a newly-allocated human-readable string.
+//
+// Currently, only the AF_INET and AF_INET6 families are recognized.
+// If the normalize flag is enabled, ::ffff:0.0.0.0/96 IPv6 addresses are
+// displayed as plain IPv4.
+std::string grpc_sockaddr_to_string(const grpc_resolved_address* addr,
+                                    bool normalize);
 
 void grpc_string_to_sockaddr(grpc_resolved_address* out, char* addr, int port);
 
index 9a52f4e..92ea6c1 100644 (file)
@@ -26,7 +26,7 @@
 #include "src/core/lib/iomgr/resolve_address.h"
 
 /** The virtual table of grpc_socket_factory */
-typedef struct {
+struct grpc_socket_factory_vtable {
   /** Replacement for socket(2) */
   int (*socket)(grpc_socket_factory* factory, int domain, int type,
                 int protocol);
@@ -37,8 +37,7 @@ typedef struct {
   int (*compare)(grpc_socket_factory* a, grpc_socket_factory* b);
   /** Destroys the socket factory instance */
   void (*destroy)(grpc_socket_factory* factory);
-} grpc_socket_factory_vtable;
-
+};
 /** The Socket Factory interface allows changes on socket options */
 struct grpc_socket_factory {
   const grpc_socket_factory_vtable* vtable;
index 8742a3b..9f77a3b 100644 (file)
 #include <stdbool.h>
 
 /** The virtual table of grpc_socket_mutator */
-typedef struct {
+struct grpc_socket_mutator_vtable {
   /** Mutates the socket options of \a fd */
   bool (*mutate_fd)(int fd, grpc_socket_mutator* mutator);
   /** Compare socket mutator \a a and \a b */
   int (*compare)(grpc_socket_mutator* a, grpc_socket_mutator* b);
   /** Destroys the socket mutator instance */
   void (*destroy)(grpc_socket_mutator* mutator);
-} grpc_socket_mutator_vtable;
-
+};
 /** The Socket Mutator interface allows changes on socket options */
 struct grpc_socket_mutator {
   const grpc_socket_mutator_vtable* vtable;
index f368cb7..60432d4 100644 (file)
@@ -41,6 +41,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <string>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
@@ -396,12 +398,10 @@ int grpc_ipv6_loopback_available(void) {
 
 static grpc_error* error_for_fd(int fd, const grpc_resolved_address* addr) {
   if (fd >= 0) return GRPC_ERROR_NONE;
-  char* addr_str;
-  grpc_sockaddr_to_string(&addr_str, addr, 0);
-  grpc_error* err = grpc_error_set_str(GRPC_OS_ERROR(errno, "socket"),
-                                       GRPC_ERROR_STR_TARGET_ADDRESS,
-                                       grpc_slice_from_copied_string(addr_str));
-  gpr_free(addr_str);
+  std::string addr_str = grpc_sockaddr_to_string(addr, false);
+  grpc_error* err = grpc_error_set_str(
+      GRPC_OS_ERROR(errno, "socket"), GRPC_ERROR_STR_TARGET_ADDRESS,
+      grpc_slice_from_copied_string(addr_str.c_str()));
   return err;
 }
 
index 23d8c0c..7461a75 100644 (file)
@@ -143,14 +143,12 @@ static void OnOpen(void* arg, grpc_error* error) {
 
 static void ParseResolvedAddress(const grpc_resolved_address* addr,
                                  CFStringRef* host, int* port) {
-  char* host_port;
-  grpc_sockaddr_to_string(&host_port, addr, 1);
-  grpc_core::UniquePtr<char> host_string;
-  grpc_core::UniquePtr<char> port_string;
+  std::string host_port = grpc_sockaddr_to_string(addr, true);
+  std::string host_string;
+  std::string port_string;
   grpc_core::SplitHostPort(host_port, &host_string, &port_string);
-  *host =
-      CFStringCreateWithCString(NULL, host_string.get(), kCFStringEncodingUTF8);
-  gpr_free(host_port);
+  *host = CFStringCreateWithCString(NULL, host_string.c_str(),
+                                    kCFStringEncodingUTF8);
   *port = grpc_sockaddr_get_port(addr);
 }
 
index 928c70d..7a673f4 100644 (file)
@@ -49,7 +49,7 @@
 
 extern grpc_core::TraceFlag grpc_tcp_trace;
 
-typedef struct {
+struct async_connect {
   gpr_mu mu;
   grpc_fd* fd;
   grpc_timer alarm;
@@ -61,8 +61,7 @@ typedef struct {
   grpc_endpoint** ep;
   grpc_closure* closure;
   grpc_channel_args* channel_args;
-} async_connect;
-
+};
 static grpc_error* prepare_socket(const grpc_resolved_address* addr, int fd,
                                   const grpc_channel_args* channel_args) {
   grpc_error* err = GRPC_ERROR_NONE;
@@ -302,9 +301,13 @@ void grpc_tcp_client_create_from_prepared_fd(
     return;
   }
   if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
+    grpc_error* error = GRPC_OS_ERROR(errno, "connect");
+    char* addr_str = grpc_sockaddr_to_uri(addr);
+    error = grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS,
+                               grpc_slice_from_copied_string(addr_str));
+    gpr_free(addr_str);
     grpc_fd_orphan(fdobj, nullptr, nullptr, "tcp_client_connect_error");
-    grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure,
-                            GRPC_OS_ERROR(errno, "connect"));
+    grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure, error);
     return;
   }
 
index 5f32f5d..3d310b1 100644 (file)
@@ -40,7 +40,7 @@
 #include "src/core/lib/iomgr/tcp_windows.h"
 #include "src/core/lib/iomgr/timer.h"
 
-typedef struct {
+struct async_connect {
   grpc_closure* on_done;
   gpr_mu mu;
   grpc_winsocket* socket;
@@ -51,8 +51,7 @@ typedef struct {
   grpc_closure on_connect;
   grpc_endpoint** endpoint;
   grpc_channel_args* channel_args;
-} async_connect;
-
+};
 static void async_connect_unlock_and_cleanup(async_connect* ac,
                                              grpc_winsocket* socket) {
   int done = (--ac->refs == 0);
index 9141c65..0688c5e 100644 (file)
@@ -52,7 +52,7 @@ void grpc_custom_endpoint_init(grpc_socket_vtable* impl) {
   grpc_set_tcp_server_impl(&custom_tcp_server_vtable);
 }
 
-typedef struct {
+struct custom_tcp_endpoint {
   grpc_endpoint base;
   gpr_refcount refcount;
   grpc_custom_socket* socket;
@@ -69,8 +69,7 @@ typedef struct {
   bool shutting_down;
 
   char* peer_string;
-} custom_tcp_endpoint;
-
+};
 static void tcp_free(grpc_custom_socket* s) {
   custom_tcp_endpoint* tcp = (custom_tcp_endpoint*)s->endpoint;
   grpc_resource_user_unref(tcp->resource_user);
index 8de1258..49781ad 100644 (file)
@@ -23,6 +23,8 @@
 #include <assert.h>
 #include <string.h>
 
+#include <string>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
@@ -389,15 +391,9 @@ static grpc_error* tcp_server_add_port(grpc_tcp_server* s,
   }
 
   if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
-    char* port_string;
-    grpc_sockaddr_to_string(&port_string, addr, 0);
-    const char* str = grpc_error_string(error);
-    if (port_string) {
-      gpr_log(GPR_INFO, "SERVER %p add_port %s error=%s", s, port_string, str);
-      gpr_free(port_string);
-    } else {
-      gpr_log(GPR_INFO, "SERVER %p add_port error=%s", s, str);
-    }
+    gpr_log(GPR_INFO, "SERVER %p add_port %s error=%s", s,
+            grpc_sockaddr_to_string(addr, false).c_str(),
+            grpc_error_string(error));
   }
 
   family = grpc_sockaddr_get_family(addr);
index 25f2e77..25dc791 100644 (file)
@@ -37,6 +37,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <string>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -349,7 +351,7 @@ static grpc_error* add_wildcard_addrs_to_server(grpc_tcp_server* s,
 
 static grpc_error* clone_port(grpc_tcp_listener* listener, unsigned count) {
   grpc_tcp_listener* sp = nullptr;
-  char* addr_str;
+  std::string addr_str;
   char* name;
   grpc_error* err;
 
@@ -368,8 +370,8 @@ static grpc_error* clone_port(grpc_tcp_listener* listener, unsigned count) {
                                          true, &port);
     if (err != GRPC_ERROR_NONE) return err;
     listener->server->nports++;
-    grpc_sockaddr_to_string(&addr_str, &listener->addr, 1);
-    gpr_asprintf(&name, "tcp-server-listener:%s/clone-%d", addr_str, i);
+    addr_str = grpc_sockaddr_to_string(&listener->addr, true);
+    gpr_asprintf(&name, "tcp-server-listener:%s/clone-%d", addr_str.c_str(), i);
     sp = static_cast<grpc_tcp_listener*>(gpr_malloc(sizeof(grpc_tcp_listener)));
     sp->next = listener->next;
     listener->next = sp;
@@ -389,7 +391,6 @@ static grpc_error* clone_port(grpc_tcp_listener* listener, unsigned count) {
     while (listener->server->tail->next != nullptr) {
       listener->server->tail = listener->server->tail->next;
     }
-    gpr_free(addr_str);
     gpr_free(name);
   }
 
index da18cc3..6e98256 100644 (file)
@@ -29,6 +29,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <string>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -83,15 +85,15 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s, int fd,
                                         grpc_tcp_listener** listener) {
   grpc_tcp_listener* sp = nullptr;
   int port = -1;
-  char* addr_str;
+  std::string addr_str;
   char* name;
 
   grpc_error* err =
       grpc_tcp_server_prepare_socket(s, fd, addr, s->so_reuseport, &port);
   if (err == GRPC_ERROR_NONE) {
     GPR_ASSERT(port > 0);
-    grpc_sockaddr_to_string(&addr_str, addr, 1);
-    gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
+    addr_str = grpc_sockaddr_to_string(addr, true);
+    gpr_asprintf(&name, "tcp-server-listener:%s", addr_str.c_str());
     gpr_mu_lock(&s->mu);
     s->nports++;
     GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
@@ -114,7 +116,6 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s, int fd,
     sp->sibling = nullptr;
     GPR_ASSERT(sp->emfd);
     gpr_mu_unlock(&s->mu);
-    gpr_free(addr_str);
     gpr_free(name);
   }
 
index 7fd86c5..9a6c169 100644 (file)
@@ -29,6 +29,8 @@
 #include <stddef.h>
 #include <string.h>
 
+#include <string>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -112,7 +114,6 @@ grpc_error* grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s,
   }
   for (ifa_it = ifa; ifa_it != nullptr; ifa_it = ifa_it->ifa_next) {
     grpc_resolved_address addr;
-    char* addr_str = nullptr;
     grpc_dualstack_mode dsmode;
     grpc_tcp_listener* new_sp = nullptr;
     const char* ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : "<unknown>");
@@ -131,30 +132,27 @@ grpc_error* grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s,
       err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set port");
       break;
     }
-    if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) {
-      addr_str = gpr_strdup("<error>");
-    }
+    std::string addr_str = grpc_sockaddr_to_string(&addr, false);
     gpr_log(GPR_DEBUG,
             "Adding local addr from interface %s flags 0x%x to server: %s",
-            ifa_name, ifa_it->ifa_flags, addr_str);
+            ifa_name, ifa_it->ifa_flags, addr_str.c_str());
     /* We could have multiple interfaces with the same address (e.g., bonding),
        so look for duplicates. */
     if (find_listener_with_addr(s, &addr) != nullptr) {
-      gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str,
-              ifa_name);
-      gpr_free(addr_str);
+      gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s",
+              addr_str.c_str(), ifa_name);
       continue;
     }
     if ((err = grpc_tcp_server_add_addr(s, &addr, port_index, fd_index, &dsmode,
                                         &new_sp)) != GRPC_ERROR_NONE) {
       char* err_str = nullptr;
       grpc_error* root_err;
-      if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) {
+      if (gpr_asprintf(&err_str, "Failed to add listener: %s",
+                       addr_str.c_str()) < 0) {
         err_str = gpr_strdup("Failed to add listener");
       }
       root_err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_str);
       gpr_free(err_str);
-      gpr_free(addr_str);
       err = grpc_error_add_child(root_err, err);
       break;
     } else {
@@ -166,7 +164,6 @@ grpc_error* grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s,
       }
       sp = new_sp;
     }
-    gpr_free(addr_str);
   }
   freeifaddrs(ifa);
   if (err != GRPC_ERROR_NONE) {
index f0847a1..942b7d6 100644 (file)
@@ -370,7 +370,7 @@ static void uv_resolve_callback(uv_getaddrinfo_t* req, int status,
                                tcp_error_create("getaddrinfo failed", status));
 }
 
-static grpc_error* uv_resolve(char* host, char* port,
+static grpc_error* uv_resolve(const char* host, const char* port,
                               grpc_resolved_addresses** result) {
   int status;
   uv_getaddrinfo_t req;
@@ -388,7 +388,8 @@ static grpc_error* uv_resolve(char* host, char* port,
   return tcp_error_create("getaddrinfo failed", status);
 }
 
-static void uv_resolve_async(grpc_custom_resolver* r, char* host, char* port) {
+static void uv_resolve_async(grpc_custom_resolver* r, const char* host,
+                             const char* port) {
   int status;
   uv_getaddrinfo_t* req =
       (uv_getaddrinfo_t*)gpr_malloc(sizeof(uv_getaddrinfo_t));
index 8745f7f..877d1be 100644 (file)
@@ -24,7 +24,7 @@
    weighted mean.  It is designed for batch operations where we do many adds
    before updating the average. */
 
-typedef struct {
+struct grpc_time_averaged_stats {
   /* The initial average value.  This is the reported average until the first
      grpc_time_averaged_stats_update_average call.  If a positive regress_weight
      is used, we also regress towards this value on each update. */
@@ -56,8 +56,7 @@ typedef struct {
   /* A time-decayed average of the (batch_total_value_ / batch_num_samples_),
      computed by decaying the samples_in_avg_ weight in the weighted average. */
   double aggregate_weighted_avg;
-} grpc_time_averaged_stats;
-
+};
 /* See the comments on the members above for an explanation of init_avg,
    regress_weight, and persistence_factor. */
 void grpc_time_averaged_stats_init(grpc_time_averaged_stats* stats,
index 0f00eea..3c28838 100644 (file)
@@ -56,7 +56,7 @@ grpc_core::TraceFlag grpc_timer_check_trace(false, "timer_check");
  * stats maintained in 'stats' and the relevant timers are then moved from the
  * 'list' to 'heap'.
  */
-typedef struct {
+struct timer_shard {
   gpr_mu mu;
   grpc_time_averaged_stats stats;
   /* All and only timers with deadlines < this will be in the heap. */
@@ -70,8 +70,7 @@ typedef struct {
   grpc_timer_heap heap;
   /* This holds timers whose deadline is >= queue_deadline_cap. */
   grpc_timer list;
-} timer_shard;
-
+};
 static size_t g_num_shards;
 
 /* Array of timer shards. Whenever a timer (grpc_timer *) is added, its address
index 7b983e7..2b08c65 100644 (file)
 
 #include "src/core/lib/iomgr/timer.h"
 
-typedef struct {
+struct grpc_timer_heap {
   grpc_timer** timers;
   uint32_t timer_count;
   uint32_t timer_capacity;
-} grpc_timer_heap;
-
+};
 /* return true if the new timer is the first timer in the heap */
 bool grpc_timer_heap_add(grpc_timer_heap* heap, grpc_timer* timer);
 
index 0bfd22f..461f543 100644 (file)
@@ -44,6 +44,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -52,7 +54,6 @@
 #include <grpc/support/time.h>
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/memory.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/ev_posix.h"
@@ -147,11 +148,9 @@ GrpcUdpListener::GrpcUdpListener(grpc_udp_server* server, int fd,
       server_(server),
       orphan_notified_(false),
       already_shutdown_(false) {
-  char* addr_str;
   char* name;
-  grpc_sockaddr_to_string(&addr_str, addr, 1);
-  gpr_asprintf(&name, "udp-server-listener:%s", addr_str);
-  gpr_free(addr_str);
+  std::string addr_str = grpc_sockaddr_to_string(addr, true);
+  gpr_asprintf(&name, "udp-server-listener:%s", addr_str.c_str());
   emfd_ = grpc_fd_create(fd, name, true);
   memcpy(&addr_, addr, sizeof(grpc_resolved_address));
   GPR_ASSERT(emfd_);
@@ -177,7 +176,7 @@ struct grpc_udp_server {
   int shutdown;
 
   /* An array of listeners */
-  grpc_core::InlinedVector<GrpcUdpListener, 16> listeners;
+  absl::InlinedVector<GrpcUdpListener, 16> listeners;
 
   /* factory for use to create udp listeners */
   GrpcUdpHandlerFactory* handler_factory;
@@ -412,10 +411,8 @@ static int prepare_socket(grpc_socket_factory* socket_factory, int fd,
   }
 
   if (bind_socket(socket_factory, fd, addr) < 0) {
-    char* addr_str;
-    grpc_sockaddr_to_string(&addr_str, addr, 0);
-    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
-    gpr_free(addr_str);
+    std::string addr_str = grpc_sockaddr_to_string(addr, false);
+    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str.c_str(), strerror(errno));
     goto error;
   }
 
@@ -582,10 +579,8 @@ int grpc_udp_server_add_port(grpc_udp_server* s,
             "Try to have multiple listeners on same port, but SO_REUSEPORT is "
             "not supported. Only create 1 listener.");
   }
-  char* addr_str;
-  grpc_sockaddr_to_string(&addr_str, addr, 1);
-  gpr_log(GPR_DEBUG, "add address: %s to server", addr_str);
-  gpr_free(addr_str);
+  std::string addr_str = grpc_sockaddr_to_string(addr, true);
+  gpr_log(GPR_DEBUG, "add address: %s to server", addr_str.c_str());
 
   int allocated_port1 = -1;
   int allocated_port2 = -1;
index a949ae5..8e26a46 100644 (file)
@@ -27,7 +27,8 @@
 #include <string>
 #include <vector>
 
-#include "src/core/lib/gprpp/string_view.h"
+#include "absl/strings/string_view.h"
+
 #include "src/core/lib/iomgr/error.h"
 
 namespace grpc_core {
@@ -55,7 +56,7 @@ class Json {
   using Array = std::vector<Json>;
 
   // Parses JSON string from json_str.  On error, sets *error.
-  static Json Parse(StringView json_str, grpc_error** error);
+  static Json Parse(absl::string_view json_str, grpc_error** error);
 
   Json() = default;
 
index 6a1aaa3..208e972 100644 (file)
@@ -34,7 +34,7 @@ namespace {
 
 class JsonReader {
  public:
-  static grpc_error* Parse(StringView input, Json* output);
+  static grpc_error* Parse(absl::string_view input, Json* output);
 
  private:
   enum class Status {
@@ -80,7 +80,7 @@ class JsonReader {
    */
   static constexpr uint32_t GRPC_JSON_READ_CHAR_EOF = 0x7ffffff0;
 
-  explicit JsonReader(StringView input)
+  explicit JsonReader(absl::string_view input)
       : original_input_(reinterpret_cast<const uint8_t*>(input.data())),
         input_(original_input_),
         remaining_input_(input.size()) {}
@@ -815,7 +815,7 @@ JsonReader::Status JsonReader::Run() {
   GPR_UNREACHABLE_CODE(return Status::GRPC_JSON_INTERNAL_ERROR);
 }
 
-grpc_error* JsonReader::Parse(StringView input, Json* output) {
+grpc_error* JsonReader::Parse(absl::string_view input, Json* output) {
   JsonReader reader(input);
   Status status = reader.Run();
   if (reader.truncated_errors_) {
@@ -846,7 +846,7 @@ grpc_error* JsonReader::Parse(StringView input, Json* output) {
 
 }  // namespace
 
-Json Json::Parse(StringView json_str, grpc_error** error) {
+Json Json::Parse(absl::string_view json_str, grpc_error** error) {
   Json value;
   *error = JsonReader::Parse(json_str, &value);
   return value;
index 3f37190..6235a3d 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+#include "absl/strings/string_view.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
 #include "src/core/lib/json/json.h"
 
-#include "src/core/lib/gprpp/string_view.h"
-
 namespace grpc_core {
 
 namespace {
@@ -52,7 +52,7 @@ class JsonWriter {
 
   void OutputCheck(size_t needed);
   void OutputChar(char c);
-  void OutputString(const StringView str);
+  void OutputString(const absl::string_view str);
   void OutputIndent();
   void ValueEnd();
   void EscapeUtf16(uint16_t utf16);
@@ -92,7 +92,7 @@ void JsonWriter::OutputChar(char c) {
   output_.push_back(c);
 }
 
-void JsonWriter::OutputString(const StringView str) {
+void JsonWriter::OutputString(const absl::string_view str) {
   OutputCheck(str.size());
   output_.append(str.data(), str.size());
 }
@@ -110,11 +110,12 @@ void JsonWriter::OutputIndent() {
     return;
   }
   while (spaces >= (sizeof(spacesstr) - 1)) {
-    OutputString(StringView(spacesstr, sizeof(spacesstr) - 1));
+    OutputString(absl::string_view(spacesstr, sizeof(spacesstr) - 1));
     spaces -= static_cast<unsigned>(sizeof(spacesstr) - 1);
   }
   if (spaces == 0) return;
-  OutputString(StringView(spacesstr + sizeof(spacesstr) - 1 - spaces, spaces));
+  OutputString(
+      absl::string_view(spacesstr + sizeof(spacesstr) - 1 - spaces, spaces));
 }
 
 void JsonWriter::ValueEnd() {
@@ -131,7 +132,7 @@ void JsonWriter::ValueEnd() {
 
 void JsonWriter::EscapeUtf16(uint16_t utf16) {
   static const char hex[] = "0123456789abcdef";
-  OutputString(StringView("\\u", 2));
+  OutputString(absl::string_view("\\u", 2));
   OutputChar(hex[(utf16 >> 12) & 0x0f]);
   OutputChar(hex[(utf16 >> 8) & 0x0f]);
   OutputChar(hex[(utf16 >> 4) & 0x0f]);
@@ -150,19 +151,19 @@ void JsonWriter::EscapeString(const std::string& string) {
     } else if (c < 32 || c == 127) {
       switch (c) {
         case '\b':
-          OutputString(StringView("\\b", 2));
+          OutputString(absl::string_view("\\b", 2));
           break;
         case '\f':
-          OutputString(StringView("\\f", 2));
+          OutputString(absl::string_view("\\f", 2));
           break;
         case '\n':
-          OutputString(StringView("\\n", 2));
+          OutputString(absl::string_view("\\n", 2));
           break;
         case '\r':
-          OutputString(StringView("\\r", 2));
+          OutputString(absl::string_view("\\r", 2));
           break;
         case '\t':
-          OutputString(StringView("\\t", 2));
+          OutputString(absl::string_view("\\t", 2));
           break;
         default:
           EscapeUtf16(c);
index 57967e1..6b9e9d1 100644 (file)
@@ -23,7 +23,8 @@
 
 #include <string>
 
-#include "src/core/lib/gprpp/inlined_vector.h"
+#include "absl/container/inlined_vector.h"
+
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/security/credentials/credentials.h"
 
@@ -71,8 +72,7 @@ class grpc_composite_channel_credentials : public grpc_channel_credentials {
 class grpc_composite_call_credentials : public grpc_call_credentials {
  public:
   using CallCredentialsList =
-      grpc_core::InlinedVector<grpc_core::RefCountedPtr<grpc_call_credentials>,
-                               2>;
+      absl::InlinedVector<grpc_core::RefCountedPtr<grpc_call_credentials>, 2>;
 
   grpc_composite_call_credentials(
       grpc_core::RefCountedPtr<grpc_call_credentials> creds1,
index e738553..7aff8f2 100644 (file)
@@ -148,11 +148,10 @@ grpc_channel_credentials* grpc_channel_credentials_find_in_args(
 
 /* --- grpc_credentials_mdelem_array. --- */
 
-typedef struct {
+struct grpc_credentials_mdelem_array {
   grpc_mdelem* md = nullptr;
   size_t size = 0;
-} grpc_credentials_mdelem_array;
-
+};
 /// Takes a new ref to \a md.
 void grpc_credentials_mdelem_array_add(grpc_credentials_mdelem_array* list,
                                        grpc_mdelem md);
index 58e550e..f7dc85e 100644 (file)
@@ -68,13 +68,12 @@ static grpc_core::internal::grpc_gce_tenancy_checker g_gce_tenancy_checker =
 
 static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); }
 
-typedef struct {
+struct metadata_server_detector {
   grpc_polling_entity pollent;
   int is_done;
   int success;
   grpc_http_response response;
-} metadata_server_detector;
-
+};
 grpc_core::RefCountedPtr<grpc_channel_security_connector>
 grpc_google_default_channel_credentials::create_security_connector(
     grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
@@ -224,17 +223,13 @@ static grpc_error* create_default_creds_from_path(
   grpc_slice creds_data = grpc_empty_slice();
   grpc_error* error = GRPC_ERROR_NONE;
   Json json;
-  grpc_core::StringView str;
   if (creds_path == nullptr) {
     error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("creds_path unset");
     goto end;
   }
   error = grpc_load_file(creds_path, 0, &creds_data);
   if (error != GRPC_ERROR_NONE) goto end;
-  str = grpc_core::StringView(
-      reinterpret_cast<char*>(GRPC_SLICE_START_PTR(creds_data)),
-      GRPC_SLICE_LENGTH(creds_data));
-  json = Json::Parse(str, &error);
+  json = Json::Parse(grpc_core::StringViewFromSlice(creds_data), &error);
   if (error != GRPC_ERROR_NONE) goto end;
   if (json.type() != Json::Type::OBJECT) {
     error = grpc_error_set_str(
index 23887b0..b9a41c6 100644 (file)
 
 /* --- auth_json_key parsing. --- */
 
-typedef struct {
+struct grpc_auth_json_key {
   const char* type;
   char* private_key_id;
   char* client_id;
   char* client_email;
   RSA* private_key;
-} grpc_auth_json_key;
-
+};
 /* Returns 1 if the object is valid, 0 otherwise. */
 int grpc_auth_json_key_is_valid(const grpc_auth_json_key* json_key);
 
index 1d082b2..cd8217f 100644 (file)
@@ -86,9 +86,7 @@ static Json parse_json_part_from_jwt(const char* str, size_t len) {
     gpr_log(GPR_ERROR, "Invalid base64.");
     return Json();  // JSON null
   }
-  grpc_core::StringView string(
-      reinterpret_cast<char*>(GRPC_SLICE_START_PTR(slice)),
-      GRPC_SLICE_LENGTH(slice));
+  absl::string_view string = grpc_core::StringViewFromSlice(slice);
   grpc_error* error = GRPC_ERROR_NONE;
   Json json = Json::Parse(string, &error);
   if (error != GRPC_ERROR_NONE) {
@@ -120,14 +118,13 @@ static gpr_timespec validate_time_field(const Json& json, const char* key) {
 
 /* --- JOSE header. see http://tools.ietf.org/html/rfc7515#section-4 --- */
 
-typedef struct {
+struct jose_header {
   const char* alg;
   const char* kid;
   const char* typ;
   /* TODO(jboeuf): Add others as needed (jku, jwk, x5u, x5c and so on...). */
   grpc_core::ManualConstructor<Json> json;
-} jose_header;
-
+};
 static void jose_header_destroy(jose_header* h) {
   h->json.Destroy();
   gpr_free(h);
@@ -337,7 +334,7 @@ typedef enum {
   HTTP_RESPONSE_COUNT /* must be last */
 } http_response_index;
 
-typedef struct {
+struct verifier_cb_ctx {
   grpc_jwt_verifier* verifier;
   grpc_polling_entity pollent;
   jose_header* header;
@@ -348,8 +345,7 @@ typedef struct {
   void* user_data;
   grpc_jwt_verification_done_cb user_cb;
   grpc_http_response responses[HTTP_RESPONSE_COUNT];
-} verifier_cb_ctx;
-
+};
 /* Takes ownership of the header, claims and signature. */
 static verifier_cb_ctx* verifier_cb_ctx_create(
     grpc_jwt_verifier* verifier, grpc_pollset* pollset, jose_header* header,
@@ -394,11 +390,10 @@ gpr_timespec grpc_jwt_verifier_clock_skew = {60, 0, GPR_TIMESPAN};
 /* Max delay defaults to one minute. */
 grpc_millis grpc_jwt_verifier_max_delay = 60 * GPR_MS_PER_SEC;
 
-typedef struct {
+struct email_key_mapping {
   char* email_domain;
   char* key_url_prefix;
-} email_key_mapping;
-
+};
 struct grpc_jwt_verifier {
   email_key_mapping* mappings;
   size_t num_mappings; /* Should be very few, linear search ok. */
@@ -418,7 +413,7 @@ static Json json_from_http(const grpc_httpcli_response* response) {
   }
   grpc_error* error = GRPC_ERROR_NONE;
   Json json = Json::Parse(
-      grpc_core::StringView(response->body, response->body_length), &error);
+      absl::string_view(response->body, response->body_length), &error);
   if (error != GRPC_ERROR_NONE) {
     gpr_log(GPR_ERROR, "Invalid JSON found in response.");
     return Json();  // JSON null
index d448386..66ddbf2 100644 (file)
@@ -71,7 +71,7 @@ gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims* claims);
 
 typedef struct grpc_jwt_verifier grpc_jwt_verifier;
 
-typedef struct {
+struct grpc_jwt_verifier_email_domain_key_url_mapping {
   /* The email domain is the part after the @ sign. */
   const char* email_domain;
 
@@ -79,8 +79,7 @@ typedef struct {
      https://<key_url_prefix>/<issuer_email>
      Therefore the key_url_prefix must NOT contain https://. */
   const char* key_url_prefix;
-} grpc_jwt_verifier_email_domain_key_url_mapping;
-
+};
 /* Globals to control the verifier. Not thread-safe. */
 extern gpr_timespec grpc_jwt_verifier_clock_skew;
 extern grpc_millis grpc_jwt_verifier_max_delay;
index c922d35..550aa0c 100644 (file)
@@ -23,6 +23,9 @@
 
 #include <string.h>
 
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/grpc_security.h>
 #include <grpc/impl/codegen/slice.h>
 #include <grpc/slice.h>
@@ -32,7 +35,6 @@
 
 #include "absl/strings/str_format.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/load_file.h"
@@ -522,12 +524,10 @@ namespace grpc_core {
 
 namespace {
 
-void MaybeAddToBody(gpr_strvec* body_strvec, const char* field_name,
-                    const char* field) {
+void MaybeAddToBody(const char* field_name, const char* field,
+                    std::vector<std::string>* body) {
   if (field == nullptr || strlen(field) == 0) return;
-  char* new_query;
-  gpr_asprintf(&new_query, "&%s=%s", field_name, field);
-  gpr_strvec_add(body_strvec, new_query);
+  body->push_back(absl::StrFormat("&%s=%s", field_name, field));
 }
 
 grpc_error* LoadTokenFile(const char* path, gpr_slice* token) {
@@ -607,20 +607,18 @@ class StsTokenFetcherCredentials
 
   grpc_error* FillBody(char** body, size_t* body_length) {
     *body = nullptr;
-    gpr_strvec body_strvec;
-    gpr_strvec_init(&body_strvec);
+    std::vector<std::string> body_parts;
     grpc_slice subject_token = grpc_empty_slice();
     grpc_slice actor_token = grpc_empty_slice();
     grpc_error* err = GRPC_ERROR_NONE;
 
-    auto cleanup = [&body, &body_length, &body_strvec, &subject_token,
+    auto cleanup = [&body, &body_length, &body_parts, &subject_token,
                     &actor_token, &err]() {
       if (err == GRPC_ERROR_NONE) {
-        *body = gpr_strvec_flatten(&body_strvec, body_length);
-      } else {
-        gpr_free(*body);
+        std::string body_str = absl::StrJoin(body_parts, "");
+        *body = gpr_strdup(body_str.c_str());
+        *body_length = body_str.size();
       }
-      gpr_strvec_destroy(&body_strvec);
       grpc_slice_unref_internal(subject_token);
       grpc_slice_unref_internal(actor_token);
       return err;
@@ -628,23 +626,23 @@ class StsTokenFetcherCredentials
 
     err = LoadTokenFile(subject_token_path_.get(), &subject_token);
     if (err != GRPC_ERROR_NONE) return cleanup();
-    gpr_asprintf(
-        body, GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING,
+    body_parts.push_back(absl::StrFormat(
+        GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING,
         reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(subject_token)),
-        subject_token_type_.get());
-    gpr_strvec_add(&body_strvec, *body);
-    MaybeAddToBody(&body_strvec, "resource", resource_.get());
-    MaybeAddToBody(&body_strvec, "audience", audience_.get());
-    MaybeAddToBody(&body_strvec, "scope", scope_.get());
-    MaybeAddToBody(&body_strvec, "requested_token_type",
-                   requested_token_type_.get());
+        subject_token_type_.get()));
+    MaybeAddToBody("resource", resource_.get(), &body_parts);
+    MaybeAddToBody("audience", audience_.get(), &body_parts);
+    MaybeAddToBody("scope", scope_.get(), &body_parts);
+    MaybeAddToBody("requested_token_type", requested_token_type_.get(),
+                   &body_parts);
     if ((actor_token_path_ != nullptr) && *actor_token_path_ != '\0') {
       err = LoadTokenFile(actor_token_path_.get(), &actor_token);
       if (err != GRPC_ERROR_NONE) return cleanup();
       MaybeAddToBody(
-          &body_strvec, "actor_token",
-          reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(actor_token)));
-      MaybeAddToBody(&body_strvec, "actor_token_type", actor_token_type_.get());
+          "actor_token",
+          reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(actor_token)),
+          &body_parts);
+      MaybeAddToBody("actor_token_type", actor_token_type_.get(), &body_parts);
     }
     return cleanup();
   }
@@ -669,7 +667,7 @@ grpc_error* ValidateStsCredentialsOptions(
     void operator()(grpc_uri* uri) { grpc_uri_destroy(uri); }
   };
   *sts_url_out = nullptr;
-  InlinedVector<grpc_error*, 3> error_list;
+  absl::InlinedVector<grpc_error*, 3> error_list;
   std::unique_ptr<grpc_uri, GrpcUriDeleter> sts_url(
       options->token_exchange_service_uri != nullptr
           ? grpc_uri_parse(options->token_exchange_service_uri, false)
index 9065da4..2a9b37e 100644 (file)
   "s&subject_token_type=%s"
 
 // auth_refresh_token parsing.
-typedef struct {
+struct grpc_auth_refresh_token {
   const char* type;
   char* client_id;
   char* client_secret;
   char* refresh_token;
-} grpc_auth_refresh_token;
-
+};
 /// Returns 1 if the object is valid, 0 otherwise.
 int grpc_auth_refresh_token_is_valid(
     const grpc_auth_refresh_token* refresh_token);
index c411fb2..a5f032a 100644 (file)
@@ -23,7 +23,8 @@
 
 #include <grpc/grpc_security.h>
 
-#include "src/core/lib/gprpp/inlined_vector.h"
+#include "absl/container/inlined_vector.h"
+
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/security/security_connector/ssl_utils.h"
 
@@ -44,8 +45,7 @@ struct grpc_tls_error_details
 struct grpc_tls_key_materials_config
     : public grpc_core::RefCounted<grpc_tls_key_materials_config> {
  public:
-  typedef grpc_core::InlinedVector<grpc_core::PemKeyCertPair, 1>
-      PemKeyCertPairList;
+  typedef absl::InlinedVector<grpc_core::PemKeyCertPair, 1> PemKeyCertPairList;
 
   /** Getters for member fields. **/
   const char* pem_root_certs() const { return pem_root_certs_.get(); }
index 6bfe6ea..47c357f 100644 (file)
@@ -111,7 +111,7 @@ class grpc_alts_channel_security_connector final
     return strcmp(target_name_, other->target_name_);
   }
 
-  bool check_call_host(grpc_core::StringView host,
+  bool check_call_host(absl::string_view host,
                        grpc_auth_context* /*auth_context*/,
                        grpc_closure* /*on_call_host_checked*/,
                        grpc_error** error) override {
index 7a81e68..f0f515c 100644 (file)
@@ -103,20 +103,20 @@ class grpc_fake_channel_security_connector final
         tsi_create_fake_handshaker(/*is_client=*/true), this, args));
   }
 
-  bool check_call_host(grpc_core::StringView host,
+  bool check_call_host(absl::string_view host,
                        grpc_auth_context* /*auth_context*/,
                        grpc_closure* /*on_call_host_checked*/,
                        grpc_error** /*error*/) override {
-    grpc_core::StringView authority_hostname;
-    grpc_core::StringView authority_ignored_port;
-    grpc_core::StringView target_hostname;
-    grpc_core::StringView target_ignored_port;
+    absl::string_view authority_hostname;
+    absl::string_view authority_ignored_port;
+    absl::string_view target_hostname;
+    absl::string_view target_ignored_port;
     grpc_core::SplitHostPort(host, &authority_hostname,
                              &authority_ignored_port);
     grpc_core::SplitHostPort(target_, &target_hostname, &target_ignored_port);
     if (target_name_override_ != nullptr) {
-      grpc_core::StringView fake_security_target_name_override_hostname;
-      grpc_core::StringView fake_security_target_name_override_ignored_port;
+      absl::string_view fake_security_target_name_override_hostname;
+      absl::string_view fake_security_target_name_override_ignored_port;
       grpc_core::SplitHostPort(
           target_name_override_, &fake_security_target_name_override_hostname,
           &fake_security_target_name_override_ignored_port);
index e97773f..f7c6c2c 100644 (file)
@@ -34,6 +34,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -41,7 +43,6 @@
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gprpp/global_config.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/iomgr/load_file.h"
 
 GPR_GLOBAL_CONFIG_DEFINE_STRING(grpc_system_ssl_roots_dir, "",
@@ -100,7 +101,7 @@ grpc_slice CreateRootCertsBundle(const char* certs_directory) {
     char path[MAXPATHLEN];
     off_t size;
   };
-  InlinedVector<FileData, 2> roots_filenames;
+  absl::InlinedVector<FileData, 2> roots_filenames;
   size_t total_bundle_size = 0;
   struct dirent* directory_entry;
   while ((directory_entry = readdir(ca_directory)) != nullptr) {
index f2e4e0c..585c170 100644 (file)
@@ -181,7 +181,7 @@ class grpc_local_channel_security_connector final
                      creds->connect_type());
   }
 
-  bool check_call_host(grpc_core::StringView host,
+  bool check_call_host(absl::string_view host,
                        grpc_auth_context* /*auth_context*/,
                        grpc_closure* /*on_call_host_checked*/,
                        grpc_error** error) override {
index 32033ec..0f1ac64 100644 (file)
@@ -98,7 +98,7 @@ class grpc_channel_security_connector : public grpc_security_connector {
   /// Returns true if completed synchronously, in which case \a error will
   /// be set to indicate the result.  Otherwise, \a on_call_host_checked
   /// will be invoked when complete.
-  virtual bool check_call_host(grpc_core::StringView host,
+  virtual bool check_call_host(absl::string_view host,
                                grpc_auth_context* auth_context,
                                grpc_closure* on_call_host_checked,
                                grpc_error** error) = 0;
index 1318072..762069a 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <stdbool.h>
 
+#include "absl/strings/string_view.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -72,14 +74,13 @@ class grpc_ssl_channel_security_connector final
       : grpc_channel_security_connector(GRPC_SSL_URL_SCHEME,
                                         std::move(channel_creds),
                                         std::move(request_metadata_creds)),
-        overridden_target_name_(overridden_target_name == nullptr
-                                    ? nullptr
-                                    : gpr_strdup(overridden_target_name)),
+        overridden_target_name_(
+            overridden_target_name == nullptr ? "" : overridden_target_name),
         verify_options_(&config->verify_options) {
-    grpc_core::StringView host;
-    grpc_core::StringView port;
+    absl::string_view host;
+    absl::string_view port;
     grpc_core::SplitHostPort(target_name, &host, &port);
-    target_name_ = grpc_core::StringViewToCString(host);
+    target_name_ = std::string(host);
   }
 
   ~grpc_ssl_channel_security_connector() override {
@@ -124,8 +125,8 @@ class grpc_ssl_channel_security_connector final
     tsi_handshaker* tsi_hs = nullptr;
     tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
         client_handshaker_factory_,
-        overridden_target_name_ != nullptr ? overridden_target_name_.get()
-                                           : target_name_.get(),
+        overridden_target_name_.empty() ? target_name_.c_str()
+                                        : overridden_target_name_.c_str(),
         &tsi_hs);
     if (result != TSI_OK) {
       gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
@@ -139,9 +140,9 @@ class grpc_ssl_channel_security_connector final
   void check_peer(tsi_peer peer, grpc_endpoint* /*ep*/,
                   grpc_core::RefCountedPtr<grpc_auth_context>* auth_context,
                   grpc_closure* on_peer_checked) override {
-    const char* target_name = overridden_target_name_ != nullptr
-                                  ? overridden_target_name_.get()
-                                  : target_name_.get();
+    const char* target_name = overridden_target_name_.empty()
+                                  ? target_name_.c_str()
+                                  : overridden_target_name_.c_str();
     grpc_error* error = ssl_check_peer(target_name, &peer, auth_context);
     if (error == GRPC_ERROR_NONE &&
         verify_options_->verify_peer_callback != nullptr) {
@@ -176,24 +177,17 @@ class grpc_ssl_channel_security_connector final
         reinterpret_cast<const grpc_ssl_channel_security_connector*>(other_sc);
     int c = channel_security_connector_cmp(other);
     if (c != 0) return c;
-    c = strcmp(target_name_.get(), other->target_name_.get());
+    c = target_name_.compare(other->target_name_);
     if (c != 0) return c;
-    return (overridden_target_name_ == nullptr ||
-            other->overridden_target_name_ == nullptr)
-               ? GPR_ICMP(overridden_target_name_.get(),
-                          other->overridden_target_name_.get())
-               : strcmp(overridden_target_name_.get(),
-                        other->overridden_target_name_.get());
+    return overridden_target_name_.compare(other->overridden_target_name_);
   }
 
-  bool check_call_host(grpc_core::StringView host,
-                       grpc_auth_context* auth_context,
+  bool check_call_host(absl::string_view host, grpc_auth_context* auth_context,
                        grpc_closure* /*on_call_host_checked*/,
                        grpc_error** error) override {
-    return grpc_ssl_check_call_host(
-        host, target_name_.get(),
-        overridden_target_name_ != nullptr ? overridden_target_name_.get() : "",
-        auth_context, error);
+    return grpc_ssl_check_call_host(host, target_name_.c_str(),
+                                    overridden_target_name_.c_str(),
+                                    auth_context, error);
   }
 
   void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/,
@@ -203,8 +197,8 @@ class grpc_ssl_channel_security_connector final
 
  private:
   tsi_ssl_client_handshaker_factory* client_handshaker_factory_;
-  grpc_core::UniquePtr<char> target_name_;
-  grpc_core::UniquePtr<char> overridden_target_name_;
+  std::string target_name_;
+  std::string overridden_target_name_;
   const verify_peer_options* verify_options_;
 };
 
index 70e26e3..f11e819 100644 (file)
 #include "src/core/tsi/ssl_transport_security.h"
 #include "src/core/tsi/transport_security_interface.h"
 
-typedef struct {
+struct grpc_ssl_config {
   tsi_ssl_pem_key_cert_pair* pem_key_cert_pair;
   char* pem_root_certs;
   verify_peer_options verify_options;
-} grpc_ssl_config;
-
+};
 /* Creates an SSL channel_security_connector.
    - request_metadata_creds is the credentials object which metadata
      will be sent with each request. This parameter can be NULL.
@@ -57,14 +56,13 @@ grpc_ssl_channel_security_connector_create(
     tsi_ssl_session_cache* ssl_session_cache);
 
 /* Config for ssl servers. */
-typedef struct {
+struct grpc_ssl_server_config {
   tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = nullptr;
   size_t num_key_cert_pairs = 0;
   char* pem_root_certs = nullptr;
   grpc_ssl_client_certificate_request_type client_certificate_request =
       GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE;
-} grpc_ssl_server_config;
-
+};
 /* Creates an SSL server_security_connector.
    - config is the SSL config to be used for the SSL channel establishment.
    - sc is a pointer on the connector to be created.
index 2a3f300..664f3a1 100644 (file)
@@ -25,6 +25,8 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+#include <vector>
+
 #include "src/core/ext/transport/chttp2/alpn/alpn.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gpr/string.h"
@@ -149,7 +151,7 @@ grpc_error* grpc_ssl_check_alpn(const tsi_peer* peer) {
   return GRPC_ERROR_NONE;
 }
 
-grpc_error* grpc_ssl_check_peer_name(grpc_core::StringView peer_name,
+grpc_error* grpc_ssl_check_peer_name(absl::string_view peer_name,
                                      const tsi_peer* peer) {
   /* Check the peer name if specified. */
   if (!peer_name.empty() && !grpc_ssl_host_matches_name(peer, peer_name)) {
@@ -163,9 +165,9 @@ grpc_error* grpc_ssl_check_peer_name(grpc_core::StringView peer_name,
   return GRPC_ERROR_NONE;
 }
 
-bool grpc_ssl_check_call_host(grpc_core::StringView host,
-                              grpc_core::StringView target_name,
-                              grpc_core::StringView overridden_target_name,
+bool grpc_ssl_check_call_host(absl::string_view host,
+                              absl::string_view target_name,
+                              absl::string_view overridden_target_name,
                               grpc_auth_context* auth_context,
                               grpc_error** error) {
   grpc_security_status status = GRPC_SECURITY_ERROR;
@@ -197,29 +199,50 @@ const char** grpc_fill_alpn_protocol_strings(size_t* num_alpn_protocols) {
 }
 
 int grpc_ssl_host_matches_name(const tsi_peer* peer,
-                               grpc_core::StringView peer_name) {
-  grpc_core::StringView allocated_name;
-  grpc_core::StringView ignored_port;
+                               absl::string_view peer_name) {
+  absl::string_view allocated_name;
+  absl::string_view ignored_port;
   grpc_core::SplitHostPort(peer_name, &allocated_name, &ignored_port);
   if (allocated_name.empty()) return 0;
 
   // IPv6 zone-id should not be included in comparisons.
   const size_t zone_id = allocated_name.find('%');
-  if (zone_id != grpc_core::StringView::npos) {
+  if (zone_id != absl::string_view::npos) {
     allocated_name.remove_suffix(allocated_name.size() - zone_id);
   }
   return tsi_ssl_peer_matches_name(peer, allocated_name);
 }
 
-int grpc_ssl_cmp_target_name(
-    grpc_core::StringView target_name, grpc_core::StringView other_target_name,
-    grpc_core::StringView overridden_target_name,
-    grpc_core::StringView other_overridden_target_name) {
+int grpc_ssl_cmp_target_name(absl::string_view target_name,
+                             absl::string_view other_target_name,
+                             absl::string_view overridden_target_name,
+                             absl::string_view other_overridden_target_name) {
   int c = target_name.compare(other_target_name);
   if (c != 0) return c;
   return overridden_target_name.compare(other_overridden_target_name);
 }
 
+static bool IsSpiffeId(absl::string_view uri) {
+  // Return false without logging for a non-spiffe uri scheme.
+  if (!absl::StartsWith(uri, "spiffe://")) {
+    return false;
+  };
+  if (uri.size() > 2048) {
+    gpr_log(GPR_INFO, "Invalid SPIFFE ID: ID longer than 2048 bytes.");
+    return false;
+  }
+  std::vector<absl::string_view> splits = absl::StrSplit(uri, '/');
+  if (splits.size() < 4 || splits[3] == "") {
+    gpr_log(GPR_INFO, "Invalid SPIFFE ID: workload id is empty.");
+    return false;
+  }
+  if (splits[2].size() > 255) {
+    gpr_log(GPR_INFO, "Invalid SPIFFE ID: domain longer than 255 characters.");
+    return false;
+  }
+  return true;
+}
+
 grpc_core::RefCountedPtr<grpc_auth_context> grpc_ssl_peer_to_auth_context(
     const tsi_peer* peer, const char* transport_security_type) {
   size_t i;
@@ -232,6 +255,9 @@ grpc_core::RefCountedPtr<grpc_auth_context> grpc_ssl_peer_to_auth_context(
   grpc_auth_context_add_cstring_property(
       ctx.get(), GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
       transport_security_type);
+  const char* spiffe_data = nullptr;
+  size_t spiffe_length = 0;
+  int spiffe_id_count = 0;
   for (i = 0; i < peer->property_count; i++) {
     const tsi_peer_property* prop = &peer->properties[i];
     if (prop->name == nullptr) continue;
@@ -263,12 +289,30 @@ grpc_core::RefCountedPtr<grpc_auth_context> grpc_ssl_peer_to_auth_context(
       grpc_auth_context_add_property(
           ctx.get(), GRPC_TRANSPORT_SECURITY_LEVEL_PROPERTY_NAME,
           prop->value.data, prop->value.length);
+    } else if (strcmp(prop->name, TSI_X509_URI_PEER_PROPERTY) == 0) {
+      absl::string_view spiffe_id(prop->value.data, prop->value.length);
+      if (IsSpiffeId(spiffe_id)) {
+        spiffe_data = prop->value.data;
+        spiffe_length = prop->value.length;
+        spiffe_id_count += 1;
+      }
     }
   }
   if (peer_identity_property_name != nullptr) {
     GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(
                    ctx.get(), peer_identity_property_name) == 1);
   }
+  // SPIFFE ID should be unique. If we find more than one SPIFFE IDs, we log
+  // the error without returning the error.
+  if (spiffe_id_count > 1) {
+    gpr_log(GPR_INFO, "Invalid SPIFFE ID: SPIFFE ID should be unique.");
+  }
+  if (spiffe_id_count == 1) {
+    GPR_ASSERT(spiffe_length > 0);
+    GPR_ASSERT(spiffe_data != nullptr);
+    grpc_auth_context_add_property(ctx.get(), GRPC_PEER_SPIFFE_ID_PROPERTY_NAME,
+                                   spiffe_data, spiffe_length);
+  }
   return ctx;
 }
 
@@ -314,6 +358,9 @@ tsi_peer grpc_shallow_peer_from_ssl_auth_context(
                  0) {
         add_shallow_auth_property_to_peer(&peer, prop,
                                           TSI_X509_PEM_CERT_CHAIN_PROPERTY);
+      } else if (strcmp(prop->name, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME) == 0) {
+        add_shallow_auth_property_to_peer(&peer, prop,
+                                          TSI_X509_URI_PEER_PROPERTY);
       }
     }
   }
index c521b1f..b7522e8 100644 (file)
 
 #include <stdbool.h>
 
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+
 #include <grpc/grpc_security.h>
 #include <grpc/slice_buffer.h>
 
 #include "src/core/lib/gprpp/global_config.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/gprpp/string_view.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/security/security_connector/security_connector.h"
 #include "src/core/lib/security/security_connector/ssl_utils_config.h"
 grpc_error* grpc_ssl_check_alpn(const tsi_peer* peer);
 
 /* Check peer name information returned from SSL handshakes. */
-grpc_error* grpc_ssl_check_peer_name(grpc_core::StringView peer_name,
+grpc_error* grpc_ssl_check_peer_name(absl::string_view peer_name,
                                      const tsi_peer* peer);
 /* Compare targer_name information extracted from SSL security connectors. */
-int grpc_ssl_cmp_target_name(
-    grpc_core::StringView target_name, grpc_core::StringView other_target_name,
-    grpc_core::StringView overridden_target_name,
-    grpc_core::StringView other_overridden_target_name);
+int grpc_ssl_cmp_target_name(absl::string_view target_name,
+                             absl::string_view other_target_name,
+                             absl::string_view overridden_target_name,
+                             absl::string_view other_overridden_target_name);
 /* Check the host that will be set for a call is acceptable.*/
-bool grpc_ssl_check_call_host(grpc_core::StringView host,
-                              grpc_core::StringView target_name,
-                              grpc_core::StringView overridden_target_name,
+bool grpc_ssl_check_call_host(absl::string_view host,
+                              absl::string_view target_name,
+                              absl::string_view overridden_target_name,
                               grpc_auth_context* auth_context,
                               grpc_error** error);
 /* Return HTTP2-compliant cipher suites that gRPC accepts by default. */
@@ -101,7 +103,7 @@ tsi_peer grpc_shallow_peer_from_ssl_auth_context(
     const grpc_auth_context* auth_context);
 void grpc_shallow_peer_destruct(tsi_peer* peer);
 int grpc_ssl_host_matches_name(const tsi_peer* peer,
-                               grpc_core::StringView peer_name);
+                               absl::string_view peer_name);
 
 /* --- Default SSL Root Store. --- */
 namespace grpc_core {
index ca361aa..6cc2d84 100644 (file)
@@ -23,6 +23,8 @@
 #include <stdbool.h>
 #include <string.h>
 
+#include "absl/strings/string_view.h"
+
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -144,15 +146,14 @@ TlsChannelSecurityConnector::TlsChannelSecurityConnector(
     : grpc_channel_security_connector(GRPC_SSL_URL_SCHEME,
                                       std::move(channel_creds),
                                       std::move(request_metadata_creds)),
-      overridden_target_name_(overridden_target_name == nullptr
-                                  ? nullptr
-                                  : gpr_strdup(overridden_target_name)) {
+      overridden_target_name_(
+          overridden_target_name == nullptr ? "" : overridden_target_name) {
   key_materials_config_ = grpc_tls_key_materials_config_create()->Ref();
   check_arg_ = ServerAuthorizationCheckArgCreate(this);
-  grpc_core::StringView host;
-  grpc_core::StringView port;
+  absl::string_view host;
+  absl::string_view port;
   grpc_core::SplitHostPort(target_name, &host, &port);
-  target_name_ = grpc_core::StringViewToCString(host);
+  target_name_ = std::string(host);
 }
 
 TlsChannelSecurityConnector::~TlsChannelSecurityConnector() {
@@ -176,8 +177,8 @@ void TlsChannelSecurityConnector::add_handshakers(
   tsi_handshaker* tsi_hs = nullptr;
   tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
       client_handshaker_factory_,
-      overridden_target_name_ != nullptr ? overridden_target_name_.get()
-                                         : target_name_.get(),
+      overridden_target_name_.empty() ? target_name_.c_str()
+                                      : overridden_target_name_.c_str(),
       &tsi_hs);
   if (result != TSI_OK) {
     gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
@@ -192,9 +193,9 @@ void TlsChannelSecurityConnector::check_peer(
     tsi_peer peer, grpc_endpoint* /*ep*/,
     grpc_core::RefCountedPtr<grpc_auth_context>* auth_context,
     grpc_closure* on_peer_checked) {
-  const char* target_name = overridden_target_name_ != nullptr
-                                ? overridden_target_name_.get()
-                                : target_name_.get();
+  const char* target_name = overridden_target_name_.empty()
+                                ? target_name_.c_str()
+                                : overridden_target_name_.c_str();
   grpc_error* error = grpc_ssl_check_alpn(&peer);
   if (error != GRPC_ERROR_NONE) {
     grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
@@ -271,16 +272,16 @@ int TlsChannelSecurityConnector::cmp(
   if (c != 0) {
     return c;
   }
-  return grpc_ssl_cmp_target_name(target_name_.get(), other->target_name_.get(),
-                                  overridden_target_name_.get(),
-                                  other->overridden_target_name_.get());
+  return grpc_ssl_cmp_target_name(
+      target_name_.c_str(), other->target_name_.c_str(),
+      overridden_target_name_.c_str(), other->overridden_target_name_.c_str());
 }
 
 bool TlsChannelSecurityConnector::check_call_host(
-    grpc_core::StringView host, grpc_auth_context* auth_context,
+    absl::string_view host, grpc_auth_context* auth_context,
     grpc_closure* on_call_host_checked, grpc_error** error) {
-  return grpc_ssl_check_call_host(host, target_name_.get(),
-                                  overridden_target_name_.get(), auth_context,
+  return grpc_ssl_check_call_host(host, target_name_.c_str(),
+                                  overridden_target_name_.c_str(), auth_context,
                                   error);
 }
 
index 4ac831f..db5c87b 100644 (file)
@@ -57,8 +57,7 @@ class TlsChannelSecurityConnector final
 
   int cmp(const grpc_security_connector* other_sc) const override;
 
-  bool check_call_host(grpc_core::StringView host,
-                       grpc_auth_context* auth_context,
+  bool check_call_host(absl::string_view host, grpc_auth_context* auth_context,
                        grpc_closure* on_call_host_checked,
                        grpc_error** error) override;
 
@@ -98,8 +97,8 @@ class TlsChannelSecurityConnector final
 
   grpc_core::Mutex mu_;
   grpc_closure* on_peer_checked_;
-  grpc_core::UniquePtr<char> target_name_;
-  grpc_core::UniquePtr<char> overridden_target_name_;
+  std::string target_name_;
+  std::string overridden_target_name_;
   tsi_ssl_client_handshaker_factory* client_handshaker_factory_ = nullptr;
   grpc_tls_server_authorization_check_arg* check_arg_;
   grpc_core::RefCountedPtr<grpc_tls_key_materials_config> key_materials_config_;
index c3658a9..ed24b4f 100644 (file)
@@ -379,8 +379,7 @@ static void client_auth_start_transport_stream_op_batch(
       GRPC_CALL_STACK_REF(calld->owning_call, "check_call_host");
       GRPC_CLOSURE_INIT(&calld->async_result_closure, on_host_checked, batch,
                         grpc_schedule_on_exec_ctx);
-      grpc_core::StringView call_host(
-          grpc_core::StringViewFromSlice(calld->host));
+      absl::string_view call_host(grpc_core::StringViewFromSlice(calld->host));
       grpc_error* error = GRPC_ERROR_NONE;
       if (chand->security_connector->check_call_host(
               call_host, chand->auth_context.get(),
index 0feef16..b41628c 100644 (file)
@@ -52,11 +52,10 @@ typedef struct slice_shard {
 
 static slice_shard g_shards[SHARD_COUNT];
 
-typedef struct {
+struct static_metadata_hash_ent {
   uint32_t hash;
   uint32_t idx;
-} static_metadata_hash_ent;
-
+};
 static static_metadata_hash_ent
     static_metadata_hash[4 * GRPC_STATIC_MDSTR_COUNT];
 static uint32_t max_static_metadata_hash_probe;
index b203a16..d9a4253 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <cstring>
 
+#include "absl/strings/string_view.h"
+
 #include <grpc/slice.h>
 
 #include "src/core/lib/gpr/murmur_hash.h"
@@ -186,6 +188,13 @@ struct InternedSlice : public ManagedMemorySlice {
   explicit InternedSlice(InternedSliceRefcount* s);
 };
 
+// Converts grpc_slice to absl::string_view.
+inline absl::string_view StringViewFromSlice(const grpc_slice& slice) {
+  return absl::string_view(
+      reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(slice)),
+      GRPC_SLICE_LENGTH(slice));
+}
+
 }  // namespace grpc_core
 
 #endif /* GRPC_CORE_LIB_SLICE_SLICE_UTILS_H */
index fcebe9b..81154b8 100644 (file)
@@ -670,12 +670,11 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call* c,
   return GRPC_CALL_OK;
 }
 
-typedef struct {
+struct cancel_state {
   grpc_call* call;
   grpc_closure start_batch;
   grpc_closure finish_batch;
-} cancel_state;
-
+};
 // The on_complete callback used when sending a cancel_stream batch down
 // the filter stack.  Yields the call combiner when the batch is done.
 static void done_termination(void* arg, grpc_error* /*error*/) {
index 23c344a..eac5513 100644 (file)
 
 #include <inttypes.h>
 
+#include <vector>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 
-static void add_metadata(gpr_strvec* b, const grpc_metadata* md, size_t count) {
-  size_t i;
+static void add_metadata(const grpc_metadata* md, size_t count,
+                         std::vector<std::string>* b) {
   if (md == nullptr) {
-    gpr_strvec_add(b, gpr_strdup("(nil)"));
+    b->push_back("(nil)");
     return;
   }
-  for (i = 0; i < count; i++) {
-    gpr_strvec_add(b, gpr_strdup("\nkey="));
-    gpr_strvec_add(b, grpc_slice_to_c_string(md[i].key));
-
-    gpr_strvec_add(b, gpr_strdup(" value="));
-    gpr_strvec_add(b,
-                   grpc_dump_slice(md[i].value, GPR_DUMP_HEX | GPR_DUMP_ASCII));
+  for (size_t i = 0; i < count; i++) {
+    b->push_back("\nkey=");
+    b->push_back(std::string(grpc_core::StringViewFromSlice(md[i].key)));
+    b->push_back(" value=");
+    char* dump = grpc_dump_slice(md[i].value, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+    b->push_back(dump);
+    gpr_free(dump);
   }
 }
 
-char* grpc_op_string(const grpc_op* op) {
-  char* tmp;
-  char* out;
-
-  gpr_strvec b;
-  gpr_strvec_init(&b);
-
+static std::string grpc_op_string(const grpc_op* op) {
+  std::vector<std::string> parts;
   switch (op->op) {
     case GRPC_OP_SEND_INITIAL_METADATA:
-      gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA"));
-      add_metadata(&b, op->data.send_initial_metadata.metadata,
-                   op->data.send_initial_metadata.count);
+      parts.push_back("SEND_INITIAL_METADATA");
+      add_metadata(op->data.send_initial_metadata.metadata,
+                   op->data.send_initial_metadata.count, &parts);
       break;
     case GRPC_OP_SEND_MESSAGE:
-      gpr_asprintf(&tmp, "SEND_MESSAGE ptr=%p",
-                   op->data.send_message.send_message);
-      gpr_strvec_add(&b, tmp);
+      parts.push_back(absl::StrFormat("SEND_MESSAGE ptr=%p",
+                                      op->data.send_message.send_message));
       break;
     case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
-      gpr_strvec_add(&b, gpr_strdup("SEND_CLOSE_FROM_CLIENT"));
+      parts.push_back("SEND_CLOSE_FROM_CLIENT");
       break;
     case GRPC_OP_SEND_STATUS_FROM_SERVER:
-      gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=",
-                   op->data.send_status_from_server.status);
-      gpr_strvec_add(&b, tmp);
+      parts.push_back(
+          absl::StrFormat("SEND_STATUS_FROM_SERVER status=%d details=",
+                          op->data.send_status_from_server.status));
       if (op->data.send_status_from_server.status_details != nullptr) {
-        gpr_strvec_add(&b, grpc_dump_slice(
-                               *op->data.send_status_from_server.status_details,
-                               GPR_DUMP_ASCII));
+        char* dump = grpc_dump_slice(
+            *op->data.send_status_from_server.status_details, GPR_DUMP_ASCII);
+        parts.push_back(dump);
+        gpr_free(dump);
       } else {
-        gpr_strvec_add(&b, gpr_strdup("(null)"));
+        parts.push_back("(null)");
       }
-      add_metadata(&b, op->data.send_status_from_server.trailing_metadata,
-                   op->data.send_status_from_server.trailing_metadata_count);
+      add_metadata(op->data.send_status_from_server.trailing_metadata,
+                   op->data.send_status_from_server.trailing_metadata_count,
+                   &parts);
       break;
     case GRPC_OP_RECV_INITIAL_METADATA:
-      gpr_asprintf(&tmp, "RECV_INITIAL_METADATA ptr=%p",
-                   op->data.recv_initial_metadata.recv_initial_metadata);
-      gpr_strvec_add(&b, tmp);
+      parts.push_back(absl::StrFormat(
+          "RECV_INITIAL_METADATA ptr=%p",
+          op->data.recv_initial_metadata.recv_initial_metadata));
       break;
     case GRPC_OP_RECV_MESSAGE:
-      gpr_asprintf(&tmp, "RECV_MESSAGE ptr=%p",
-                   op->data.recv_message.recv_message);
-      gpr_strvec_add(&b, tmp);
+      parts.push_back(absl::StrFormat("RECV_MESSAGE ptr=%p",
+                                      op->data.recv_message.recv_message));
       break;
     case GRPC_OP_RECV_STATUS_ON_CLIENT:
-      gpr_asprintf(&tmp,
-                   "RECV_STATUS_ON_CLIENT metadata=%p status=%p details=%p",
-                   op->data.recv_status_on_client.trailing_metadata,
-                   op->data.recv_status_on_client.status,
-                   op->data.recv_status_on_client.status_details);
-      gpr_strvec_add(&b, tmp);
+      parts.push_back(absl::StrFormat(
+          "RECV_STATUS_ON_CLIENT metadata=%p status=%p details=%p",
+          op->data.recv_status_on_client.trailing_metadata,
+          op->data.recv_status_on_client.status,
+          op->data.recv_status_on_client.status_details));
       break;
     case GRPC_OP_RECV_CLOSE_ON_SERVER:
-      gpr_asprintf(&tmp, "RECV_CLOSE_ON_SERVER cancelled=%p",
-                   op->data.recv_close_on_server.cancelled);
-      gpr_strvec_add(&b, tmp);
+      parts.push_back(absl::StrFormat("RECV_CLOSE_ON_SERVER cancelled=%p",
+                                      op->data.recv_close_on_server.cancelled));
   }
-  out = gpr_strvec_flatten(&b, nullptr);
-  gpr_strvec_destroy(&b);
-
-  return out;
+  return absl::StrJoin(parts, "");
 }
 
 void grpc_call_log_batch(const char* file, int line, gpr_log_severity severity,
                          const grpc_op* ops, size_t nops) {
-  char* tmp;
-  size_t i;
-  for (i = 0; i < nops; i++) {
-    tmp = grpc_op_string(&ops[i]);
-    gpr_log(file, line, severity, "ops[%" PRIuPTR "]: %s", i, tmp);
-    gpr_free(tmp);
+  for (size_t i = 0; i < nops; i++) {
+    gpr_log(file, line, severity, "ops[%" PRIuPTR "]: %s", i,
+            grpc_op_string(&ops[i]).c_str());
   }
 }
index 3a359a1..bcfa5e6 100644 (file)
@@ -329,6 +329,7 @@ char* grpc_channel_get_target(grpc_channel* channel) {
 
 void grpc_channel_get_info(grpc_channel* channel,
                            const grpc_channel_info* channel_info) {
+  grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
   grpc_core::ExecCtx exec_ctx;
   grpc_channel_element* elem =
       grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
@@ -336,6 +337,7 @@ void grpc_channel_get_info(grpc_channel* channel,
 }
 
 void grpc_channel_reset_connect_backoff(grpc_channel* channel) {
+  grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
   grpc_core::ExecCtx exec_ctx;
   GRPC_API_TRACE("grpc_channel_reset_connect_backoff(channel=%p)", 1,
                  (channel));
@@ -386,6 +388,7 @@ grpc_call* grpc_channel_create_call(grpc_channel* channel,
                                     grpc_slice method, const grpc_slice* host,
                                     gpr_timespec deadline, void* reserved) {
   GPR_ASSERT(!reserved);
+  grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
   grpc_core::ExecCtx exec_ctx;
   grpc_call* call = grpc_channel_create_call_internal(
       channel, parent_call, propagation_mask, cq, nullptr,
@@ -449,6 +452,7 @@ void* grpc_channel_register_call(grpc_channel* channel, const char* method,
       "grpc_channel_register_call(channel=%p, method=%s, host=%s, reserved=%p)",
       4, (channel, method, host, reserved));
   GPR_ASSERT(!reserved);
+  grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
   grpc_core::ExecCtx exec_ctx;
 
   grpc_core::MutexLock lock(&channel->registration_table->mu);
@@ -481,6 +485,7 @@ grpc_call* grpc_channel_create_registered_call(
        registered_call_handle, deadline.tv_sec, deadline.tv_nsec,
        (int)deadline.clock_type, reserved));
   GPR_ASSERT(!reserved);
+  grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
   grpc_core::ExecCtx exec_ctx;
   grpc_call* call = grpc_channel_create_call_internal(
       channel, parent_call, propagation_mask, completion_queue, nullptr,
@@ -532,6 +537,7 @@ void grpc_channel_destroy_internal(grpc_channel* channel) {
 }
 
 void grpc_channel_destroy(grpc_channel* channel) {
+  grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
   grpc_core::ExecCtx exec_ctx;
   grpc_channel_destroy_internal(channel);
 }
index be02a05..82e5521 100644 (file)
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/completion_queue.h"
 
-typedef struct {
+struct ping_result {
   grpc_closure closure;
   void* tag;
   grpc_completion_queue* cq;
   grpc_cq_completion completion_storage;
-} ping_result;
-
+};
 static void ping_destroy(void* arg, grpc_cq_completion* /*storage*/) {
   gpr_free(arg);
 }
index 60cbb24..a383f78 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
+#include <vector>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/atm.h>
 #include <grpc/support/log.h>
@@ -56,12 +61,11 @@ namespace {
 GPR_TLS_DECL(g_cached_event);
 GPR_TLS_DECL(g_cached_cq);
 
-typedef struct {
+struct plucker {
   grpc_pollset_worker** worker;
   void* tag;
-} plucker;
-
-typedef struct {
+};
+struct cq_poller_vtable {
   bool can_get_pollset;
   bool can_listen;
   size_t (*size)(void);
@@ -72,8 +76,7 @@ typedef struct {
                       grpc_millis deadline);
   void (*shutdown)(grpc_pollset* pollset, grpc_closure* closure);
   void (*destroy)(grpc_pollset* pollset);
-} cq_poller_vtable;
-
+};
 typedef struct non_polling_worker {
   gpr_cv cv;
   bool kicked;
@@ -81,13 +84,12 @@ typedef struct non_polling_worker {
   struct non_polling_worker* prev;
 } non_polling_worker;
 
-typedef struct {
+struct non_polling_poller {
   gpr_mu mu;
   bool kicked_without_poller;
   non_polling_worker* root;
   grpc_closure* shutdown;
-} non_polling_poller;
-
+};
 size_t non_polling_poller_size(void) { return sizeof(non_polling_poller); }
 
 void non_polling_poller_init(grpc_pollset* pollset, gpr_mu** mu) {
@@ -430,15 +432,14 @@ static const cq_vtable g_cq_vtable[] = {
 
 grpc_core::TraceFlag grpc_cq_pluck_trace(false, "queue_pluck");
 
-#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event)      \
-  do {                                                    \
-    if (GRPC_TRACE_FLAG_ENABLED(grpc_api_trace) &&        \
-        (GRPC_TRACE_FLAG_ENABLED(grpc_cq_pluck_trace) ||  \
-         (event)->type != GRPC_QUEUE_TIMEOUT)) {          \
-      char* _ev = grpc_event_string(event);               \
-      gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \
-      gpr_free(_ev);                                      \
-    }                                                     \
+#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event)     \
+  do {                                                   \
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_api_trace) &&       \
+        (GRPC_TRACE_FLAG_ENABLED(grpc_cq_pluck_trace) || \
+         (event)->type != GRPC_QUEUE_TIMEOUT)) {         \
+      gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq,      \
+              grpc_event_string(event).c_str());         \
+    }                                                    \
   } while (0)
 
 static void on_pollset_shutdown_done(void* cq, grpc_error* error);
@@ -874,8 +875,15 @@ static void cq_end_op_for_callback(
     cq_finish_shutdown_callback(cq);
   }
 
+  // If possible, schedule the callback onto an existing thread-local
+  // ApplicationCallbackExecCtx, which is a work queue. This is possible for:
+  // 1. The callback is internally-generated and there is an ACEC available
+  // 2. The callback is marked inlineable and there is an ACEC available
+  // 3. We are already running in a background poller thread (which always has
+  //    an ACEC available at the base of the stack).
   auto* functor = static_cast<grpc_experimental_completion_queue_functor*>(tag);
-  if (internal || functor->inlineable ||
+  if (((internal || functor->inlineable) &&
+       grpc_core::ApplicationCallbackExecCtx::Available()) ||
       grpc_iomgr_is_any_background_poller_thread()) {
     grpc_core::ApplicationCallbackExecCtx::Enqueue(functor,
                                                    (error == GRPC_ERROR_NONE));
@@ -896,15 +904,14 @@ void grpc_cq_end_op(grpc_completion_queue* cq, void* tag, grpc_error* error,
   cq->vtable->end_op(cq, tag, error, done, done_arg, storage, internal);
 }
 
-typedef struct {
+struct cq_is_finished_arg {
   gpr_atm last_seen_things_queued_ever;
   grpc_completion_queue* cq;
   grpc_millis deadline;
   grpc_cq_completion* stolen_completion;
   void* tag; /* for pluck */
   bool first_loop;
-} cq_is_finished_arg;
-
+};
 class ExecCtxNext : public grpc_core::ExecCtx {
  public:
   ExecCtxNext(void* arg) : ExecCtx(0), check_ready_to_finish_arg_(arg) {}
@@ -944,21 +951,14 @@ class ExecCtxNext : public grpc_core::ExecCtx {
 #ifndef NDEBUG
 static void dump_pending_tags(grpc_completion_queue* cq) {
   if (!GRPC_TRACE_FLAG_ENABLED(grpc_trace_pending_tags)) return;
-
-  gpr_strvec v;
-  gpr_strvec_init(&v);
-  gpr_strvec_add(&v, gpr_strdup("PENDING TAGS:"));
+  std::vector<std::string> parts;
+  parts.push_back("PENDING TAGS:");
   gpr_mu_lock(cq->mu);
   for (size_t i = 0; i < cq->outstanding_tag_count; i++) {
-    char* s;
-    gpr_asprintf(&s, " %p", cq->outstanding_tags[i]);
-    gpr_strvec_add(&v, s);
+    parts.push_back(absl::StrFormat(" %p", cq->outstanding_tags[i]));
   }
   gpr_mu_unlock(cq->mu);
-  char* out = gpr_strvec_flatten(&v, nullptr);
-  gpr_strvec_destroy(&v);
-  gpr_log(GPR_DEBUG, "%s", out);
-  gpr_free(out);
+  gpr_log(GPR_DEBUG, "%s", absl::StrJoin(parts, "").c_str());
 }
 #else
 static void dump_pending_tags(grpc_completion_queue* /*cq*/) {}
index d639bae..32d85f7 100644 (file)
 
 #include <stdio.h>
 
+#include <vector>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/byte_buffer.h>
 #include <grpc/support/string_util.h>
 #include "src/core/lib/gpr/string.h"
 
-static void addhdr(gpr_strvec* buf, grpc_event* ev) {
-  char* tmp;
-  gpr_asprintf(&tmp, "tag:%p", ev->tag);
-  gpr_strvec_add(buf, tmp);
+static void addhdr(grpc_event* ev, std::vector<std::string>* buf) {
+  buf->push_back(absl::StrFormat("tag:%p", ev->tag));
 }
 
 static const char* errstr(int success) { return success ? "OK" : "ERROR"; }
 
-static void adderr(gpr_strvec* buf, int success) {
-  char* tmp;
-  gpr_asprintf(&tmp, " %s", errstr(success));
-  gpr_strvec_add(buf, tmp);
+static void adderr(int success, std::vector<std::string>* buf) {
+  buf->push_back(absl::StrFormat(" %s", errstr(success)));
 }
 
-char* grpc_event_string(grpc_event* ev) {
-  char* out;
-  gpr_strvec buf;
-
-  if (ev == nullptr) return gpr_strdup("null");
-
-  gpr_strvec_init(&buf);
-
+std::string grpc_event_string(grpc_event* ev) {
+  if (ev == nullptr) return "null";
+  std::vector<std::string> out;
   switch (ev->type) {
     case GRPC_QUEUE_TIMEOUT:
-      gpr_strvec_add(&buf, gpr_strdup("QUEUE_TIMEOUT"));
+      out.push_back("QUEUE_TIMEOUT");
       break;
     case GRPC_QUEUE_SHUTDOWN:
-      gpr_strvec_add(&buf, gpr_strdup("QUEUE_SHUTDOWN"));
+      out.push_back("QUEUE_SHUTDOWN");
       break;
     case GRPC_OP_COMPLETE:
-      gpr_strvec_add(&buf, gpr_strdup("OP_COMPLETE: "));
-      addhdr(&buf, ev);
-      adderr(&buf, ev->success);
+      out.push_back("OP_COMPLETE: ");
+      addhdr(ev, &out);
+      adderr(ev->success, &out);
       break;
   }
-
-  out = gpr_strvec_flatten(&buf, nullptr);
-  gpr_strvec_destroy(&buf);
-  return out;
+  return absl::StrJoin(out, "");
 }
index e609570..9e02a52 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
+#include <string>
+
 #include <grpc/grpc.h>
 
 /* Returns a string describing an event. Must be later freed with gpr_free() */
-char* grpc_event_string(grpc_event* ev);
+std::string grpc_event_string(grpc_event* ev);
 
 #endif /* GRPC_CORE_LIB_SURFACE_EVENT_STRING_H */
index 998eb6d..d22b52a 100644 (file)
@@ -72,15 +72,39 @@ enum requested_call_type { BATCH_CALL, REGISTERED_CALL };
 struct registered_method;
 
 struct requested_call {
-  grpc_core::ManualConstructor<
-      grpc_core::MultiProducerSingleConsumerQueue::Node>
-      mpscq_node;
-  requested_call_type type;
-  void* tag;
-  grpc_completion_queue* cq_bound_to_call;
-  grpc_call** call;
+  requested_call(void* tag_arg, grpc_completion_queue* call_cq,
+                 grpc_call** call_arg, grpc_metadata_array* initial_md,
+                 grpc_call_details* details)
+      : type(BATCH_CALL),
+        tag(tag_arg),
+        cq_bound_to_call(call_cq),
+        call(call_arg),
+        initial_metadata(initial_md) {
+    details->reserved = nullptr;
+    data.batch.details = details;
+  }
+
+  requested_call(void* tag_arg, grpc_completion_queue* call_cq,
+                 grpc_call** call_arg, grpc_metadata_array* initial_md,
+                 registered_method* rm, gpr_timespec* deadline,
+                 grpc_byte_buffer** optional_payload)
+      : type(REGISTERED_CALL),
+        tag(tag_arg),
+        cq_bound_to_call(call_cq),
+        call(call_arg),
+        initial_metadata(initial_md) {
+    data.registered.method = rm;
+    data.registered.deadline = deadline;
+    data.registered.optional_payload = optional_payload;
+  }
+
+  grpc_core::MultiProducerSingleConsumerQueue::Node mpscq_node;
+  const requested_call_type type;
+  void* const tag;
+  grpc_completion_queue* const cq_bound_to_call;
+  grpc_call** const call;
   grpc_cq_completion completion;
-  grpc_metadata_array* initial_metadata;
+  grpc_metadata_array* const initial_metadata;
   union {
     struct {
       grpc_call_details* details;
@@ -134,6 +158,10 @@ enum call_state {
 
 struct call_data;
 
+grpc_call_error ValidateServerRequest(
+    grpc_completion_queue* cq_for_notification, void* tag,
+    grpc_byte_buffer** optional_payload, registered_method* rm);
+
 // RPCs that come in from the transport must be matched against RPC requests
 // from the application. An incoming request from the application can be matched
 // to an RPC that has already arrived or can be queued up for later use.
@@ -242,14 +270,23 @@ struct call_data {
 };
 
 struct registered_method {
-  char* method;
-  char* host;
-  grpc_server_register_method_payload_handling payload_handling;
-  uint32_t flags;
+  registered_method(
+      const char* method_arg, const char* host_arg,
+      grpc_server_register_method_payload_handling payload_handling_arg,
+      uint32_t flags_arg)
+      : method(method_arg == nullptr ? "" : method_arg),
+        host(host_arg == nullptr ? "" : host_arg),
+        payload_handling(payload_handling_arg),
+        flags(flags_arg) {}
+
+  ~registered_method() = default;
+
+  const std::string method;
+  const std::string host;
+  const grpc_server_register_method_payload_handling payload_handling;
+  const uint32_t flags;
   /* one request matcher per method */
-  // TODO(vjpai): Move this to a unique_ptr once this has a real
-  // constructor/destructor
-  RequestMatcherInterface* matcher = nullptr;
+  std::unique_ptr<RequestMatcherInterface> matcher;
   registered_method* next;
 };
 
@@ -285,6 +322,8 @@ struct grpc_server {
   bool starting;
   gpr_cv starting_cv;
 
+  // TODO(vjpai): Convert from a linked-list head pointer to a std::vector once
+  // grpc_server has a real constructor/destructor
   registered_method* registered_methods;
   /** one request matcher for unregistered methods */
   // TODO(vjpai): Convert to a std::unique_ptr once grpc_server has a real
@@ -444,7 +483,7 @@ class RealRequestMatcher : public RequestMatcherInterface {
 
   void RequestCallWithPossiblePublish(size_t request_queue_index,
                                       requested_call* call) override {
-    if (requests_per_cq_[request_queue_index].Push(call->mpscq_node.get())) {
+    if (requests_per_cq_[request_queue_index].Push(&call->mpscq_node)) {
       /* this was the first queued request: we need to lock and start
          matching calls */
       gpr_mu_lock(&server_->mu_call);
@@ -530,6 +569,103 @@ class RealRequestMatcher : public RequestMatcherInterface {
   std::vector<LockedMultiProducerSingleConsumerQueue> requests_per_cq_;
 };
 
+// AllocatingRequestMatchers don't allow the application to request an RPC in
+// advance or queue up any incoming RPC for later match. Instead, MatchOrQueue
+// will call out to an allocation function passed in at the construction of the
+// object. These request matchers are designed for the C++ callback API, so they
+// only support 1 completion queue (passed in at the constructor).
+class AllocatingRequestMatcherBase : public RequestMatcherInterface {
+ public:
+  AllocatingRequestMatcherBase(grpc_server* server, grpc_completion_queue* cq)
+      : server_(server), cq_(cq) {
+    size_t idx;
+    for (idx = 0; idx < server->cq_count; idx++) {
+      if (server->cqs[idx] == cq) {
+        break;
+      }
+    }
+    GPR_ASSERT(idx < server->cq_count);
+    cq_idx_ = idx;
+  }
+
+  void ZombifyPending() override {}
+
+  void KillRequests(grpc_error* error) override { GRPC_ERROR_UNREF(error); }
+
+  size_t request_queue_count() const override { return 0; }
+
+  void RequestCallWithPossiblePublish(size_t /*request_queue_index*/,
+                                      requested_call* /*call*/) final {
+    GPR_ASSERT(false);
+  }
+
+  grpc_server* server() const override { return server_; }
+
+  // Supply the completion queue related to this request matcher
+  grpc_completion_queue* cq() const { return cq_; }
+
+  // Supply the completion queue's index relative to the server.
+  size_t cq_idx() const { return cq_idx_; }
+
+ private:
+  grpc_server* const server_;
+  grpc_completion_queue* const cq_;
+  size_t cq_idx_;
+};
+
+// An allocating request matcher for non-registered methods (used for generic
+// API and unimplemented RPCs).
+class AllocatingRequestMatcherBatch : public AllocatingRequestMatcherBase {
+ public:
+  AllocatingRequestMatcherBatch(
+      grpc_server* server, grpc_completion_queue* cq,
+      std::function<grpc_core::ServerBatchCallAllocation()> allocator)
+      : AllocatingRequestMatcherBase(server, cq),
+        allocator_(std::move(allocator)) {}
+  void MatchOrQueue(size_t /*start_request_queue_index*/,
+                    call_data* calld) override {
+    grpc_core::ServerBatchCallAllocation call_info = allocator_();
+    GPR_ASSERT(ValidateServerRequest(cq(), static_cast<void*>(call_info.tag),
+                                     nullptr, nullptr) == GRPC_CALL_OK);
+    requested_call* rc = new requested_call(
+        static_cast<void*>(call_info.tag), cq(), call_info.call,
+        call_info.initial_metadata, call_info.details);
+    gpr_atm_no_barrier_store(&calld->state, ACTIVATED);
+    publish_call(server(), calld, cq_idx(), rc);
+  }
+
+ private:
+  std::function<grpc_core::ServerBatchCallAllocation()> allocator_;
+};
+
+// An allocating request matcher for registered methods.
+class AllocatingRequestMatcherRegistered : public AllocatingRequestMatcherBase {
+ public:
+  AllocatingRequestMatcherRegistered(
+      grpc_server* server, grpc_completion_queue* cq, registered_method* rm,
+      std::function<grpc_core::ServerRegisteredCallAllocation()> allocator)
+      : AllocatingRequestMatcherBase(server, cq),
+        registered_method_(rm),
+        allocator_(std::move(allocator)) {}
+  void MatchOrQueue(size_t /*start_request_queue_index*/,
+                    call_data* calld) override {
+    grpc_core::ServerRegisteredCallAllocation call_info = allocator_();
+    GPR_ASSERT(ValidateServerRequest(cq(), static_cast<void*>(call_info.tag),
+                                     call_info.optional_payload,
+                                     registered_method_) == GRPC_CALL_OK);
+    requested_call* rc = new requested_call(
+        static_cast<void*>(call_info.tag), cq(), call_info.call,
+        call_info.initial_metadata, registered_method_, call_info.deadline,
+        call_info.optional_payload);
+    gpr_atm_no_barrier_store(&calld->state, ACTIVATED);
+    publish_call(server(), calld, cq_idx(), rc);
+  }
+
+ private:
+  registered_method* const registered_method_;
+  std::function<grpc_core::ServerRegisteredCallAllocation()> allocator_;
+};
+
 /*
  * server proper
  */
@@ -546,10 +682,7 @@ void server_delete(grpc_server* server) {
   gpr_cv_destroy(&server->starting_cv);
   while ((rm = server->registered_methods) != nullptr) {
     server->registered_methods = rm->next;
-    delete rm->matcher;
-    gpr_free(rm->method);
-    gpr_free(rm->host);
-    gpr_free(rm);
+    delete rm;
   }
   delete server->unregistered_request_matcher;
   for (i = 0; i < server->cq_count; i++) {
@@ -603,7 +736,9 @@ void destroy_channel(channel_data* chand) {
                        op);
 }
 
-void done_request_event(void* req, grpc_cq_completion* /*c*/) { gpr_free(req); }
+void done_request_event(void* req, grpc_cq_completion* /*c*/) {
+  delete static_cast<requested_call*>(req);
+}
 
 void publish_call(grpc_server* server, call_data* calld, size_t cq_idx,
                   requested_call* rc) {
@@ -718,7 +853,8 @@ void start_new_rpc(grpc_call_element* elem) {
                 GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST)) {
         continue;
       }
-      finish_start_new_rpc(server, elem, rm->server_registered_method->matcher,
+      finish_start_new_rpc(server, elem,
+                           rm->server_registered_method->matcher.get(),
                            rm->server_registered_method->payload_handling);
       return;
     }
@@ -735,7 +871,8 @@ void start_new_rpc(grpc_call_element* elem) {
                 GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST)) {
         continue;
       }
-      finish_start_new_rpc(server, elem, rm->server_registered_method->matcher,
+      finish_start_new_rpc(server, elem,
+                           rm->server_registered_method->matcher.get(),
                            rm->server_registered_method->payload_handling);
       return;
     }
@@ -1043,11 +1180,9 @@ void register_completion_queue(grpc_server* server, grpc_completion_queue* cq,
   server->cqs[n] = cq;
 }
 
-int streq(const char* a, const char* b) {
-  if (a == nullptr && b == nullptr) return 1;
-  if (a == nullptr) return 0;
-  if (b == nullptr) return 0;
-  return 0 == strcmp(a, b);
+bool streq(const std::string& a, const char* b) {
+  return (a.empty() && b == nullptr) ||
+         ((b != nullptr) && !strcmp(a.c_str(), b));
 }
 
 class ConnectivityWatcher
@@ -1101,7 +1236,7 @@ grpc_call_error queue_call_request(grpc_server* server, size_t cq_idx,
       rm = server->unregistered_request_matcher;
       break;
     case REGISTERED_CALL:
-      rm = rc->data.registered.method->matcher;
+      rm = rc->data.registered.method->matcher.get();
       break;
   }
   rm->RequestCallWithPossiblePublish(cq_idx, rc);
@@ -1119,6 +1254,26 @@ void fail_call(grpc_server* server, size_t cq_idx, requested_call* rc,
 }
 }  // namespace
 
+namespace grpc_core {
+
+void SetServerRegisteredMethodAllocator(
+    grpc_server* server, grpc_completion_queue* cq, void* method_tag,
+    std::function<ServerRegisteredCallAllocation()> allocator) {
+  registered_method* rm = static_cast<registered_method*>(method_tag);
+  rm->matcher.reset(new AllocatingRequestMatcherRegistered(
+      server, cq, rm, std::move(allocator)));
+}
+
+void SetServerBatchMethodAllocator(
+    grpc_server* server, grpc_completion_queue* cq,
+    std::function<ServerBatchCallAllocation()> allocator) {
+  GPR_DEBUG_ASSERT(server->unregistered_request_matcher == nullptr);
+  server->unregistered_request_matcher =
+      new AllocatingRequestMatcherBatch(server, cq, std::move(allocator));
+}
+
+};  // namespace grpc_core
+
 const grpc_channel_filter grpc_server_top_filter = {
     server_start_transport_stream_op_batch,
     grpc_channel_next_op,
@@ -1224,12 +1379,8 @@ void* grpc_server_register_method(
             flags);
     return nullptr;
   }
-  m = static_cast<registered_method*>(gpr_zalloc(sizeof(registered_method)));
-  m->method = gpr_strdup(method);
-  m->host = gpr_strdup(host);
+  m = new registered_method(method, host, payload_handling, flags);
   m->next = server->registered_methods;
-  m->payload_handling = payload_handling;
-  m->flags = flags;
   server->registered_methods = m;
   return m;
 }
@@ -1250,9 +1401,13 @@ void grpc_server_start(grpc_server* server) {
           grpc_cq_pollset(server->cqs[i]);
     }
   }
-  server->unregistered_request_matcher = new RealRequestMatcher(server);
+  if (server->unregistered_request_matcher == nullptr) {
+    server->unregistered_request_matcher = new RealRequestMatcher(server);
+  }
   for (registered_method* rm = server->registered_methods; rm; rm = rm->next) {
-    rm->matcher = new RealRequestMatcher(server);
+    if (rm->matcher == nullptr) {
+      rm->matcher.reset(new RealRequestMatcher(server));
+    }
   }
 
   gpr_mu_lock(&server->mu_global);
@@ -1331,10 +1486,10 @@ void grpc_server_setup_transport(
         static_cast<channel_registered_method*>(gpr_zalloc(alloc));
     for (rm = s->registered_methods; rm; rm = rm->next) {
       grpc_core::ExternallyManagedSlice host;
-      grpc_core::ExternallyManagedSlice method(rm->method);
-      const bool has_host = rm->host != nullptr;
+      grpc_core::ExternallyManagedSlice method(rm->method.c_str());
+      const bool has_host = !rm->host.empty();
       if (has_host) {
-        host = grpc_core::ExternallyManagedSlice(rm->host);
+        host = grpc_core::ExternallyManagedSlice(rm->host.c_str());
       }
       hash = GRPC_MDSTR_KV_HASH(has_host ? host.Hash() : 0, method.Hash());
       for (probes = 0; chand->registered_methods[(hash + probes) % slots]
@@ -1523,15 +1678,51 @@ void grpc_server_add_listener(
   server->listeners = l;
 }
 
+namespace {
+grpc_call_error ValidateServerRequest(
+    grpc_completion_queue* cq_for_notification, void* tag,
+    grpc_byte_buffer** optional_payload, registered_method* rm) {
+  if ((rm == nullptr && optional_payload != nullptr) ||
+      ((rm != nullptr) && ((optional_payload == nullptr) !=
+                           (rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)))) {
+    return GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH;
+  }
+  if (grpc_cq_begin_op(cq_for_notification, tag) == false) {
+    return GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN;
+  }
+  return GRPC_CALL_OK;
+}
+grpc_call_error ValidateServerRequestAndCq(
+    size_t* cq_idx, grpc_server* server,
+    grpc_completion_queue* cq_for_notification, void* tag,
+    grpc_byte_buffer** optional_payload, registered_method* rm) {
+  size_t idx;
+  for (idx = 0; idx < server->cq_count; idx++) {
+    if (server->cqs[idx] == cq_for_notification) {
+      break;
+    }
+  }
+  if (idx == server->cq_count) {
+    return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
+  }
+  grpc_call_error error =
+      ValidateServerRequest(cq_for_notification, tag, optional_payload, rm);
+  if (error != GRPC_CALL_OK) {
+    return error;
+  }
+
+  *cq_idx = idx;
+  return GRPC_CALL_OK;
+}
+}  // namespace
+
 grpc_call_error grpc_server_request_call(
     grpc_server* server, grpc_call** call, grpc_call_details* details,
     grpc_metadata_array* initial_metadata,
     grpc_completion_queue* cq_bound_to_call,
     grpc_completion_queue* cq_for_notification, void* tag) {
-  grpc_call_error error;
   grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
   grpc_core::ExecCtx exec_ctx;
-  requested_call* rc = static_cast<requested_call*>(gpr_malloc(sizeof(*rc)));
   GRPC_STATS_INC_SERVER_REQUESTED_CALLS();
   GRPC_API_TRACE(
       "grpc_server_request_call("
@@ -1540,33 +1731,17 @@ grpc_call_error grpc_server_request_call(
       7,
       (server, call, details, initial_metadata, cq_bound_to_call,
        cq_for_notification, tag));
+
   size_t cq_idx;
-  for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) {
-    if (server->cqs[cq_idx] == cq_for_notification) {
-      break;
-    }
-  }
-  if (cq_idx == server->cq_count) {
-    gpr_free(rc);
-    error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
-    goto done;
+  grpc_call_error error = ValidateServerRequestAndCq(
+      &cq_idx, server, cq_for_notification, tag, nullptr, nullptr);
+  if (error != GRPC_CALL_OK) {
+    return error;
   }
-  if (grpc_cq_begin_op(cq_for_notification, tag) == false) {
-    gpr_free(rc);
-    error = GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN;
-    goto done;
-  }
-  details->reserved = nullptr;
-  rc->type = BATCH_CALL;
-  rc->tag = tag;
-  rc->cq_bound_to_call = cq_bound_to_call;
-  rc->call = call;
-  rc->data.batch.details = details;
-  rc->initial_metadata = initial_metadata;
-  error = queue_call_request(server, cq_idx, rc);
-done:
-
-  return error;
+
+  requested_call* rc = new requested_call(tag, cq_bound_to_call, call,
+                                          initial_metadata, details);
+  return queue_call_request(server, cq_idx, rc);
 }
 
 grpc_call_error grpc_server_request_registered_call(
@@ -1577,7 +1752,6 @@ grpc_call_error grpc_server_request_registered_call(
   grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
   grpc_core::ExecCtx exec_ctx;
   GRPC_STATS_INC_SERVER_REQUESTED_CALLS();
-  requested_call* rc = static_cast<requested_call*>(gpr_malloc(sizeof(*rc)));
   registered_method* rm = static_cast<registered_method*>(rmp);
   GRPC_API_TRACE(
       "grpc_server_request_registered_call("
@@ -1589,33 +1763,15 @@ grpc_call_error grpc_server_request_registered_call(
        cq_bound_to_call, cq_for_notification, tag));
 
   size_t cq_idx;
-  for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) {
-    if (server->cqs[cq_idx] == cq_for_notification) {
-      break;
-    }
-  }
-  if (cq_idx == server->cq_count) {
-    gpr_free(rc);
-    return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
-  }
-  if ((optional_payload == nullptr) !=
-      (rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)) {
-    gpr_free(rc);
-    return GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH;
+  grpc_call_error error = ValidateServerRequestAndCq(
+      &cq_idx, server, cq_for_notification, tag, optional_payload, rm);
+  if (error != GRPC_CALL_OK) {
+    return error;
   }
 
-  if (grpc_cq_begin_op(cq_for_notification, tag) == false) {
-    gpr_free(rc);
-    return GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN;
-  }
-  rc->type = REGISTERED_CALL;
-  rc->tag = tag;
-  rc->cq_bound_to_call = cq_bound_to_call;
-  rc->call = call;
-  rc->data.registered.method = rm;
-  rc->data.registered.deadline = deadline;
-  rc->initial_metadata = initial_metadata;
-  rc->data.registered.optional_payload = optional_payload;
+  requested_call* rc =
+      new requested_call(tag, cq_bound_to_call, call, initial_metadata, rm,
+                         deadline, optional_payload);
   return queue_call_request(server, cq_idx, rc);
 }
 
index 2285821..3f11c83 100644 (file)
@@ -64,4 +64,36 @@ int grpc_server_has_open_connections(grpc_server* server);
 void grpc_server_get_pollsets(grpc_server* server, grpc_pollset*** pollsets,
                               size_t* pollset_count);
 
+namespace grpc_core {
+
+// An object to represent the most relevant characteristics of a newly-allocated
+// call object when using an AllocatingRequestMatcherBatch
+struct ServerBatchCallAllocation {
+  grpc_experimental_completion_queue_functor* tag;
+  grpc_call** call;
+  grpc_metadata_array* initial_metadata;
+  grpc_call_details* details;
+};
+
+// An object to represent the most relevant characteristics of a newly-allocated
+// call object when using an AllocatingRequestMatcherRegistered
+struct ServerRegisteredCallAllocation {
+  grpc_experimental_completion_queue_functor* tag;
+  grpc_call** call;
+  grpc_metadata_array* initial_metadata;
+  gpr_timespec* deadline;
+  grpc_byte_buffer** optional_payload;
+};
+
+// Functions to specify that a specific registered method or the unregistered
+// collection should use a specific allocator for request matching.
+void SetServerRegisteredMethodAllocator(
+    grpc_server* server, grpc_completion_queue* cq, void* method_tag,
+    std::function<ServerRegisteredCallAllocation()> allocator);
+void SetServerBatchMethodAllocator(
+    grpc_server* server, grpc_completion_queue* cq,
+    std::function<ServerBatchCallAllocation()> allocator);
+
+}  // namespace grpc_core
+
 #endif /* GRPC_CORE_LIB_SURFACE_SERVER_H */
index b16e8dd..207fbfe 100644 (file)
@@ -25,4 +25,4 @@
 
 const char* grpc_version_string(void) { return "10.0.0"; }
 
-const char* grpc_g_stands_for(void) { return "gringotts"; }
+const char* grpc_g_stands_for(void) { return "gradius"; }
index 16da01d..2d34f52 100644 (file)
@@ -58,12 +58,13 @@ const char* ConnectivityStateName(grpc_connectivity_state state) {
 class AsyncConnectivityStateWatcherInterface::Notifier {
  public:
   Notifier(RefCountedPtr<AsyncConnectivityStateWatcherInterface> watcher,
-           grpc_connectivity_state state, Combiner* combiner)
+           grpc_connectivity_state state,
+           const std::shared_ptr<WorkSerializer>& work_serializer)
       : watcher_(std::move(watcher)), state_(state) {
-    if (combiner != nullptr) {
-      combiner->Run(
-          GRPC_CLOSURE_INIT(&closure_, SendNotification, this, nullptr),
-          GRPC_ERROR_NONE);
+    if (work_serializer != nullptr) {
+      work_serializer->Run(
+          [this]() { SendNotification(this, GRPC_ERROR_NONE); },
+          DEBUG_LOCATION);
     } else {
       GRPC_CLOSURE_INIT(&closure_, SendNotification, this,
                         grpc_schedule_on_exec_ctx);
@@ -89,7 +90,7 @@ class AsyncConnectivityStateWatcherInterface::Notifier {
 
 void AsyncConnectivityStateWatcherInterface::Notify(
     grpc_connectivity_state state) {
-  new Notifier(Ref(), state, combiner_);  // Deletes itself when done.
+  new Notifier(Ref(), state, work_serializer_);  // Deletes itself when done.
 }
 
 //
index b2add5d..5ab62be 100644 (file)
@@ -29,6 +29,7 @@
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/iomgr/closure.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 
 namespace grpc_core {
 
@@ -70,14 +71,15 @@ class AsyncConnectivityStateWatcherInterface
 
   // If \a combiner is nullptr, then the notification will be scheduled on the
   // ExecCtx.
-  explicit AsyncConnectivityStateWatcherInterface(Combiner* combiner = nullptr)
-      : combiner_(combiner) {}
+  explicit AsyncConnectivityStateWatcherInterface(
+      std::shared_ptr<WorkSerializer> work_serializer = nullptr)
+      : work_serializer_(std::move(work_serializer)) {}
 
   // Invoked asynchronously when Notify() is called.
   virtual void OnConnectivityStateChange(grpc_connectivity_state new_state) = 0;
 
  private:
-  Combiner* combiner_;
+  std::shared_ptr<WorkSerializer> work_serializer_;
 };
 
 // Tracks connectivity state.  Maintains a list of watchers that are
index 46a437e..3101f48 100644 (file)
@@ -154,11 +154,10 @@ inline grpc_error* GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail(
 
 grpc_error* grpc_attach_md_to_error(grpc_error* src, grpc_mdelem md);
 
-typedef struct {
+struct grpc_filtered_mdelem {
   grpc_error* error;
   grpc_mdelem md;
-} grpc_filtered_mdelem;
-
+};
 #define GRPC_FILTERED_ERROR(error) \
   { (error), GRPC_MDNULL }
 #define GRPC_FILTERED_MDELEM(md) \
index 5f86dac..46c6cd8 100644 (file)
@@ -68,29 +68,21 @@ grpc_status_code grpc_http2_status_to_grpc_status(int status) {
     case 200:
       return GRPC_STATUS_OK;
     case 400:
-      return GRPC_STATUS_INVALID_ARGUMENT;
+      return GRPC_STATUS_INTERNAL;
     case 401:
       return GRPC_STATUS_UNAUTHENTICATED;
     case 403:
       return GRPC_STATUS_PERMISSION_DENIED;
     case 404:
-      return GRPC_STATUS_NOT_FOUND;
-    case 409:
-      return GRPC_STATUS_ABORTED;
-    case 412:
-      return GRPC_STATUS_FAILED_PRECONDITION;
-    case 429:
-      return GRPC_STATUS_RESOURCE_EXHAUSTED;
-    case 499:
-      return GRPC_STATUS_CANCELLED;
-    case 500:
-      return GRPC_STATUS_UNKNOWN;
-    case 501:
       return GRPC_STATUS_UNIMPLEMENTED;
+    case 429:
+      return GRPC_STATUS_UNAVAILABLE;
+    case 502:
+      return GRPC_STATUS_UNAVAILABLE;
     case 503:
       return GRPC_STATUS_UNAVAILABLE;
     case 504:
-      return GRPC_STATUS_DEADLINE_EXCEEDED;
+      return GRPC_STATUS_UNAVAILABLE;
     /* everything else is unknown */
     default:
       return GRPC_STATUS_UNKNOWN;
index 6adcd8d..99a3298 100644 (file)
@@ -233,13 +233,12 @@ grpc_transport_op* grpc_make_transport_op(grpc_closure* on_complete) {
   return &op->op;
 }
 
-typedef struct {
+struct made_transport_stream_op {
   grpc_closure outer_on_complete;
   grpc_closure* inner_on_complete;
   grpc_transport_stream_op_batch op;
   grpc_transport_stream_op_batch_payload payload;
-} made_transport_stream_op;
-
+};
 static void destroy_made_transport_stream_op(void* arg, grpc_error* error) {
   made_transport_stream_op* op = static_cast<made_transport_stream_op*>(arg);
   grpc_closure* c = op->inner_on_complete;
index 1837451..ab51289 100644 (file)
@@ -408,8 +408,9 @@ void grpc_transport_stream_op_batch_finish_with_failure(
     grpc_transport_stream_op_batch* op, grpc_error* error,
     grpc_core::CallCombiner* call_combiner);
 
-char* grpc_transport_stream_op_batch_string(grpc_transport_stream_op_batch* op);
-char* grpc_transport_op_string(grpc_transport_op* op);
+std::string grpc_transport_stream_op_batch_string(
+    grpc_transport_stream_op_batch* op);
+std::string grpc_transport_op_string(grpc_transport_op* op);
 
 /* Send a batch of operations on a transport
 
index 34b36c3..722a64e 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
+#include <vector>
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
 #include "src/core/lib/gpr/string.h"
 /* These routines are here to facilitate debugging - they produce string
    representations of various transport data structures */
 
-static void put_metadata(gpr_strvec* b, grpc_mdelem md) {
-  gpr_strvec_add(b, gpr_strdup("key="));
-  gpr_strvec_add(
-      b, grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII));
-
-  gpr_strvec_add(b, gpr_strdup(" value="));
-  gpr_strvec_add(
-      b, grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII));
+static void put_metadata(grpc_mdelem md, std::vector<std::string>* out) {
+  out->push_back("key=");
+  char* dump = grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
+  out->push_back(dump);
+  gpr_free(dump);
+  out->push_back(" value=");
+  dump = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
+  out->push_back(dump);
+  gpr_free(dump);
 }
 
-static void put_metadata_list(gpr_strvec* b, grpc_metadata_batch md) {
+static void put_metadata_list(grpc_metadata_batch md,
+                              std::vector<std::string>* out) {
   grpc_linked_mdelem* m;
   for (m = md.list.head; m != nullptr; m = m->next) {
-    if (m != md.list.head) gpr_strvec_add(b, gpr_strdup(", "));
-    put_metadata(b, m->md);
+    if (m != md.list.head) out->push_back(", ");
+    put_metadata(m->md, out);
   }
   if (md.deadline != GRPC_MILLIS_INF_FUTURE) {
-    char* tmp;
-    gpr_asprintf(&tmp, " deadline=%" PRId64, md.deadline);
-    gpr_strvec_add(b, tmp);
+    out->push_back(absl::StrFormat(" deadline=%" PRId64, md.deadline));
   }
 }
 
-char* grpc_transport_stream_op_batch_string(
+std::string grpc_transport_stream_op_batch_string(
     grpc_transport_stream_op_batch* op) {
-  char* tmp;
-  char* out;
-
-  gpr_strvec b;
-  gpr_strvec_init(&b);
+  std::vector<std::string> out;
 
   if (op->send_initial_metadata) {
-    gpr_strvec_add(&b, gpr_strdup(" "));
-    gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA{"));
-    put_metadata_list(
-        &b, *op->payload->send_initial_metadata.send_initial_metadata);
-    gpr_strvec_add(&b, gpr_strdup("}"));
+    out.push_back(" SEND_INITIAL_METADATA{");
+    put_metadata_list(*op->payload->send_initial_metadata.send_initial_metadata,
+                      &out);
+    out.push_back("}");
   }
 
   if (op->send_message) {
-    gpr_strvec_add(&b, gpr_strdup(" "));
     if (op->payload->send_message.send_message != nullptr) {
-      gpr_asprintf(&tmp, "SEND_MESSAGE:flags=0x%08x:len=%d",
-                   op->payload->send_message.send_message->flags(),
-                   op->payload->send_message.send_message->length());
+      out.push_back(
+          absl::StrFormat(" SEND_MESSAGE:flags=0x%08x:len=%d",
+                          op->payload->send_message.send_message->flags(),
+                          op->payload->send_message.send_message->length()));
     } else {
       // This can happen when we check a batch after the transport has
       // processed and cleared the send_message op.
-      tmp =
-          gpr_strdup("SEND_MESSAGE(flag and length unknown, already orphaned)");
+      out.push_back(" SEND_MESSAGE(flag and length unknown, already orphaned)");
     }
-    gpr_strvec_add(&b, tmp);
   }
 
   if (op->send_trailing_metadata) {
-    gpr_strvec_add(&b, gpr_strdup(" "));
-    gpr_strvec_add(&b, gpr_strdup("SEND_TRAILING_METADATA{"));
+    out.push_back(" SEND_TRAILING_METADATA{");
     put_metadata_list(
-        &b, *op->payload->send_trailing_metadata.send_trailing_metadata);
-    gpr_strvec_add(&b, gpr_strdup("}"));
+        *op->payload->send_trailing_metadata.send_trailing_metadata, &out);
+    out.push_back("}");
   }
 
   if (op->recv_initial_metadata) {
-    gpr_strvec_add(&b, gpr_strdup(" "));
-    gpr_strvec_add(&b, gpr_strdup("RECV_INITIAL_METADATA"));
+    out.push_back(" RECV_INITIAL_METADATA");
   }
 
   if (op->recv_message) {
-    gpr_strvec_add(&b, gpr_strdup(" "));
-    gpr_strvec_add(&b, gpr_strdup("RECV_MESSAGE"));
+    out.push_back(" RECV_MESSAGE");
   }
 
   if (op->recv_trailing_metadata) {
-    gpr_strvec_add(&b, gpr_strdup(" "));
-    gpr_strvec_add(&b, gpr_strdup("RECV_TRAILING_METADATA"));
+    out.push_back(" RECV_TRAILING_METADATA");
   }
 
   if (op->cancel_stream) {
-    gpr_strvec_add(&b, gpr_strdup(" "));
-    const char* msg =
-        grpc_error_string(op->payload->cancel_stream.cancel_error);
-    gpr_asprintf(&tmp, "CANCEL:%s", msg);
-
-    gpr_strvec_add(&b, tmp);
+    out.push_back(absl::StrCat(
+        " CANCEL:",
+        grpc_error_string(op->payload->cancel_stream.cancel_error)));
   }
 
-  out = gpr_strvec_flatten(&b, nullptr);
-  gpr_strvec_destroy(&b);
-
-  return out;
+  return absl::StrJoin(out, "");
 }
 
-char* grpc_transport_op_string(grpc_transport_op* op) {
-  char* tmp;
-  char* out;
-  bool first = true;
-
-  gpr_strvec b;
-  gpr_strvec_init(&b);
+std::string grpc_transport_op_string(grpc_transport_op* op) {
+  std::vector<std::string> out;
 
   if (op->start_connectivity_watch != nullptr) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = false;
-    gpr_asprintf(
-        &tmp, "START_CONNECTIVITY_WATCH:watcher=%p:from=%s",
+    out.push_back(absl::StrFormat(
+        " START_CONNECTIVITY_WATCH:watcher=%p:from=%s",
         op->start_connectivity_watch.get(),
-        grpc_core::ConnectivityStateName(op->start_connectivity_watch_state));
-    gpr_strvec_add(&b, tmp);
+        grpc_core::ConnectivityStateName(op->start_connectivity_watch_state)));
   }
 
   if (op->stop_connectivity_watch != nullptr) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = false;
-    gpr_asprintf(&tmp, "STOP_CONNECTIVITY_WATCH:watcher=%p",
-                 op->stop_connectivity_watch);
-    gpr_strvec_add(&b, tmp);
+    out.push_back(absl::StrFormat(" STOP_CONNECTIVITY_WATCH:watcher=%p",
+                                  op->stop_connectivity_watch));
   }
 
   if (op->disconnect_with_error != GRPC_ERROR_NONE) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = false;
-    const char* err = grpc_error_string(op->disconnect_with_error);
-    gpr_asprintf(&tmp, "DISCONNECT:%s", err);
-    gpr_strvec_add(&b, tmp);
+    out.push_back(absl::StrCat(" DISCONNECT:",
+                               grpc_error_string(op->disconnect_with_error)));
   }
 
   if (op->goaway_error) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = false;
-    const char* msg = grpc_error_string(op->goaway_error);
-    gpr_asprintf(&tmp, "SEND_GOAWAY:%s", msg);
-
-    gpr_strvec_add(&b, tmp);
+    out.push_back(
+        absl::StrCat(" SEND_GOAWAY:%s", grpc_error_string(op->goaway_error)));
   }
 
   if (op->set_accept_stream) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = false;
-    gpr_asprintf(&tmp, "SET_ACCEPT_STREAM:%p(%p,...)", op->set_accept_stream_fn,
-                 op->set_accept_stream_user_data);
-    gpr_strvec_add(&b, tmp);
+    out.push_back(absl::StrFormat(" SET_ACCEPT_STREAM:%p(%p,...)",
+                                  op->set_accept_stream_fn,
+                                  op->set_accept_stream_user_data));
   }
 
   if (op->bind_pollset != nullptr) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = false;
-    gpr_strvec_add(&b, gpr_strdup("BIND_POLLSET"));
+    out.push_back(" BIND_POLLSET");
   }
 
   if (op->bind_pollset_set != nullptr) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = false;
-    gpr_strvec_add(&b, gpr_strdup("BIND_POLLSET_SET"));
+    out.push_back(" BIND_POLLSET_SET");
   }
 
   if (op->send_ping.on_initiate != nullptr || op->send_ping.on_ack != nullptr) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    // first = false;
-    gpr_strvec_add(&b, gpr_strdup("SEND_PING"));
+    out.push_back(" SEND_PING");
   }
 
-  out = gpr_strvec_flatten(&b, nullptr);
-  gpr_strvec_destroy(&b);
-
-  return out;
+  return absl::StrJoin(out, "");
 }
 
 void grpc_call_log_op(const char* file, int line, gpr_log_severity severity,
                       grpc_call_element* elem,
                       grpc_transport_stream_op_batch* op) {
-  char* str = grpc_transport_stream_op_batch_string(op);
-  gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem, str);
-  gpr_free(str);
+  gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem,
+          grpc_transport_stream_op_batch_string(op).c_str());
 }
index b6771bb..5cd7c47 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <stddef.h>
 
-typedef struct {
+struct grpc_uri {
   char* scheme;
   char* authority;
   char* path;
@@ -35,8 +35,7 @@ typedef struct {
   /** Split each query part by '='. NULL if not present. */
   char** query_parts_values;
   char* fragment;
-} grpc_uri;
-
+};
 /** parse a uri, return NULL on failure */
 grpc_uri* grpc_uri_parse(const char* uri_text, bool suppress_errors);
 
index 43b8a4a..571a915 100644 (file)
@@ -31,7 +31,7 @@
 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"
 
 /* V-table for alts_grpc_record_protocol implementations.  */
-typedef struct {
+struct alts_grpc_record_protocol_vtable {
   tsi_result (*protect)(alts_grpc_record_protocol* self,
                         grpc_slice_buffer* unprotected_slices,
                         grpc_slice_buffer* protected_slices);
@@ -39,8 +39,7 @@ typedef struct {
                           grpc_slice_buffer* protected_slices,
                           grpc_slice_buffer* unprotected_slices);
   void (*destruct)(alts_grpc_record_protocol* self);
-} alts_grpc_record_protocol_vtable;
-
+};
 /* Main struct for alts_grpc_record_protocol implementation, shared by both
  * integrity-only record protocol and privacy-integrity record protocol.
  * Integrity-only record protocol has additional data elements.
index c34aa9c..1b6b8ca 100644 (file)
    | size |     data    |
    where the size field value is the size of the size field plus the size of
    the data encoded in little endian on 4 bytes.  */
-typedef struct {
+struct tsi_fake_frame {
   unsigned char* data;
   size_t size;
   size_t allocated_size;
   size_t offset;
   int needs_draining;
-} tsi_fake_frame;
-
+};
 typedef enum {
   TSI_FAKE_CLIENT_INIT = 0,
   TSI_FAKE_SERVER_INIT = 1,
@@ -58,7 +57,7 @@ typedef enum {
   TSI_FAKE_HANDSHAKE_MESSAGE_MAX = 4
 } tsi_fake_handshake_message;
 
-typedef struct {
+struct tsi_fake_handshaker {
   tsi_handshaker base;
   int is_client;
   tsi_fake_handshake_message next_message_to_send;
@@ -68,23 +67,20 @@ typedef struct {
   unsigned char* outgoing_bytes_buffer;
   size_t outgoing_bytes_buffer_size;
   tsi_result result;
-} tsi_fake_handshaker;
-
-typedef struct {
+};
+struct tsi_fake_frame_protector {
   tsi_frame_protector base;
   tsi_fake_frame protect_frame;
   tsi_fake_frame unprotect_frame;
   size_t max_frame_size;
-} tsi_fake_frame_protector;
-
-typedef struct {
+};
+struct tsi_fake_zero_copy_grpc_protector {
   tsi_zero_copy_grpc_protector base;
   grpc_slice_buffer header_sb;
   grpc_slice_buffer protected_sb;
   size_t max_frame_size;
   size_t parsed_frame_size;
-} tsi_fake_zero_copy_grpc_protector;
-
+};
 /* --- Utils. ---*/
 
 static const char* tsi_fake_handshake_message_strings[] = {
@@ -488,12 +484,11 @@ static const tsi_zero_copy_grpc_protector_vtable
 
 /* --- tsi_handshaker_result methods implementation. ---*/
 
-typedef struct {
+struct fake_handshaker_result {
   tsi_handshaker_result base;
   unsigned char* unused_bytes;
   size_t unused_bytes_size;
-} fake_handshaker_result;
-
+};
 static tsi_result fake_handshaker_result_extract_peer(
     const tsi_handshaker_result* self, tsi_peer* peer) {
   /* Construct a tsi_peer with 1 property: certificate type, security_level. */
index e53e1b1..dda3f3c 100644 (file)
@@ -33,8 +33,6 @@
 #include <sys/socket.h>
 #endif
 
-#include "absl/strings/match.h"
-
 #include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -42,6 +40,9 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/thd_id.h>
 
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+
 extern "C" {
 #include <openssl/bio.h>
 #include <openssl/crypto.h> /* For OPENSSL_free */
@@ -105,7 +106,7 @@ struct tsi_ssl_server_handshaker_factory {
   size_t alpn_protocol_list_length;
 };
 
-typedef struct {
+struct tsi_ssl_handshaker {
   tsi_handshaker base;
   SSL* ssl;
   BIO* network_io;
@@ -113,25 +114,22 @@ typedef struct {
   unsigned char* outgoing_bytes_buffer;
   size_t outgoing_bytes_buffer_size;
   tsi_ssl_handshaker_factory* factory_ref;
-} tsi_ssl_handshaker;
-
-typedef struct {
+};
+struct tsi_ssl_handshaker_result {
   tsi_handshaker_result base;
   SSL* ssl;
   BIO* network_io;
   unsigned char* unused_bytes;
   size_t unused_bytes_size;
-} tsi_ssl_handshaker_result;
-
-typedef struct {
+};
+struct tsi_ssl_frame_protector {
   tsi_frame_protector base;
   SSL* ssl;
   BIO* network_io;
   unsigned char* buffer;
   size_t buffer_size;
   size_t buffer_offset;
-} tsi_ssl_frame_protector;
-
+};
 /* --- Library Initialization. ---*/
 
 static gpr_once g_init_openssl_once = GPR_ONCE_INIT;
@@ -238,7 +236,7 @@ static void ssl_info_callback(const SSL* ssl, int where, int ret) {
 
 /* Returns 1 if name looks like an IP address, 0 otherwise.
    This is a very rough heuristic, and only handles IPv6 in hexadecimal form. */
-static int looks_like_ip_address(grpc_core::StringView name) {
+static int looks_like_ip_address(absl::string_view name) {
   size_t dot_count = 0;
   size_t num_size = 0;
   for (size_t i = 0; i < name.size(); ++i) {
@@ -345,13 +343,10 @@ static tsi_result add_pem_certificate(X509* cert, tsi_peer_property* property) {
 /* Gets the subject SANs from an X509 cert as a tsi_peer_property. */
 static tsi_result add_subject_alt_names_properties_to_peer(
     tsi_peer* peer, GENERAL_NAMES* subject_alt_names,
-    size_t subject_alt_name_count) {
+    size_t subject_alt_name_count, int* current_insert_index) {
   size_t i;
   tsi_result result = TSI_OK;
 
-  /* Reset for DNS entries filtering. */
-  peer->property_count -= subject_alt_name_count;
-
   for (i = 0; i < subject_alt_name_count; i++) {
     GENERAL_NAME* subject_alt_name =
         sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i));
@@ -376,7 +371,17 @@ static tsi_result add_subject_alt_names_properties_to_peer(
       result = tsi_construct_string_peer_property(
           TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
           reinterpret_cast<const char*>(name), static_cast<size_t>(name_size),
-          &peer->properties[peer->property_count++]);
+          &peer->properties[(*current_insert_index)++]);
+      if (result != TSI_OK) {
+        OPENSSL_free(name);
+        break;
+      }
+      if (subject_alt_name->type == GEN_URI) {
+        result = tsi_construct_string_peer_property(
+            TSI_X509_URI_PEER_PROPERTY, reinterpret_cast<const char*>(name),
+            static_cast<size_t>(name_size),
+            &peer->properties[(*current_insert_index)++]);
+      }
       OPENSSL_free(name);
     } else if (subject_alt_name->type == GEN_IPADD) {
       char ntop_buf[INET6_ADDRSTRLEN];
@@ -401,7 +406,7 @@ static tsi_result add_subject_alt_names_properties_to_peer(
 
       result = tsi_construct_string_peer_property_from_cstring(
           TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, name,
-          &peer->properties[peer->property_count++]);
+          &peer->properties[(*current_insert_index)++]);
     }
     if (result != TSI_OK) break;
   }
@@ -424,26 +429,35 @@ static tsi_result peer_from_x509(X509* cert, int include_certificate_type,
   property_count = (include_certificate_type ? static_cast<size_t>(1) : 0) +
                    2 /* common name, certificate */ +
                    static_cast<size_t>(subject_alt_name_count);
+  for (int i = 0; i < subject_alt_name_count; i++) {
+    GENERAL_NAME* subject_alt_name =
+        sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i));
+    if (subject_alt_name->type == GEN_URI) {
+      property_count += 1;
+    }
+  }
   result = tsi_construct_peer(property_count, peer);
   if (result != TSI_OK) return result;
+  int current_insert_index = 0;
   do {
     if (include_certificate_type) {
       result = tsi_construct_string_peer_property_from_cstring(
           TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
-          &peer->properties[0]);
+          &peer->properties[current_insert_index++]);
       if (result != TSI_OK) break;
     }
     result = peer_property_from_x509_common_name(
-        cert, &peer->properties[include_certificate_type ? 1 : 0]);
+        cert, &peer->properties[current_insert_index++]);
     if (result != TSI_OK) break;
 
-    result = add_pem_certificate(
-        cert, &peer->properties[include_certificate_type ? 2 : 1]);
+    result =
+        add_pem_certificate(cert, &peer->properties[current_insert_index++]);
     if (result != TSI_OK) break;
 
     if (subject_alt_name_count != 0) {
       result = add_subject_alt_names_properties_to_peer(
-          peer, subject_alt_names, static_cast<size_t>(subject_alt_name_count));
+          peer, subject_alt_names, static_cast<size_t>(subject_alt_name_count),
+          &current_insert_index);
       if (result != TSI_OK) break;
     }
   } while (0);
@@ -452,6 +466,8 @@ static tsi_result peer_from_x509(X509* cert, int include_certificate_type,
     sk_GENERAL_NAME_pop_free(subject_alt_names, GENERAL_NAME_free);
   }
   if (result != TSI_OK) tsi_peer_destruct(peer);
+
+  GPR_ASSERT((int)peer->property_count == current_insert_index);
   return result;
 }
 
@@ -1645,8 +1661,8 @@ static void tsi_ssl_server_handshaker_factory_destroy(
   gpr_free(self);
 }
 
-static int does_entry_match_name(grpc_core::StringView entry,
-                                 grpc_core::StringView name) {
+static int does_entry_match_name(absl::string_view entry,
+                                 absl::string_view name) {
   if (entry.empty()) return 0;
 
   /* Take care of '.' terminations. */
@@ -1669,17 +1685,15 @@ static int does_entry_match_name(grpc_core::StringView entry,
     return 0;
   }
   size_t name_subdomain_pos = name.find('.');
-  if (name_subdomain_pos == grpc_core::StringView::npos) return 0;
+  if (name_subdomain_pos == absl::string_view::npos) return 0;
   if (name_subdomain_pos >= name.size() - 2) return 0;
-  grpc_core::StringView name_subdomain =
+  absl::string_view name_subdomain =
       name.substr(name_subdomain_pos + 1); /* Starts after the dot. */
   entry.remove_prefix(2);                  /* Remove *. */
   size_t dot = name_subdomain.find('.');
-  if (dot == grpc_core::StringView::npos || dot == name_subdomain.size() - 1) {
-    grpc_core::UniquePtr<char> name_subdomain_cstr(
-        grpc_core::StringViewToCString(name_subdomain));
+  if (dot == absl::string_view::npos || dot == name_subdomain.size() - 1) {
     gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s",
-            name_subdomain_cstr.get());
+            std::string(name_subdomain).c_str());
     return 0;
   }
   if (name_subdomain.back() == '.') {
@@ -2058,8 +2072,7 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
 
 /* --- tsi_ssl utils. --- */
 
-int tsi_ssl_peer_matches_name(const tsi_peer* peer,
-                              grpc_core::StringView name) {
+int tsi_ssl_peer_matches_name(const tsi_peer* peer, absl::string_view name) {
   size_t i = 0;
   size_t san_count = 0;
   const tsi_peer_property* cn_property = nullptr;
@@ -2073,7 +2086,7 @@ int tsi_ssl_peer_matches_name(const tsi_peer* peer,
                TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
       san_count++;
 
-      grpc_core::StringView entry(property->value.data, property->value.length);
+      absl::string_view entry(property->value.data, property->value.length);
       if (!like_ip && does_entry_match_name(entry, name)) {
         return 1;
       } else if (like_ip && name == entry) {
@@ -2088,8 +2101,8 @@ int tsi_ssl_peer_matches_name(const tsi_peer* peer,
 
   /* If there's no SAN, try the CN, but only if its not like an IP Address */
   if (san_count == 0 && cn_property != nullptr && !like_ip) {
-    if (does_entry_match_name(grpc_core::StringView(cn_property->value.data,
-                                                    cn_property->value.length),
+    if (does_entry_match_name(absl::string_view(cn_property->value.data,
+                                                cn_property->value.length),
                               name)) {
       return 1;
     }
index ae1e413..5ace7ff 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <grpc/support/port_platform.h>
 
-#include "src/core/lib/gprpp/string_view.h"
+#include "absl/strings/string_view.h"
 #include "src/core/tsi/transport_security_interface.h"
 
 extern "C" {
@@ -43,6 +43,8 @@ extern "C" {
 
 #define TSI_SSL_ALPN_SELECTED_PROTOCOL "ssl_alpn_selected_protocol"
 
+#define TSI_X509_URI_PEER_PROPERTY "x509_uri"
+
 /* --- tsi_ssl_root_certs_store object ---
 
    This object stores SSL root certificates. It can be shared by multiple SSL
@@ -81,7 +83,7 @@ typedef struct tsi_ssl_client_handshaker_factory
     tsi_ssl_client_handshaker_factory;
 
 /* Object that holds a private key / certificate chain pair in PEM format. */
-typedef struct {
+struct tsi_ssl_pem_key_cert_pair {
   /* private_key is the NULL-terminated string containing the PEM encoding of
      the client's private key. */
   const char* private_key;
@@ -89,8 +91,7 @@ typedef struct {
   /* cert_chain is the NULL-terminated string containing the PEM encoding of
      the client's certificate chain. */
   const char* cert_chain;
-} tsi_ssl_pem_key_cert_pair;
-
+};
 /* TO BE DEPRECATED.
    Creates a client handshaker factory.
    - pem_key_cert_pair is a pointer to the object containing client's private
@@ -317,7 +318,7 @@ void tsi_ssl_server_handshaker_factory_unref(
    - handle mixed case.
    - handle %encoded chars.
    - handle public suffix wildchar more strictly (e.g. *.co.uk) */
-int tsi_ssl_peer_matches_name(const tsi_peer* peer, grpc_core::StringView name);
+int tsi_ssl_peer_matches_name(const tsi_peer* peer, absl::string_view name);
 
 /* --- Testing support. ---
 
@@ -332,10 +333,9 @@ typedef void (*tsi_ssl_handshaker_factory_destructor)(
     tsi_ssl_handshaker_factory* factory);
 
 /* Virtual table for tsi_ssl_handshaker_factory. */
-typedef struct {
+struct tsi_ssl_handshaker_factory_vtable {
   tsi_ssl_handshaker_factory_destructor destroy;
-} tsi_ssl_handshaker_factory_vtable;
-
+};
 /* Set destructor of handshaker_factory to new_destructor, returns previous
    destructor. */
 const tsi_ssl_handshaker_factory_vtable* tsi_ssl_handshaker_factory_swap_vtable(
index 482d300..d3b1c7f 100644 (file)
@@ -30,7 +30,7 @@ extern grpc_core::TraceFlag tsi_tracing_enabled;
 
 /* Base for tsi_frame_protector implementations.
    See transport_security_interface.h for documentation. */
-typedef struct {
+struct tsi_frame_protector_vtable {
   tsi_result (*protect)(tsi_frame_protector* self,
                         const unsigned char* unprotected_bytes,
                         size_t* unprotected_bytes_size,
@@ -46,15 +46,14 @@ typedef struct {
                           unsigned char* unprotected_bytes,
                           size_t* unprotected_bytes_size);
   void (*destroy)(tsi_frame_protector* self);
-} tsi_frame_protector_vtable;
-
+};
 struct tsi_frame_protector {
   const tsi_frame_protector_vtable* vtable;
 };
 
 /* Base for tsi_handshaker implementations.
    See transport_security_interface.h for documentation. */
-typedef struct {
+struct tsi_handshaker_vtable {
   tsi_result (*get_bytes_to_send_to_peer)(tsi_handshaker* self,
                                           unsigned char* bytes,
                                           size_t* bytes_size);
@@ -74,8 +73,7 @@ typedef struct {
                      tsi_handshaker_result** handshaker_result,
                      tsi_handshaker_on_next_done_cb cb, void* user_data);
   void (*shutdown)(tsi_handshaker* self);
-} tsi_handshaker_vtable;
-
+};
 struct tsi_handshaker {
   const tsi_handshaker_vtable* vtable;
   bool frame_protector_created;
@@ -91,7 +89,7 @@ struct tsi_handshaker {
    in grpc, where we do need the exec_ctx passed through, but the API still
    needs to compile in other applications, where grpc_exec_ctx is not defined.
 */
-typedef struct {
+struct tsi_handshaker_result_vtable {
   tsi_result (*extract_peer)(const tsi_handshaker_result* self, tsi_peer* peer);
   tsi_result (*create_zero_copy_grpc_protector)(
       const tsi_handshaker_result* self,
@@ -104,8 +102,7 @@ typedef struct {
                                  const unsigned char** bytes,
                                  size_t* bytes_size);
   void (*destroy)(tsi_handshaker_result* self);
-} tsi_handshaker_result_vtable;
-
+};
 struct tsi_handshaker_result {
   const tsi_handshaker_result_vtable* vtable;
 };
index d33fa0b..4779b68 100644 (file)
@@ -61,7 +61,7 @@ tsi_result tsi_zero_copy_grpc_protector_max_frame_size(
     tsi_zero_copy_grpc_protector* self, size_t* max_frame_size);
 
 /* Base for tsi_zero_copy_grpc_protector implementations.  */
-typedef struct {
+struct tsi_zero_copy_grpc_protector_vtable {
   tsi_result (*protect)(tsi_zero_copy_grpc_protector* self,
                         grpc_slice_buffer* unprotected_slices,
                         grpc_slice_buffer* protected_slices);
@@ -71,8 +71,7 @@ typedef struct {
   void (*destroy)(tsi_zero_copy_grpc_protector* self);
   tsi_result (*max_frame_size)(tsi_zero_copy_grpc_protector* self,
                                size_t* max_frame_size);
-} tsi_zero_copy_grpc_protector_vtable;
-
+};
 struct tsi_zero_copy_grpc_protector {
   const tsi_zero_copy_grpc_protector_vtable* vtable;
 };
index ac7d153..6e93870 100644 (file)
@@ -208,11 +208,10 @@ typedef struct tsi_peer_property {
   } value;
 } tsi_peer_property;
 
-typedef struct {
+struct tsi_peer {
   tsi_peer_property* properties;
   size_t property_count;
-} tsi_peer;
-
+};
 /* Destructs the tsi_peer object. */
 void tsi_peer_destruct(tsi_peer* self);
 
index 1359d02..67a96cc 100644 (file)
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name     = 'Protobuf-C++'
-  s.version  = '3.11.2'
+  s.version  = '3.12.2'
   s.summary  = 'Protocol Buffers v3 runtime library for C++.'
   s.homepage = 'https://github.com/google/protobuf'
   s.license  = '3-Clause BSD License'
index 3f1d4a6..4f2dbc6 100755 (executable)
@@ -70,18 +70,26 @@ also sets up an `add_subdirectory()` rule for you. This causes gRPC to be
 built as part of your project.
 
 ```cmake
+cmake_minimum_required(VERSION 3.15)
+project(my_project)
+
 include(FetchContent)
 FetchContent_Declare(
   gRPC
   GIT_REPOSITORY https://github.com/grpc/grpc
-  GIT_TAG        v1.25.0
+  GIT_TAG        RELEASE_TAG_HERE  # e.g v1.28.0
 )
+set(FETCHCONTENT_QUIET OFF)
 FetchContent_MakeAvailable(gRPC)
 
 add_executable(my_exe my_exe.cc)
 target_link_libraries(my_exe grpc++)
 ```
 
+Note that you need to
+[install the prerequisites](../../BUILDING.md#pre-requisites)
+before building gRPC.
+
 ### git submodule
 If you cannot use FetchContent, another approach is to add the gRPC source tree
 to your project as a
index c821e10..8c6fd51 100644 (file)
@@ -18,6 +18,8 @@
 
 #include <grpc/support/alloc.h>
 #include <grpcpp/security/tls_credentials_options.h>
+
+#include "absl/container/inlined_vector.h"
 #include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h"
 #include "src/cpp/common/tls_credentials_options_util.h"
 
@@ -111,7 +113,7 @@ void TlsCredentialReloadArg::set_key_materials(
     c_arg_->key_materials_config = grpc_tls_key_materials_config_create();
   }
   /** Convert |pem_key_cert_pair_list| to an inlined vector of ssl pairs. **/
-  ::grpc_core::InlinedVector<::grpc_core::PemKeyCertPair, 1>
+  ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1>
       c_pem_key_cert_pair_list;
   for (const auto& key_cert_pair : pem_key_cert_pair_list) {
     c_pem_key_cert_pair_list.emplace_back(
@@ -128,7 +130,7 @@ void TlsCredentialReloadArg::set_key_materials_config(
     c_arg_->key_materials_config = nullptr;
     return;
   }
-  ::grpc_core::InlinedVector<::grpc_core::PemKeyCertPair, 1>
+  ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1>
       c_pem_key_cert_pair_list;
   for (const auto& key_cert_pair :
        key_materials_config->pem_key_cert_pair_list()) {
@@ -279,6 +281,25 @@ TlsServerAuthorizationCheckConfig::~TlsServerAuthorizationCheckConfig() {}
 
 /** gRPC TLS credential options API implementation **/
 TlsCredentialsOptions::TlsCredentialsOptions(
+    grpc_tls_server_verification_option server_verification_option,
+    std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config,
+    std::shared_ptr<TlsCredentialReloadConfig> credential_reload_config,
+    std::shared_ptr<TlsServerAuthorizationCheckConfig>
+        server_authorization_check_config)
+    : TlsCredentialsOptions(
+          GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, server_verification_option,
+          std::move(key_materials_config), std::move(credential_reload_config),
+          std::move(server_authorization_check_config)) {}
+
+TlsCredentialsOptions::TlsCredentialsOptions(
+    grpc_ssl_client_certificate_request_type cert_request_type,
+    std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config,
+    std::shared_ptr<TlsCredentialReloadConfig> credential_reload_config)
+    : TlsCredentialsOptions(cert_request_type, GRPC_TLS_SERVER_VERIFICATION,
+                            std::move(key_materials_config),
+                            std::move(credential_reload_config), nullptr) {}
+
+TlsCredentialsOptions::TlsCredentialsOptions(
     grpc_ssl_client_certificate_request_type cert_request_type,
     grpc_tls_server_verification_option server_verification_option,
     std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config,
index 59915e4..2211460 100644 (file)
  *
  */
 
-#include "src/cpp/common/tls_credentials_options_util.h"
+#include "absl/container/inlined_vector.h"
+
 #include <grpcpp/security/tls_credentials_options.h>
+#include "src/cpp/common/tls_credentials_options_util.h"
 
 namespace grpc_impl {
 namespace experimental {
@@ -35,7 +37,7 @@ grpc_tls_key_materials_config* ConvertToCKeyMaterialsConfig(
   }
   grpc_tls_key_materials_config* c_config =
       grpc_tls_key_materials_config_create();
-  ::grpc_core::InlinedVector<::grpc_core::PemKeyCertPair, 1>
+  ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1>
       c_pem_key_cert_pair_list;
   for (const auto& key_cert_pair : config->pem_key_cert_pair_list()) {
     grpc_ssl_pem_key_cert_pair* ssl_pair =
index f9f2abe..cc0fdc6 100644 (file)
@@ -22,5 +22,5 @@
 #include <grpcpp/grpcpp.h>
 
 namespace grpc {
-grpc::string Version() { return "1.29.1"; }
+grpc::string Version() { return "1.30.0"; }
 }  // namespace grpc
index a30e491..2f6c270 100644 (file)
@@ -47,6 +47,7 @@
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/surface/call.h"
 #include "src/core/lib/surface/completion_queue.h"
+#include "src/core/lib/surface/server.h"
 #include "src/cpp/client/create_channel_internal.h"
 #include "src/cpp/server/external_connection_acceptor_impl.h"
 #include "src/cpp/server/health/default_health_check_service.h"
@@ -62,17 +63,6 @@ namespace {
 // max-threads set) to the server builder.
 #define DEFAULT_MAX_SYNC_SERVER_THREADS INT_MAX
 
-// How many callback requests of each method should we pre-register at start
-#define DEFAULT_CALLBACK_REQS_PER_METHOD 512
-
-// What is the (soft) limit for outstanding requests in the server
-#define SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING 30000
-
-// If the number of unmatched requests for a method drops below this amount, try
-// to allocate extra unless it pushes the total number of callbacks above the
-// soft maximum
-#define SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD 128
-
 class DefaultGlobalCallbacks final : public Server::GlobalCallbacks {
  public:
   ~DefaultGlobalCallbacks() override {}
@@ -544,74 +534,61 @@ class Server::SyncRequest final : public grpc::internal::CompletionQueueTag {
   grpc_completion_queue* cq_;
 };
 
-class Server::CallbackRequestBase : public grpc::internal::CompletionQueueTag {
- public:
-  virtual ~CallbackRequestBase() {}
-  virtual bool Request() = 0;
-};
-
 template <class ServerContextType>
-class Server::CallbackRequest final : public Server::CallbackRequestBase {
+class Server::CallbackRequest final
+    : public grpc::internal::CompletionQueueTag {
  public:
   static_assert(
       std::is_base_of<grpc::CallbackServerContext, ServerContextType>::value,
       "ServerContextType must be derived from CallbackServerContext");
 
-  // The constructor needs to know the server for this callback request and its
-  // index in the server's request count array to allow for proper dynamic
-  // requesting of incoming RPCs. For codegen services, the values of method and
-  // method_tag represent the defined characteristics of the method being
-  // requested. For generic services, method and method_tag are nullptr since
-  // these services don't have pre-defined methods or method registration tags.
-  CallbackRequest(Server* server, size_t method_idx,
-                  grpc::internal::RpcServiceMethod* method, void* method_tag)
+  // For codegen services, the value of method represents the defined
+  // characteristics of the method being requested. For generic services, method
+  // is nullptr since these services don't have pre-defined methods.
+  CallbackRequest(Server* server, grpc::internal::RpcServiceMethod* method,
+                  grpc::CompletionQueue* cq,
+                  grpc_core::ServerRegisteredCallAllocation* data)
       : server_(server),
-        method_index_(method_idx),
         method_(method),
-        method_tag_(method_tag),
-        has_request_payload_(
-            method_ != nullptr &&
-            (method->method_type() == grpc::internal::RpcMethod::NORMAL_RPC ||
-             method->method_type() ==
-                 grpc::internal::RpcMethod::SERVER_STREAMING)),
-        cq_(server->CallbackCQ()),
+        has_request_payload_(method->method_type() ==
+                                 grpc::internal::RpcMethod::NORMAL_RPC ||
+                             method->method_type() ==
+                                 grpc::internal::RpcMethod::SERVER_STREAMING),
+        cq_(cq),
         tag_(this) {
-    server_->callback_reqs_outstanding_++;
+    server->Ref();
     Setup();
+    data->tag = &tag_;
+    data->call = &call_;
+    data->initial_metadata = &request_metadata_;
+    data->deadline = &deadline_;
+    data->optional_payload = has_request_payload_ ? &request_payload_ : nullptr;
   }
 
-  ~CallbackRequest() {
-    Clear();
-
-    // The counter of outstanding requests must be decremented
-    // under a lock in case it causes the server shutdown.
-    grpc::internal::MutexLock l(&server_->callback_reqs_mu_);
-    if (--server_->callback_reqs_outstanding_ == 0) {
-      server_->callback_reqs_done_cv_.Signal();
+  // For generic services, method is nullptr since these services don't have
+  // pre-defined methods.
+  CallbackRequest(Server* server, grpc::CompletionQueue* cq,
+                  grpc_core::ServerBatchCallAllocation* data)
+      : server_(server),
+        method_(nullptr),
+        has_request_payload_(false),
+        cq_(cq),
+        tag_(this) {
+    server->Ref();
+    Setup();
+    data->tag = &tag_;
+    data->call = &call_;
+    data->initial_metadata = &request_metadata_;
+    if (!call_details_) {
+      call_details_ = new grpc_call_details;
+      grpc_call_details_init(call_details_);
     }
+    data->details = call_details_;
   }
 
-  bool Request() override {
-    if (method_tag_) {
-      if (grpc_server_request_registered_call(
-              server_->c_server(), method_tag_, &call_, &deadline_,
-              &request_metadata_,
-              has_request_payload_ ? &request_payload_ : nullptr, cq_->cq(),
-              cq_->cq(), static_cast<void*>(&tag_)) != GRPC_CALL_OK) {
-        return false;
-      }
-    } else {
-      if (!call_details_) {
-        call_details_ = new grpc_call_details;
-        grpc_call_details_init(call_details_);
-      }
-      if (grpc_server_request_call(server_->c_server(), &call_, call_details_,
-                                   &request_metadata_, cq_->cq(), cq_->cq(),
-                                   static_cast<void*>(&tag_)) != GRPC_CALL_OK) {
-        return false;
-      }
-    }
-    return true;
+  ~CallbackRequest() {
+    Clear();
+    server_->UnrefWithPossibleNotify();
   }
 
   // Needs specialization to account for different processing of metadata
@@ -655,12 +632,6 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
       GPR_ASSERT(!req_->FinalizeResult(&ignored, &new_ok));
       GPR_ASSERT(ignored == req_);
 
-      int count =
-          static_cast<int>(gpr_atm_no_barrier_fetch_add(
-              &req_->server_
-                   ->callback_unmatched_reqs_count_[req_->method_index_],
-              -1)) -
-          1;
       if (!ok) {
         // The call has been shutdown.
         // Delete its contents to free up the request.
@@ -668,24 +639,6 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
         return;
       }
 
-      // If this was the last request in the list or it is below the soft
-      // minimum and there are spare requests available, set up a new one.
-      if (count == 0 || (count < SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD &&
-                         req_->server_->callback_reqs_outstanding_ <
-                             SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) {
-        auto* new_req = new CallbackRequest<ServerContextType>(
-            req_->server_, req_->method_index_, req_->method_,
-            req_->method_tag_);
-        if (!new_req->Request()) {
-          // The server must have just decided to shutdown.
-          gpr_atm_no_barrier_fetch_add(
-              &new_req->server_
-                   ->callback_unmatched_reqs_count_[new_req->method_index_],
-              -1);
-          delete new_req;
-        }
-      }
-
       // Bind the call, deadline, and metadata from what we got
       req_->ctx_.set_call(req_->call_);
       req_->ctx_.cq_ = req_->cq_;
@@ -740,28 +693,7 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
                           : req_->server_->generic_handler_.get();
       handler->RunHandler(grpc::internal::MethodHandler::HandlerParameter(
           call_, &req_->ctx_, req_->request_, req_->request_status_,
-          req_->handler_data_, [this] {
-            // Recycle this request if there aren't too many outstanding.
-            // Note that we don't have to worry about a case where there
-            // are no requests waiting to match for this method since that
-            // is already taken care of when binding a request to a call.
-            // TODO(vjpai): Also don't recycle this request if the dynamic
-            //              load no longer justifies it. Consider measuring
-            //              dynamic load and setting a target accordingly.
-            if (req_->server_->callback_reqs_outstanding_ <
-                SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING) {
-              req_->Clear();
-              req_->Setup();
-            } else {
-              // We can free up this request because there are too many
-              delete req_;
-              return;
-            }
-            if (!req_->Request()) {
-              // The server must have just decided to shutdown.
-              delete req_;
-            }
-          }));
+          req_->handler_data_, [this] { delete req_; }));
     }
   };
 
@@ -779,8 +711,6 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
   }
 
   void Setup() {
-    gpr_atm_no_barrier_fetch_add(
-        &server_->callback_unmatched_reqs_count_[method_index_], 1);
     grpc_metadata_array_init(&request_metadata_);
     ctx_.Setup(gpr_inf_future(GPR_CLOCK_REALTIME));
     request_payload_ = nullptr;
@@ -790,9 +720,7 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
   }
 
   Server* const server_;
-  const size_t method_index_;
   grpc::internal::RpcServiceMethod* const method_;
-  void* const method_tag_;
   const bool has_request_payload_;
   grpc_byte_buffer* request_payload_;
   void* request_;
@@ -1055,13 +983,6 @@ Server::~Server() {
   }
 
   grpc_server_destroy(server_);
-  for (auto& per_method_count : callback_unmatched_reqs_count_) {
-    // There should be no more unmatched callbacks for any method
-    // as each request is failed by Shutdown. Check that this actually
-    // happened
-    GPR_ASSERT(static_cast<int>(gpr_atm_no_barrier_load(&per_method_count)) ==
-               0);
-  }
 }
 
 void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) {
@@ -1139,17 +1060,16 @@ bool Server::RegisterService(const grpc::string* host, grpc::Service* service) {
         value->AddSyncMethod(method.get(), method_registration_tag);
       }
     } else {
-      // a callback method. Register at least some callback requests
-      callback_unmatched_reqs_count_.push_back(0);
-      auto method_index = callback_unmatched_reqs_count_.size() - 1;
-      // TODO(vjpai): Register these dynamically based on need
-      for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) {
-        callback_reqs_to_start_.push_back(
-            new CallbackRequest<grpc::CallbackServerContext>(
-                this, method_index, method.get(), method_registration_tag));
-      }
-      // Enqueue it so that it will be Request'ed later after all request
-      // matchers are created at core server startup
+      has_callback_methods_ = true;
+      grpc::internal::RpcServiceMethod* method_value = method.get();
+      grpc::CompletionQueue* cq = CallbackCQ();
+      grpc_core::SetServerRegisteredMethodAllocator(
+          server_, cq->cq(), method_registration_tag, [this, cq, method_value] {
+            grpc_core::ServerRegisteredCallAllocation result;
+            new CallbackRequest<grpc::CallbackServerContext>(this, method_value,
+                                                             cq, &result);
+            return result;
+          });
     }
 
     method_name = method->name();
@@ -1183,14 +1103,12 @@ void Server::RegisterCallbackGenericService(
   has_callback_generic_service_ = true;
   generic_handler_.reset(service->Handler());
 
-  callback_unmatched_reqs_count_.push_back(0);
-  auto method_index = callback_unmatched_reqs_count_.size() - 1;
-  // TODO(vjpai): Register these dynamically based on need
-  for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) {
-    callback_reqs_to_start_.push_back(
-        new CallbackRequest<grpc::GenericCallbackServerContext>(
-            this, method_index, nullptr, nullptr));
-  }
+  grpc::CompletionQueue* cq = CallbackCQ();
+  grpc_core::SetServerBatchMethodAllocator(server_, cq->cq(), [this, cq] {
+    grpc_core::ServerBatchCallAllocation result;
+    new CallbackRequest<grpc::GenericCallbackServerContext>(this, cq, &result);
+    return result;
+  });
 }
 
 int Server::AddListeningPort(const grpc::string& addr,
@@ -1201,6 +1119,31 @@ int Server::AddListeningPort(const grpc::string& addr,
   return port;
 }
 
+void Server::Ref() {
+  shutdown_refs_outstanding_.fetch_add(1, std::memory_order_relaxed);
+}
+
+void Server::UnrefWithPossibleNotify() {
+  if (GPR_UNLIKELY(shutdown_refs_outstanding_.fetch_sub(
+                       1, std::memory_order_acq_rel) == 1)) {
+    // No refs outstanding means that shutdown has been initiated and no more
+    // callback requests are outstanding.
+    grpc::internal::MutexLock lock(&mu_);
+    GPR_ASSERT(shutdown_);
+    shutdown_done_ = true;
+    shutdown_done_cv_.Signal();
+  }
+}
+
+void Server::UnrefAndWaitLocked() {
+  if (GPR_UNLIKELY(shutdown_refs_outstanding_.fetch_sub(
+                       1, std::memory_order_acq_rel) == 1)) {
+    shutdown_done_ = true;
+    return;  // no need to wait on CV since done condition already set
+  }
+  shutdown_done_cv_.WaitUntil(&mu_, [this] { return shutdown_done_; });
+}
+
 void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) {
   GPR_ASSERT(!started_);
   global_callbacks_->PreServerStart(this);
@@ -1236,7 +1179,7 @@ void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) {
   // If this server uses callback methods, then create a callback generic
   // service to handle any unimplemented methods using the default reactor
   // creator
-  if (!callback_reqs_to_start_.empty() && !has_callback_generic_service_) {
+  if (has_callback_methods_ && !has_callback_generic_service_) {
     unimplemented_service_.reset(new grpc::CallbackGenericService);
     RegisterCallbackGenericService(unimplemented_service_.get());
   }
@@ -1276,11 +1219,6 @@ void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) {
     value->Start();
   }
 
-  for (auto* cbreq : callback_reqs_to_start_) {
-    GPR_ASSERT(cbreq->Request());
-  }
-  callback_reqs_to_start_.clear();
-
   if (default_health_check_service_impl != nullptr) {
     default_health_check_service_impl->StartServingThread();
   }
@@ -1333,23 +1271,8 @@ void Server::ShutdownInternal(gpr_timespec deadline) {
     value->Wait();
   }
 
-  // Wait for all outstanding callback requests to complete
-  // (whether waiting for a match or already active).
-  // We know that no new requests will be created after this point
-  // because they are only created at server startup time or when
-  // we have a successful match on a request. During the shutdown phase,
-  // requests that have not yet matched will be failed rather than
-  // allowed to succeed, which will cause the server to delete the
-  // request and decrement the count. Possibly a request will match before
-  // the shutdown but then find that shutdown has already started by the
-  // time it tries to register a new request. In that case, the registration
-  // will report a failure, indicating a shutdown and again we won't end
-  // up incrementing the counter.
-  {
-    grpc::internal::MutexLock cblock(&callback_reqs_mu_);
-    callback_reqs_done_cv_.WaitUntil(
-        &callback_reqs_mu_, [this] { return callback_reqs_outstanding_ == 0; });
-  }
+  // Drop the shutdown ref and wait for all other refs to drop as well.
+  UnrefAndWaitLocked();
 
   // Shutdown the callback CQ. The CQ is owned by its own shutdown tag, so it
   // will delete itself at true shutdown.
@@ -1421,15 +1344,17 @@ grpc::CompletionQueue* Server::CallbackCQ() {
   // TODO(vjpai): Consider using a single global CQ for the default CQ
   // if there is no explicit per-server CQ registered
   grpc::internal::MutexLock l(&mu_);
-  if (callback_cq_ == nullptr) {
-    auto* shutdown_callback = new grpc::ShutdownCallback;
-    callback_cq_ = new grpc::CompletionQueue(grpc_completion_queue_attributes{
-        GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING,
-        shutdown_callback});
-
-    // Transfer ownership of the new cq to its own shutdown callback
-    shutdown_callback->TakeCQ(callback_cq_);
+  if (callback_cq_ != nullptr) {
+    return callback_cq_;
   }
+  auto* shutdown_callback = new grpc::ShutdownCallback;
+  callback_cq_ = new grpc::CompletionQueue(grpc_completion_queue_attributes{
+      GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING,
+      shutdown_callback});
+
+  // Transfer ownership of the new cq to its own shutdown callback
+  shutdown_callback->TakeCQ(callback_cq_);
+
   return callback_cq_;
 }
 
index 400365a..b115999 100644 (file)
@@ -135,7 +135,7 @@ following stanza under the `<Project>` xml node:
 
 ```xml
   <ItemGroup>
-    <Protobuf Include="**/*.proto" OutputDir="%(RelativePath)" CompileOutputs="false"  />
+    <Protobuf Include="**/*.proto" OutputDir="%(RelativeDir)" CompileOutputs="false"  />
   </ItemGroup>
 ```
 
@@ -144,7 +144,7 @@ and its subdirectories (`**`) include all files matching the wildcard `*.proto`.
 You can instead selectively include your files or selectively exclude files from
 the glob pattern; [MSBuild documentation explains
 that](https://docs.microsoft.com/visualstudio/msbuild/msbuild-items). The
-`OutputDir="%(RelativePath)"` orders the output directory for each .cs file be
+`OutputDir="%(RelativeDir)"` orders the output directory for each .cs file be
 same as the corresponding .proto directory. Finally, `CompileOutputs="false"`
 prevents compiling the generated files into an assembly.
 
@@ -188,7 +188,7 @@ directories according to their service use, for example:
 
 ```xml
   <ItemGroup>
-    <Protobuf Include="**/*.proto" OutputDir="%(RelativePath)"
+    <Protobuf Include="**/*.proto" OutputDir="%(RelativeDir)"
               CompileOutputs="false" GrpcServices="None" />
     <Protobuf Update="**/hello/*.proto;**/bye/*.proto" GrpcServices="Both" />
   </ItemGroup>
index 823ca9a..ccf0468 100644 (file)
@@ -31,9 +31,9 @@ namespace Grpc.Core
     public interface IAsyncStreamWriter<in T>
     {
         /// <summary>
-        /// Writes a single asynchronously. Only one write can be pending at a time.
+        /// Writes a message asynchronously. Only one write can be pending at a time.
         /// </summary>
-        /// <param name="message">the message to be written. Cannot be null.</param>
+        /// <param name="message">The message to be written. Cannot be null.</param>
         Task WriteAsync(T message);
 
         /// <summary>
index f7f0ae1..9c56476 100644 (file)
@@ -75,7 +75,72 @@ namespace Grpc.Core
             return this;
         }
 
-        // TODO: add support for access by key
+        /// <summary>
+        /// Gets the last metadata entry with the specified key.
+        /// If there are no matching entries then <c>null</c> is returned.
+        /// </summary>
+        public Entry Get(string key)
+        {
+            for (int i = entries.Count - 1; i >= 0; i--)
+            {
+                if (entries[i].Key == key)
+                {
+                    return entries[i];
+                }
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// Gets the string value of the last metadata entry with the specified key.
+        /// If the metadata entry is binary then an exception is thrown.
+        /// If there are no matching entries then <c>null</c> is returned.
+        /// </summary>
+        public string GetValue(string key)
+        {
+            return Get(key)?.Value;
+        }
+
+        /// <summary>
+        /// Gets the bytes value of the last metadata entry with the specified key.
+        /// If the metadata entry is not binary the string value will be returned as ASCII encoded bytes.
+        /// If there are no matching entries then <c>null</c> is returned.
+        /// </summary>
+        public byte[] GetValueBytes(string key)
+        {
+            return Get(key)?.ValueBytes;
+        }
+
+        /// <summary>
+        /// Gets all metadata entries with the specified key.
+        /// </summary>
+        public IEnumerable<Entry> GetAll(string key)
+        {
+            for (int i = 0; i < entries.Count; i++)
+            {
+                if (entries[i].Key == key)
+                {
+                    yield return entries[i];
+                }
+            }
+        }
+
+        /// <summary>
+        /// Adds a new ASCII-valued metadata entry. See <c>Metadata.Entry</c> constructor for params.
+        /// </summary>
+        public void Add(string key, string value)
+        {
+            Add(new Entry(key, value));
+        }
+
+        /// <summary>
+        /// Adds a new binary-valued metadata entry. See <c>Metadata.Entry</c> constructor for params.
+        /// </summary>
+        public void Add(string key, byte[] valueBytes)
+        {
+            Add(new Entry(key, valueBytes));
+        }
 
         #region IList members
 
@@ -136,22 +201,6 @@ namespace Grpc.Core
         }
 
         /// <summary>
-        /// Adds a new ASCII-valued metadata entry. See <c>Metadata.Entry</c> constructor for params.
-        /// </summary>
-        public void Add(string key, string value)
-        {
-            Add(new Entry(key, value));
-        }
-
-        /// <summary>
-        /// Adds a new binary-valued metadata entry. See <c>Metadata.Entry</c> constructor for params.
-        /// </summary>
-        public void Add(string key, byte[] valueBytes)
-        {
-            Add(new Entry(key, valueBytes));
-        }
-
-        /// <summary>
         /// <see cref="T:IList`1"/>
         /// </summary>
         public void Clear()
@@ -280,6 +329,7 @@ namespace Grpc.Core
 
             /// <summary>
             /// Gets the binary value of this metadata entry.
+            /// If the metadata entry is not binary the string value will be returned as ASCII encoded bytes.
             /// </summary>
             public byte[] ValueBytes
             {
@@ -299,13 +349,14 @@ namespace Grpc.Core
 
             /// <summary>
             /// Gets the string value of this metadata entry.
+            /// If the metadata entry is binary then an exception is thrown.
             /// </summary>
             public string Value
             {
                 get
                 {
                     GrpcPreconditions.CheckState(!IsBinary, "Cannot access string value of a binary metadata entry");
-                    return value ?? EncodingASCII.GetString(valueBytes);
+                    return value;
                 }
             }
 
index b1a030b..c13f9d8 100644 (file)
@@ -14,6 +14,8 @@
 // limitations under the License.
 #endregion
 
+using System;
+
 namespace Grpc.Core
 {
     /// <summary>
@@ -31,48 +33,63 @@ namespace Grpc.Core
         /// </summary>
         public static readonly Status DefaultCancelled = new Status(StatusCode.Cancelled, "");
 
-        readonly StatusCode statusCode;
-        readonly string detail;
-
         /// <summary>
         /// Creates a new instance of <c>Status</c>.
         /// </summary>
         /// <param name="statusCode">Status code.</param>
         /// <param name="detail">Detail.</param>
-        public Status(StatusCode statusCode, string detail)
+        public Status(StatusCode statusCode, string detail) : this(statusCode, detail, null)
         {
-            this.statusCode = statusCode;
-            this.detail = detail;
         }
 
         /// <summary>
-        /// Gets the gRPC status code. OK indicates success, all other values indicate an error.
+        /// Creates a new instance of <c>Status</c>.
+        /// Users should not use this constructor, except for creating instances for testing.
+        /// The debug error string should only be populated by gRPC internals.
+        /// Note: experimental API that can change or be removed without any prior notice.
         /// </summary>
-        public StatusCode StatusCode
+        /// <param name="statusCode">Status code.</param>
+        /// <param name="detail">Detail.</param>
+        /// <param name="debugException">Optional internal error details.</param>
+        public Status(StatusCode statusCode, string detail, Exception debugException)
         {
-            get
-            {
-                return statusCode;
-            }
+            StatusCode = statusCode;
+            Detail = detail;
+            DebugException = debugException;
         }
 
         /// <summary>
+        /// Gets the gRPC status code. OK indicates success, all other values indicate an error.
+        /// </summary>
+        public StatusCode StatusCode { get; }
+
+        /// <summary>
         /// Gets the detail.
         /// </summary>
-        public string Detail
-        {
-            get
-            {
-                return detail;
-            }
-        }
+        public string Detail { get; }
+
+        /// <summary>
+        /// In case of an error, this field may contain additional error details to help with debugging.
+        /// This field will be only populated on a client and its value is generated locally,
+        /// based on the internal state of the gRPC client stack (i.e. the value is never sent over the wire).
+        /// Note that this field is available only for debugging purposes, the application logic should
+        /// never rely on values of this field (it should use <c>StatusCode</c> and <c>Detail</c> instead).
+        /// Example: when a client fails to connect to a server, this field may provide additional details
+        /// why the connection to the server has failed.
+        /// Note: experimental API that can change or be removed without any prior notice.
+        /// </summary>
+        public Exception DebugException { get; }
 
         /// <summary>
         /// Returns a <see cref="System.String"/> that represents the current <see cref="Grpc.Core.Status"/>.
         /// </summary>
         public override string ToString()
         {
-            return string.Format("Status(StatusCode={0}, Detail=\"{1}\")", statusCode, detail);
+            if (DebugException != null)
+            {
+                return $"Status(StatusCode=\"{StatusCode}\", Detail=\"{Detail}\", DebugException=\"{DebugException}\")";
+            }
+            return $"Status(StatusCode=\"{StatusCode}\", Detail=\"{Detail}\")";
         }
     }
 }
index 36c0a49..f3ec98c 100644 (file)
@@ -33,11 +33,11 @@ namespace Grpc.Core
         /// <summary>
         /// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
         /// </summary>
-        public const string CurrentAssemblyFileVersion = "2.29.1.0";
+        public const string CurrentAssemblyFileVersion = "2.30.0.0";
 
         /// <summary>
         /// Current version of gRPC C#
         /// </summary>
-        public const string CurrentVersion = "2.29.1";
+        public const string CurrentVersion = "2.30.0";
     }
 }
index 331c332..7ff639c 100644 (file)
@@ -140,6 +140,26 @@ namespace Grpc.Core.Tests
         }
 
         [Test]
+        public void UnaryCall_StatusDebugErrorStringNotTransmittedFromServer()
+        {
+            helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
+            {
+                context.Status = new Status(StatusCode.Unauthenticated, "", new CoreErrorDetailException("this DebugErrorString value should not be transmitted to the client"));
+                return Task.FromResult("");
+            });
+
+            var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
+            Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode);
+            StringAssert.Contains("Error received from peer", ex.Status.DebugException.Message, "Is \"Error received from peer\" still a valid substring to search for in the client-generated error message from C-core?");
+            Assert.AreEqual(0, ex.Trailers.Count);
+
+            var ex2 = Assert.ThrowsAsync<RpcException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"));
+            Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode);
+            StringAssert.Contains("Error received from peer", ex2.Status.DebugException.Message, "Is \"Error received from peer\" still a valid substring to search for in the client-generated error message from C-core?");
+            Assert.AreEqual(0, ex2.Trailers.Count);
+        }
+
+        [Test]
         public void UnaryCall_ServerHandlerSetsStatusAndTrailers()
         {
             helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
index 0b5f1c7..56112fb 100644 (file)
@@ -18,7 +18,9 @@
 
 using System;
 using System.Diagnostics;
+using System.Linq;
 using System.Runtime.InteropServices;
+using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using Grpc.Core;
@@ -242,6 +244,110 @@ namespace Grpc.Core.Tests
             Assert.Throws<InvalidOperationException>(() => metadata.Remove(metadata[0]));
         }
 
+        [Test]
+        public void GetAll()
+        {
+            var metadata = new Metadata
+            {
+                { "abc", "abc-value1" },
+                { "abc", "abc-value2" },
+                { "xyz", "xyz-value1" },
+            };
+
+            var abcEntries = metadata.GetAll("abc").ToList();
+            Assert.AreEqual(2, abcEntries.Count);
+            Assert.AreEqual("abc-value1", abcEntries[0].Value);
+            Assert.AreEqual("abc-value2", abcEntries[1].Value);
+
+            var xyzEntries = metadata.GetAll("xyz").ToList();
+            Assert.AreEqual(1, xyzEntries.Count);
+            Assert.AreEqual("xyz-value1", xyzEntries[0].Value);
+        }
+
+        [Test]
+        public void Get()
+        {
+            var metadata = new Metadata
+            {
+                { "abc", "abc-value1" },
+                { "abc", "abc-value2" },
+                { "xyz", "xyz-value1" },
+            };
+
+            var abcEntry = metadata.Get("abc");
+            Assert.AreEqual("abc-value2", abcEntry.Value);
+
+            var xyzEntry = metadata.Get("xyz");
+            Assert.AreEqual("xyz-value1", xyzEntry.Value);
+
+            var notFound = metadata.Get("not-found");
+            Assert.AreEqual(null, notFound);
+        }
+
+        [Test]
+        public void GetValue()
+        {
+            var metadata = new Metadata
+            {
+                { "abc", "abc-value1" },
+                { "abc", "abc-value2" },
+                { "xyz", "xyz-value1" },
+                { "xyz-bin", Encoding.ASCII.GetBytes("xyz-value1") },
+            };
+
+            var abcValue = metadata.GetValue("abc");
+            Assert.AreEqual("abc-value2", abcValue);
+
+            var xyzValue = metadata.GetValue("xyz");
+            Assert.AreEqual("xyz-value1", xyzValue);
+
+            var notFound = metadata.GetValue("not-found");
+            Assert.AreEqual(null, notFound);
+        }
+
+        [Test]
+        public void GetValue_BytesValue()
+        {
+            var metadata = new Metadata
+            {
+                { "xyz-bin", Encoding.ASCII.GetBytes("xyz-value1") },
+            };
+
+            Assert.Throws<InvalidOperationException>(() => metadata.GetValue("xyz-bin"));
+        }
+
+        [Test]
+        public void GetValueBytes()
+        {
+            var metadata = new Metadata
+            {
+                { "abc-bin", Encoding.ASCII.GetBytes("abc-value1") },
+                { "abc-bin", Encoding.ASCII.GetBytes("abc-value2") },
+                { "xyz-bin", Encoding.ASCII.GetBytes("xyz-value1") },
+            };
+
+            var abcValue = metadata.GetValueBytes("abc-bin");
+            Assert.AreEqual(Encoding.ASCII.GetBytes("abc-value2"), abcValue);
+
+            var xyzValue = metadata.GetValueBytes("xyz-bin");
+            Assert.AreEqual(Encoding.ASCII.GetBytes("xyz-value1"), xyzValue);
+
+            var notFound = metadata.GetValueBytes("not-found");
+            Assert.AreEqual(null, notFound);
+        }
+
+        [Test]
+        public void GetValueBytes_StringValue()
+        {
+            var metadata = new Metadata
+            {
+                { "xyz", "xyz-value1" },
+            };
+
+            var xyzValue = metadata.GetValueBytes("xyz");
+            Assert.AreEqual(Encoding.ASCII.GetBytes("xyz-value1"), xyzValue);
+        }
+
         private Metadata CreateMetadata()
         {
             return new Metadata
index 50a6268..025f93e 100644 (file)
@@ -92,7 +92,8 @@ namespace Grpc.Core.Internal
             UIntPtr detailsLength;
             IntPtr detailsPtr = Native.grpcsharp_batch_context_recv_status_on_client_details(this, out detailsLength);
             string details = MarshalUtils.PtrToStringUTF8(detailsPtr, (int)detailsLength.ToUInt32());
-            var status = new Status(Native.grpcsharp_batch_context_recv_status_on_client_status(this), details);
+            string debugErrorString = Marshal.PtrToStringAnsi(Native.grpcsharp_batch_context_recv_status_on_client_error_string(this));
+            var status = new Status(Native.grpcsharp_batch_context_recv_status_on_client_status(this), details, debugErrorString != null ? new CoreErrorDetailException(debugErrorString) : null);
 
             IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_recv_status_on_client_trailing_metadata(this);
             var metadata = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr);
diff --git a/src/csharp/Grpc.Core/Internal/CoreErrorDetailException.cs b/src/csharp/Grpc.Core/Internal/CoreErrorDetailException.cs
new file mode 100644 (file)
index 0000000..ca68864
--- /dev/null
@@ -0,0 +1,35 @@
+#region Copyright notice and license
+
+// Copyright 2019 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core.Internal
+{
+    /// <summary>
+    /// Represents error details provides by C-core's debug_error_string
+    /// </summary>
+    internal class CoreErrorDetailException : Exception
+    {
+        public CoreErrorDetailException(string message) : base(message)
+        {
+        }
+    }
+}
index c724b30..8b60268 100644 (file)
@@ -43,6 +43,7 @@ namespace Grpc.Core.Internal
         public readonly Delegates.grpcsharp_batch_context_recv_message_next_slice_peek_delegate grpcsharp_batch_context_recv_message_next_slice_peek;
         public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate grpcsharp_batch_context_recv_status_on_client_status;
         public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate grpcsharp_batch_context_recv_status_on_client_details;
+        public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_error_string_delegate grpcsharp_batch_context_recv_status_on_client_error_string;
         public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate grpcsharp_batch_context_recv_status_on_client_trailing_metadata;
         public readonly Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate grpcsharp_batch_context_recv_close_on_server_cancelled;
         public readonly Delegates.grpcsharp_batch_context_reset_delegate grpcsharp_batch_context_reset;
@@ -151,6 +152,7 @@ namespace Grpc.Core.Internal
             this.grpcsharp_batch_context_recv_message_next_slice_peek = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_next_slice_peek_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_error_string = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_error_string_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_recv_close_on_server_cancelled = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate>(library);
             this.grpcsharp_batch_context_reset = GetMethodDelegate<Delegates.grpcsharp_batch_context_reset_delegate>(library);
@@ -258,6 +260,7 @@ namespace Grpc.Core.Internal
             this.grpcsharp_batch_context_recv_message_next_slice_peek = DllImportsFromStaticLib.grpcsharp_batch_context_recv_message_next_slice_peek;
             this.grpcsharp_batch_context_recv_status_on_client_status = DllImportsFromStaticLib.grpcsharp_batch_context_recv_status_on_client_status;
             this.grpcsharp_batch_context_recv_status_on_client_details = DllImportsFromStaticLib.grpcsharp_batch_context_recv_status_on_client_details;
+            this.grpcsharp_batch_context_recv_status_on_client_error_string = DllImportsFromStaticLib.grpcsharp_batch_context_recv_status_on_client_error_string;
             this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = DllImportsFromStaticLib.grpcsharp_batch_context_recv_status_on_client_trailing_metadata;
             this.grpcsharp_batch_context_recv_close_on_server_cancelled = DllImportsFromStaticLib.grpcsharp_batch_context_recv_close_on_server_cancelled;
             this.grpcsharp_batch_context_reset = DllImportsFromStaticLib.grpcsharp_batch_context_reset;
@@ -365,6 +368,7 @@ namespace Grpc.Core.Internal
             this.grpcsharp_batch_context_recv_message_next_slice_peek = DllImportsFromSharedLib.grpcsharp_batch_context_recv_message_next_slice_peek;
             this.grpcsharp_batch_context_recv_status_on_client_status = DllImportsFromSharedLib.grpcsharp_batch_context_recv_status_on_client_status;
             this.grpcsharp_batch_context_recv_status_on_client_details = DllImportsFromSharedLib.grpcsharp_batch_context_recv_status_on_client_details;
+            this.grpcsharp_batch_context_recv_status_on_client_error_string = DllImportsFromSharedLib.grpcsharp_batch_context_recv_status_on_client_error_string;
             this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = DllImportsFromSharedLib.grpcsharp_batch_context_recv_status_on_client_trailing_metadata;
             this.grpcsharp_batch_context_recv_close_on_server_cancelled = DllImportsFromSharedLib.grpcsharp_batch_context_recv_close_on_server_cancelled;
             this.grpcsharp_batch_context_reset = DllImportsFromSharedLib.grpcsharp_batch_context_reset;
@@ -475,6 +479,7 @@ namespace Grpc.Core.Internal
             public delegate int grpcsharp_batch_context_recv_message_next_slice_peek_delegate(BatchContextSafeHandle ctx, out UIntPtr sliceLen, out IntPtr sliceDataPtr);
             public delegate StatusCode grpcsharp_batch_context_recv_status_on_client_status_delegate(BatchContextSafeHandle ctx);
             public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_details_delegate(BatchContextSafeHandle ctx, out UIntPtr detailsLength);
+            public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_error_string_delegate(BatchContextSafeHandle ctx);
             public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate(BatchContextSafeHandle ctx);
             public delegate int grpcsharp_batch_context_recv_close_on_server_cancelled_delegate(BatchContextSafeHandle ctx);
             public delegate void grpcsharp_batch_context_reset_delegate(BatchContextSafeHandle ctx);
@@ -606,6 +611,9 @@ namespace Grpc.Core.Internal
             public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx, out UIntPtr detailsLength);
             
             [DllImport(ImportName)]
+            public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_error_string(BatchContextSafeHandle ctx);
+            
+            [DllImport(ImportName)]
             public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx);
             
             [DllImport(ImportName)]
@@ -923,6 +931,9 @@ namespace Grpc.Core.Internal
             public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx, out UIntPtr detailsLength);
             
             [DllImport(ImportName)]
+            public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_error_string(BatchContextSafeHandle ctx);
+            
+            [DllImport(ImportName)]
             public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx);
             
             [DllImport(ImportName)]
index 9c027de..35285b6 100755 (executable)
@@ -8,7 +8,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-18618-05" PrivateAssets="All" />
+    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
   </ItemGroup>
 
 </Project>
index 5317609..3324e8e 100644 (file)
@@ -1,6 +1,15 @@
 ï»¿<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
+  <!-- 
+    'Grpc_SkipNativeLibsCopy' should not be enabled in normal use.
+
+    It only exists to support special scenarios where user wants to copy the native libraries
+    to output directory themselves, in a separate build step or script.
+
+    Only use this flag if you really know what you're doing. It's your responsibility to ensure that matching versions of 
+    the Grpc.Core.dll assembly and the native libraries are used at all times.
+  -->
+  <ItemGroup Condition="'$(Grpc_SkipNativeLibsCopy)' != 'true'">
     <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win\native\grpc_csharp_ext.x86.dll">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
       <Link>grpc_csharp_ext.x86.dll</Link>
diff --git a/src/csharp/Grpc.IntegrationTesting.XdsClient/.gitignore b/src/csharp/Grpc.IntegrationTesting.XdsClient/.gitignore
new file mode 100644 (file)
index 0000000..a382af2
--- /dev/null
@@ -0,0 +1,3 @@
+bin
+obj
+
diff --git a/src/csharp/Grpc.IntegrationTesting.XdsClient/Grpc.IntegrationTesting.XdsClient.csproj b/src/csharp/Grpc.IntegrationTesting.XdsClient/Grpc.IntegrationTesting.XdsClient.csproj
new file mode 100755 (executable)
index 0000000..a5baf96
--- /dev/null
@@ -0,0 +1,24 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <Import Project="..\Grpc.Core\Common.csproj.include" />
+
+  <PropertyGroup>
+    <TargetFrameworks>net45;netcoreapp2.1</TargetFrameworks>
+    <OutputType>Exe</OutputType>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="../Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj" />
+  </ItemGroup>
+
+  <ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
+    <Reference Include="System" />
+    <Reference Include="Microsoft.CSharp" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Include="..\Grpc.Core.Api\Version.cs" />
+  </ItemGroup>
+
+</Project>
diff --git a/src/csharp/Grpc.IntegrationTesting.XdsClient/Program.cs b/src/csharp/Grpc.IntegrationTesting.XdsClient/Program.cs
new file mode 100644 (file)
index 0000000..1921443
--- /dev/null
@@ -0,0 +1,31 @@
+#region Copyright notice and license
+
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using System;
+using Grpc.IntegrationTesting;
+
+namespace Grpc.IntegrationTesting.XdsClient
+{
+    class Program
+    {
+        public static void Main(string[] args)
+        {
+            XdsInteropClient.Run(args);
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting.XdsClient/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.XdsClient/Properties/AssemblyInfo.cs
new file mode 100644 (file)
index 0000000..80289be
--- /dev/null
@@ -0,0 +1,29 @@
+#region Copyright notice and license
+
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Grpc.IntegrationTesting.XdsClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
diff --git a/src/csharp/Grpc.IntegrationTesting/XdsInteropClient.cs b/src/csharp/Grpc.IntegrationTesting/XdsInteropClient.cs
new file mode 100644 (file)
index 0000000..b9d7799
--- /dev/null
@@ -0,0 +1,300 @@
+#region Copyright notice and license
+
+// Copyright 2020 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
+
+using CommandLine;
+using Grpc.Core;
+using Grpc.Core.Logging;
+using Grpc.Core.Internal;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+    public class XdsInteropClient
+    {
+        internal class ClientOptions
+        {
+            [Option("num_channels", Default = 1)]
+            public int NumChannels { get; set; }
+
+            [Option("qps", Default = 1)]
+
+            // The desired QPS per channel.
+            public int Qps { get; set; }
+
+            [Option("server", Default = "localhost:8080")]
+            public string Server { get; set; }
+
+            [Option("stats_port", Default = 8081)]
+            public int StatsPort { get; set; }
+
+            [Option("rpc_timeout_sec", Default = 30)]
+            public int RpcTimeoutSec { get; set; }
+
+            [Option("print_response", Default = false)]
+            public bool PrintResponse { get; set; }
+        }
+
+        ClientOptions options;
+
+        StatsWatcher statsWatcher = new StatsWatcher();
+
+        // make watcher accessible by tests
+        internal StatsWatcher StatsWatcher => statsWatcher;
+
+        internal XdsInteropClient(ClientOptions options)
+        {
+            this.options = options;
+        }
+
+        public static void Run(string[] args)
+        {
+            GrpcEnvironment.SetLogger(new ConsoleLogger());
+            var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
+                .WithNotParsed(errors => Environment.Exit(1))
+                .WithParsed(options =>
+                {
+                    var xdsInteropClient = new XdsInteropClient(options);
+                    xdsInteropClient.RunAsync().Wait();
+                });
+        }
+
+        private async Task RunAsync()
+        {
+            var server = new Server
+            {
+                Services = { LoadBalancerStatsService.BindService(new LoadBalancerStatsServiceImpl(statsWatcher)) }
+            };
+
+            string host = "0.0.0.0";
+            server.Ports.Add(host, options.StatsPort, ServerCredentials.Insecure);
+            Console.WriteLine($"Running server on {host}:{options.StatsPort}");
+            server.Start();
+
+            var cancellationTokenSource = new CancellationTokenSource();
+            await RunChannelsAsync(cancellationTokenSource.Token);
+
+            await server.ShutdownAsync();
+        }
+
+        // method made internal to make it runnable by tests
+        internal async Task RunChannelsAsync(CancellationToken cancellationToken)
+        {
+            var channelTasks = new List<Task>();
+            for (int channelId = 0; channelId < options.NumChannels; channelId++)
+            {
+                var channelTask = RunSingleChannelAsync(channelId, cancellationToken);
+                channelTasks.Add(channelTask);
+            }
+
+            for (int channelId = 0; channelId < options.NumChannels; channelId++)
+            {
+                await channelTasks[channelId];
+            }
+        }
+
+        private async Task RunSingleChannelAsync(int channelId, CancellationToken cancellationToken)
+        {
+            Console.WriteLine($"Starting channel {channelId}");
+            var channel = new Channel(options.Server, ChannelCredentials.Insecure);
+            var client = new TestService.TestServiceClient(channel);
+
+            var inflightTasks = new List<Task>();
+            long rpcsStarted = 0;
+            var stopwatch = Stopwatch.StartNew();
+            while (!cancellationToken.IsCancellationRequested)
+            {
+                inflightTasks.Add(RunSingleRpcAsync(client, cancellationToken));
+                rpcsStarted++;
+
+                // only cleanup calls that have already completed, calls that are still inflight will be cleaned up later.
+                await CleanupCompletedTasksAsync(inflightTasks);
+
+                Console.WriteLine($"Currently {inflightTasks.Count} in-flight RPCs");
+
+                // if needed, wait a bit before we start the next RPC.
+                int nextDueInMillis = (int) Math.Max(0, (1000 * rpcsStarted / options.Qps) - stopwatch.ElapsedMilliseconds);
+                if (nextDueInMillis > 0)
+                {
+                    await Task.Delay(nextDueInMillis);
+                }
+            }
+            stopwatch.Stop();
+
+            Console.WriteLine($"Shutting down channel {channelId}");
+            await channel.ShutdownAsync();
+            Console.WriteLine($"Channel shutdown {channelId}");
+        }
+
+        private async Task RunSingleRpcAsync(TestService.TestServiceClient client, CancellationToken cancellationToken)
+        {
+            long rpcId = statsWatcher.RpcIdGenerator.Increment();
+            try
+            {
+                Console.WriteLine($"Starting RPC {rpcId}.");
+                var response = await client.UnaryCallAsync(new SimpleRequest(),
+                    new CallOptions(cancellationToken: cancellationToken, deadline: DateTime.UtcNow.AddSeconds(options.RpcTimeoutSec)));
+                
+                statsWatcher.OnRpcComplete(rpcId, response.Hostname);
+                if (options.PrintResponse)
+                {
+                    Console.WriteLine($"Got response {response}");
+                }
+                Console.WriteLine($"RPC {rpcId} succeeded ");
+            }
+            catch (RpcException ex)
+            {
+                statsWatcher.OnRpcComplete(rpcId, null);
+                Console.WriteLine($"RPC {rpcId} failed: {ex}");
+            }
+        }
+
+        private async Task CleanupCompletedTasksAsync(List<Task> tasks)
+        {
+            var toRemove = new List<Task>();
+            foreach (var task in tasks)
+            {
+                if (task.IsCompleted)
+                {
+                    // awaiting tasks that have already completed should be instantaneous
+                    await task;
+                }
+                toRemove.Add(task);
+            }
+            foreach (var task in toRemove)
+            {
+                tasks.Remove(task);
+            }
+        }
+    }
+
+    internal class StatsWatcher
+    {
+        private readonly object myLock = new object();
+        private readonly AtomicCounter rpcIdGenerator = new AtomicCounter(0);
+
+        private long? firstAcceptedRpcId;
+        private int numRpcsWanted;
+        private int rpcsCompleted;
+        private int rpcsNoHostname;
+        private Dictionary<string, int> rpcsByHostname;
+
+        public AtomicCounter RpcIdGenerator => rpcIdGenerator;
+
+        public StatsWatcher()
+        {
+            Reset();
+        }
+
+        public void OnRpcComplete(long rpcId, string responseHostname)
+        {
+            lock (myLock)
+            {
+                if (!firstAcceptedRpcId.HasValue || rpcId < firstAcceptedRpcId || rpcId >= firstAcceptedRpcId + numRpcsWanted)
+                {
+                    return;
+                }
+
+                if (string.IsNullOrEmpty(responseHostname))
+                {
+                    rpcsNoHostname ++;
+                }
+                else 
+                {
+                    if (!rpcsByHostname.ContainsKey(responseHostname))
+                    {
+                        rpcsByHostname[responseHostname] = 0;
+                    }
+                    rpcsByHostname[responseHostname] += 1;
+                }
+                rpcsCompleted += 1;
+
+                if (rpcsCompleted >= numRpcsWanted)
+                {
+                    Monitor.Pulse(myLock);
+                }
+            }
+        }
+
+        public void Reset()
+        {
+            lock (myLock)
+            {
+                firstAcceptedRpcId = null;
+                numRpcsWanted = 0;
+                rpcsCompleted = 0;
+                rpcsNoHostname = 0;
+                rpcsByHostname = new Dictionary<string, int>();
+            }
+        }
+
+        public LoadBalancerStatsResponse WaitForRpcStatsResponse(int rpcsWanted, int timeoutSec)
+        {
+            lock (myLock)
+            {
+                if (firstAcceptedRpcId.HasValue)
+                {
+                    throw new InvalidOperationException("StateWatcher is already collecting stats.");
+                }
+                // we are only interested in the next numRpcsWanted RPCs
+                firstAcceptedRpcId = rpcIdGenerator.Count + 1;
+                numRpcsWanted = rpcsWanted;
+
+                var deadline = DateTime.UtcNow.AddSeconds(timeoutSec);
+                while (true)
+                {
+                    var timeoutMillis = Math.Max((int)(deadline - DateTime.UtcNow).TotalMilliseconds, 0);
+                    if (!Monitor.Wait(myLock, timeoutMillis) || rpcsCompleted >= rpcsWanted)
+                    {
+                        // we collected enough RPCs, or timed out waiting
+                        var response = new LoadBalancerStatsResponse { NumFailures = rpcsNoHostname };
+                        response.RpcsByPeer.Add(rpcsByHostname);
+                        Reset();
+                        return response;
+                    }
+                }
+            }
+        }
+    }
+
+    /// <summary>
+    /// Implementation of LoadBalancerStatsService server
+    /// </summary>
+    internal class LoadBalancerStatsServiceImpl : LoadBalancerStatsService.LoadBalancerStatsServiceBase
+    {
+        StatsWatcher statsWatcher;
+
+        public LoadBalancerStatsServiceImpl(StatsWatcher statsWatcher)
+        {
+            this.statsWatcher = statsWatcher;
+        }
+
+        public override async Task<LoadBalancerStatsResponse> GetClientStats(LoadBalancerStatsRequest request, ServerCallContext context)
+        {
+            // run as a task to avoid blocking
+            var response = await Task.Run(() => statsWatcher.WaitForRpcStatsResponse(request.NumRpcs, request.TimeoutSec));
+            Console.WriteLine($"Returning stats {response} (num of requested RPCs: {request.NumRpcs})");
+            return response;
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/XdsInteropClientTest.cs b/src/csharp/Grpc.IntegrationTesting/XdsInteropClientTest.cs
new file mode 100644 (file)
index 0000000..be4e696
--- /dev/null
@@ -0,0 +1,134 @@
+#region Copyright notice and license
+
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+using NUnit.Framework;
+
+namespace Grpc.IntegrationTesting
+{
+    public class XdsInteropClientTest
+    {
+        const string Host = "localhost";
+
+        BackendServiceImpl backendService;
+
+        Server backendServer;
+        Server lbStatsServer;
+        Channel lbStatsChannel;
+        LoadBalancerStatsService.LoadBalancerStatsServiceClient lbStatsClient;
+
+        XdsInteropClient xdsInteropClient;
+
+        [OneTimeSetUp]
+        public void Init()
+        {
+            backendService = new BackendServiceImpl();
+
+            // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755
+            backendServer = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
+            {
+                Services = { TestService.BindService(backendService) },
+                Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
+            };
+            backendServer.Start();
+
+            xdsInteropClient = new XdsInteropClient(new XdsInteropClient.ClientOptions
+            {
+                NumChannels = 1,
+                Qps = 1,
+                RpcTimeoutSec = 10,
+                Server = $"{Host}:{backendServer.Ports.Single().BoundPort}",
+            });
+
+            // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755
+            lbStatsServer = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
+            {
+                Services = { LoadBalancerStatsService.BindService(new LoadBalancerStatsServiceImpl(xdsInteropClient.StatsWatcher)) },
+                Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
+            };
+            lbStatsServer.Start();
+
+            int port = lbStatsServer.Ports.Single().BoundPort;
+            lbStatsChannel = new Channel(Host, port, ChannelCredentials.Insecure);
+            lbStatsClient = new LoadBalancerStatsService.LoadBalancerStatsServiceClient(lbStatsChannel);
+        }
+
+        [OneTimeTearDown]
+        public void Cleanup()
+        {
+            lbStatsChannel.ShutdownAsync().Wait();
+            lbStatsServer.ShutdownAsync().Wait();
+            backendServer.ShutdownAsync().Wait();
+        }
+
+        [Test]
+        public async Task SmokeTest()
+        {
+            string backendName = "backend1";
+            backendService.UnaryHandler = (request, context) =>
+            {
+                return Task.FromResult(new SimpleResponse { Hostname = backendName});
+            };
+
+            var cancellationTokenSource = new CancellationTokenSource();
+            var runChannelsTask = xdsInteropClient.RunChannelsAsync(cancellationTokenSource.Token);
+
+            var stats = await lbStatsClient.GetClientStatsAsync(new LoadBalancerStatsRequest
+            {
+                NumRpcs = 5,
+                TimeoutSec = 10,
+            }, deadline: DateTime.UtcNow.AddSeconds(30));
+
+            Assert.AreEqual(0, stats.NumFailures);
+            Assert.AreEqual(backendName, stats.RpcsByPeer.Keys.Single());
+            Assert.AreEqual(5, stats.RpcsByPeer[backendName]);
+
+            await Task.Delay(100);
+
+            var stats2 = await lbStatsClient.GetClientStatsAsync(new LoadBalancerStatsRequest
+            {
+                NumRpcs = 3,
+                TimeoutSec = 10,
+            }, deadline: DateTime.UtcNow.AddSeconds(30));
+
+            Assert.AreEqual(0, stats2.NumFailures);
+            Assert.AreEqual(backendName, stats2.RpcsByPeer.Keys.Single());
+            Assert.AreEqual(3, stats2.RpcsByPeer[backendName]);
+            
+            cancellationTokenSource.Cancel();
+            await runChannelsTask;
+        }
+
+        public class BackendServiceImpl : TestService.TestServiceBase
+        {
+            public UnaryServerMethod<SimpleRequest, SimpleResponse> UnaryHandler { get; set; }
+
+            public override Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
+            {
+                return UnaryHandler(request, context);
+            }
+        }
+    }
+}
index bd0405a..37e8f32 100644 (file)
@@ -72,8 +72,8 @@ namespace Grpc.Tools.Tests
             Assert.AreEqual(4, poss.Length);
             Assert.Contains("foo.pb.cc", poss);
             Assert.Contains("foo.pb.h", poss);
-            Assert.Contains("foo_grpc.pb.cc", poss);
-            Assert.Contains("foo_grpc.pb.h", poss);
+            Assert.Contains("foo.grpc.pb.cc", poss);
+            Assert.Contains("foo.grpc.pb.h", poss);
         }
 
         [Test]
index c69c689..903dd3d 100644 (file)
@@ -157,8 +157,8 @@ namespace Grpc.Tools
                 {
                     fileStem = Path.Combine(outdir, relative, filename);
                 }
-                outputs[2] = fileStem + "_grpc.pb.cc";
-                outputs[3] = fileStem + "_grpc.pb.h";
+                outputs[2] = fileStem + ".grpc.pb.cc";
+                outputs[3] = fileStem + ".grpc.pb.h";
             }
             return outputs;
         }
index ad6725f..90e6ed7 100644 (file)
@@ -68,9 +68,9 @@
 
     <PropertyGroup>
       <!-- First try environment variable. -->
-      <Protobuf_ToolsOs>$(PROTOBUF_TOOLS_OS)</Protobuf_ToolsOs>
-      <Protobuf_ToolsCpu>$(PROTOBUF_TOOLS_CPU)</Protobuf_ToolsCpu>
-      <Protobuf_ProtocFullPath>$(PROTOBUF_PROTOC)</Protobuf_ProtocFullPath>
+      <Protobuf_ToolsOs Condition=" '$(Protobuf_ToolsOs)' == '' ">$(PROTOBUF_TOOLS_OS)</Protobuf_ToolsOs>
+      <Protobuf_ToolsCpu Condition=" '$(Protobuf_ToolsCpu)' == '' ">$(PROTOBUF_TOOLS_CPU)</Protobuf_ToolsCpu>
+      <Protobuf_ProtocFullPath Condition=" '$(Protobuf_ProtocFullPath)' == '' ">$(PROTOBUF_PROTOC)</Protobuf_ProtocFullPath>
 
       <!-- Next try OS and CPU resolved by ProtoToolsPlatform. -->
       <Protobuf_ToolsOs Condition=" '$(Protobuf_ToolsOs)' == '' ">$(_Protobuf_ToolsOs)</Protobuf_ToolsOs>
           DependsOnTargets="Protobuf_Compile"
           Condition=" '$(Language)' == 'C#' " />
 
-  <Target Name="_Protobuf_SelectFiles">
+  <Target Name="_Protobuf_SetProtoRoot">
     <!-- Guess .proto root for the files. Whenever the root is set for a file explicitly,
          leave it as is. Otherwise, for files under the project directory, set the root
          to "." for the project's directory, as it is the current when compiling; for the
     </FindUnderPath>
     <ItemGroup>
       <!-- Files with explicit metadata. -->
-      <Protobuf_Compile Include="@(Protobuf->HasMetadata('ProtoRoot'))" />
+      <Protobuf_Rooted Include="@(Protobuf->HasMetadata('ProtoRoot'))" />
       <!-- In-project files will have ProtoRoot='.'. -->
-      <Protobuf_Compile Include="@(_Protobuf_NoRootInProject)">
+      <Protobuf_Rooted Include="@(_Protobuf_NoRootInProject)">
         <ProtoRoot>.</ProtoRoot>
-      </Protobuf_Compile>
+      </Protobuf_Rooted>
       <!-- Out-of-project files will have respective ProtoRoot='%(RelativeDir)'. -->
-      <Protobuf_Compile Include="@(_Protobuf_NoRootElsewhere)">
+      <Protobuf_Rooted Include="@(_Protobuf_NoRootElsewhere)">
         <ProtoRoot>%(RelativeDir)</ProtoRoot>
-      </Protobuf_Compile>
+      </Protobuf_Rooted>
+    </ItemGroup>
+  </Target>
+
+  <!-- Select files that should be compiled. -->
+  <Target Name="_Protobuf_SelectFiles"
+          DependsOnTargets=" _Protobuf_SetProtoRoot">
+    <ItemGroup>
+      <!-- Files with explicit metadata. -->
+      <Protobuf_Compile Include="@(Protobuf_Rooted)" />
       <!-- Remove files not for compile. -->
       <Protobuf_Compile Remove="@(Protobuf_Compile)" Condition=" '%(ProtoCompile)' != 'true' " />
       <!-- Ensure invariant Source=%(Identity). -->
   <Target Name="Protobuf_Clean"
           Condition=" '@(Protobuf)' != '' "
           DependsOnTargets=" Protobuf_BeforeClean;
+                             _Protobuf_SetProtoRoot;
                              Protobuf_PrepareClean;
                              _Protobuf_CoreClean;
                              Protobuf_AfterClean" />
        Protobuf_ExpectedOutputs with all possible output. An option is to include
        all existing outputs using Include with a wildcard, if you know where to look.
 
-       Note this is like Protobuf_PrepareCompile, but uses @(Protobuf) regardless
+       Note this is like Protobuf_PrepareCompile, but uses @(Protobuf_Rooted) regardless
        of the Compile metadata, to remove all possible outputs. Plugins should err
        on the side of overextending the Protobuf_ExpectedOutputs here.
 
        All ExpectedOutputs will be removed. -->
-  <Target Name="Protobuf_PrepareClean" Condition=" '@(Protobuf)' != '' ">
+  <Target Name="Protobuf_PrepareClean" Condition=" '@(Protobuf_Rooted)' != '' ">
     <!-- Predict expected names. -->
     <ProtoCompilerOutputs Condition=" '$(Language)' == 'C#' "
-                          Protobuf="@(Protobuf)"
+                          Protobuf="@(Protobuf_Rooted)"
                           Generator="$(Protobuf_Generator)">
       <Output TaskParameter="PossibleOutputs" ItemName="Protobuf_ExpectedOutputs" />
     </ProtoCompilerOutputs>
index 19f3605..01d1b94 100644 (file)
@@ -45,6 +45,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Tools", "Grpc.Tools\Gr
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Tools.Tests", "Grpc.Tools.Tests\Grpc.Tools.Tests.csproj", "{AEBE9BD8-E433-45B7-8B3D-D458EDBBCFC4}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.XdsClient", "Grpc.IntegrationTesting.XdsClient\Grpc.IntegrationTesting.XdsClient.csproj", "{7306313A-4853-4CFF-B913-0FCB1A497449}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
@@ -135,6 +137,10 @@ Global
                {AEBE9BD8-E433-45B7-8B3D-D458EDBBCFC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {AEBE9BD8-E433-45B7-8B3D-D458EDBBCFC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {AEBE9BD8-E433-45B7-8B3D-D458EDBBCFC4}.Release|Any CPU.Build.0 = Release|Any CPU
+               {7306313A-4853-4CFF-B913-0FCB1A497449}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {7306313A-4853-4CFF-B913-0FCB1A497449}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {7306313A-4853-4CFF-B913-0FCB1A497449}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {7306313A-4853-4CFF-B913-0FCB1A497449}.Release|Any CPU.Build.0 = Release|Any CPU
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
index f60c683..66c3bfc 100644 (file)
@@ -1,7 +1,7 @@
 <!-- This file is generated -->
 <Project>
   <PropertyGroup>
-    <GrpcCsharpVersion>2.29.1</GrpcCsharpVersion>
-    <GoogleProtobufVersion>3.11.2</GoogleProtobufVersion>
+    <GrpcCsharpVersion>2.30.0</GrpcCsharpVersion>
+    <GoogleProtobufVersion>3.12.2</GoogleProtobufVersion>
   </PropertyGroup>
 </Project>
index 8e47537..8044706 100644 (file)
@@ -13,7 +13,7 @@
 @rem limitations under the License.
 
 @rem Current package versions
-set VERSION=2.29.1
+set VERSION=2.30.0
 
 @rem Adjust the location of nuget.exe
 set NUGET=C:\nuget\nuget.exe
index e09ad69..04eb68a 100644 (file)
@@ -69,6 +69,7 @@ typedef struct grpcsharp_batch_context {
     grpc_metadata_array trailing_metadata;
     grpc_status_code status;
     grpc_slice status_details;
+    const char* error_string;
   } recv_status_on_client;
   int recv_close_on_server_cancelled;
 
@@ -223,6 +224,7 @@ grpcsharp_batch_context_reset(grpcsharp_batch_context* ctx) {
   grpcsharp_metadata_array_destroy_metadata_only(
       &(ctx->recv_status_on_client.trailing_metadata));
   grpc_slice_unref(ctx->recv_status_on_client.status_details);
+  gpr_free((void*)ctx->recv_status_on_client.error_string);
   memset(ctx, 0, sizeof(grpcsharp_batch_context));
 }
 
@@ -328,6 +330,12 @@ grpcsharp_batch_context_recv_status_on_client_details(
   return (char*)GRPC_SLICE_START_PTR(ctx->recv_status_on_client.status_details);
 }
 
+GPR_EXPORT const char* GPR_CALLTYPE
+grpcsharp_batch_context_recv_status_on_client_error_string(
+    const grpcsharp_batch_context* ctx) {
+  return ctx->recv_status_on_client.error_string;
+}
+
 GPR_EXPORT const grpc_metadata_array* GPR_CALLTYPE
 grpcsharp_batch_context_recv_status_on_client_trailing_metadata(
     const grpcsharp_batch_context* ctx) {
@@ -631,6 +639,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(
       &(ctx->recv_status_on_client.status);
   ops[5].data.recv_status_on_client.status_details =
       &(ctx->recv_status_on_client.status_details);
+  ops[5].data.recv_status_on_client.error_string =
+      &(ctx->recv_status_on_client.error_string);
   ops[5].flags = 0;
   ops[5].reserved = NULL;
 
@@ -652,6 +662,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_test_call_start_unary_echo(
                                      // received from server.
   ctx->recv_status_on_client.status = GRPC_STATUS_OK;
   ctx->recv_status_on_client.status_details = grpc_empty_slice();
+  ctx->recv_status_on_client.error_string = NULL;
   // echo initial metadata as if received from server (as trailing metadata)
   grpcsharp_metadata_array_move(&(ctx->recv_status_on_client.trailing_metadata),
                                 initial_metadata);
@@ -691,6 +702,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(
       &(ctx->recv_status_on_client.status);
   ops[3].data.recv_status_on_client.status_details =
       &(ctx->recv_status_on_client.status_details);
+  ops[3].data.recv_status_on_client.error_string =
+      &(ctx->recv_status_on_client.error_string);
   ops[3].flags = 0;
   ops[3].reserved = NULL;
 
@@ -732,6 +745,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
       &(ctx->recv_status_on_client.status);
   ops[3].data.recv_status_on_client.status_details =
       &(ctx->recv_status_on_client.status_details);
+  ops[3].data.recv_status_on_client.error_string =
+      &(ctx->recv_status_on_client.error_string);
   ops[3].flags = 0;
   ops[3].reserved = NULL;
 
@@ -761,6 +776,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming(
       &(ctx->recv_status_on_client.status);
   ops[1].data.recv_status_on_client.status_details =
       &(ctx->recv_status_on_client.status_details);
+  ops[1].data.recv_status_on_client.error_string =
+      &(ctx->recv_status_on_client.error_string);
   ops[1].flags = 0;
   ops[1].reserved = NULL;
 
index 9c731f3..c7c45a7 100755 (executable)
@@ -36,7 +36,7 @@ $PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_D
 $PROTOC --plugin=$PLUGIN --csharp_out=$REFLECTION_DIR --grpc_out=$REFLECTION_DIR \
     -I src/proto src/proto/grpc/reflection/v1alpha/reflection.proto
 
-# Put grp/core/stats.proto in a subdirectory to avoid collision with grpc/testing/stats.proto
+# Put grpc/core/stats.proto in a subdirectory to avoid collision with grpc/testing/stats.proto
 mkdir -p $TESTING_DIR/CoreStats
 $PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR/CoreStats --grpc_out=$TESTING_DIR/CoreStats \
     -I src/proto src/proto/grpc/core/stats.proto
index 50eea00..6f0cb63 100644 (file)
@@ -70,7 +70,8 @@
     "Grpc.IntegrationTesting.MetadataCredentialsTest",
     "Grpc.IntegrationTesting.RunnerClientServerTest",
     "Grpc.IntegrationTesting.SslCredentialsTest",
-    "Grpc.IntegrationTesting.UnobservedTaskExceptionTest"
+    "Grpc.IntegrationTesting.UnobservedTaskExceptionTest",
+    "Grpc.IntegrationTesting.XdsInteropClientTest"
   ],
   "Grpc.Reflection.Tests": [
     "Grpc.Reflection.Tests.ReflectionClientServerTest",
index 58a7c58..11097e6 100644 (file)
@@ -58,6 +58,10 @@ void grpcsharp_batch_context_recv_status_on_client_details() {
   fprintf(stderr, "Should never reach here");
   abort();
 }
+void grpcsharp_batch_context_recv_status_on_client_error_string() {
+  fprintf(stderr, "Should never reach here");
+  abort();
+}
 void grpcsharp_batch_context_recv_status_on_client_trailing_metadata() {
   fprintf(stderr, "Should never reach here");
   abort();
index 8bb97e1..a7efb59 100644 (file)
@@ -42,7 +42,7 @@ Pod::Spec.new do |s|
   # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
   # before them.
   s.name     = '!ProtoCompiler-gRPCCppPlugin'
-  v = '1.29.1'
+  v = '1.30.0'
   s.version  = v
   s.summary  = 'The gRPC ProtoC plugin generates C++ files from .proto services.'
   s.description = <<-DESC
@@ -100,7 +100,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.11.2'
+  s.dependency '!ProtoCompiler', '3.12.2'
   # For the Protobuf dependency not to complain:
   s.ios.deployment_target = '7.0'
   s.osx.deployment_target = '10.9'
index 742b5d8..5a1de64 100644 (file)
@@ -42,7 +42,7 @@ Pod::Spec.new do |s|
   # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
   # before them.
   s.name     = '!ProtoCompiler-gRPCPlugin'
-  v = '1.29.1'
+  v = '1.30.0'
   s.version  = v
   s.summary  = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
   s.description = <<-DESC
@@ -102,7 +102,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.11.2'
+  s.dependency '!ProtoCompiler', '3.12.2'
   # For the Protobuf dependency not to complain:
   s.ios.deployment_target = '7.0'
   s.osx.deployment_target = '10.9'
index 36ec44d..97ba2cf 100644 (file)
@@ -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.11.2'
+  v = '3.12.2'
   s.version  = v
   s.summary  = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files'
   s.description = <<-DESC
index fed3fb3..122c0fa 100644 (file)
@@ -64,10 +64,20 @@ grpc_objc_library(
         "GRPCClient/GRPCCall+OAuth2.h",
         "GRPCClient/GRPCCall+Tests.h",
         "GRPCClient/GRPCCallLegacy.h",
-        "GRPCClient/GRPCTypes.h",
     ],
     deps = [
-        "rx_library_headers",
+        ":grpc_objc_interface_types",
+        ":rx_library_headers",
+    ],
+)
+
+grpc_objc_library(
+    name = "grpc_objc_interface_types",
+    srcs = [
+        "GRPCClient/GRPCTypes.m",
+    ],
+    hdrs = [
+        "GRPCClient/GRPCTypes.h",
     ],
 )
 
index a6fd9bf..e0eaf37 100644 (file)
@@ -39,7 +39,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'BoringSSL-GRPC'
-  version = '0.0.8'
+  version = '0.0.9'
   s.version  = version
   s.summary  = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.'
   # Adapted from the homepage:
@@ -76,7 +76,7 @@ Pod::Spec.new do |s|
 
   s.source = {
     :git => 'https://github.com/google/boringssl.git',
-    :commit => "1c2769383f027befac5b75b6cedd25daf3bf4dcf",
+    :commit => "3ab047a8e377083a9b38dc908fe1612d5743a021",
   }
 
   s.ios.deployment_target = '7.0'
@@ -213,470 +213,486 @@ Pod::Spec.new do |s|
     # /src/boringssl/boringssl_prefix_symbols.h. Here we decode the content and inject the header to
     # the correct location in BoringSSL.
     base64 -D <<EOF | gunzip > src/include/openssl/boringssl_prefix_symbols.h
-      H4sICAAAAAAC/2JvcmluZ3NzbF9wcmVmaXhfc3ltYm9scy5oAKy9XXOjyJaofT+/wnHm5pyIHTNlV7vb
-      +71T2aoqTbtsjyT3dM0NgQSy2YVATSK73L/+zQQE+bFWwlrpiB0zXUbPsyBJ8osk8z//8+wpLdIqrtPk
-      bPPW/yPalFVWPAmRR4cq3WU/o+c0TtLqP8TzWVmcfWqOrla3Z9tyv8/q/+/sfHvx26///Hj1cffh4rdN
-      uou3l5vfLje/btMkubhM4t3Hze6XZLv7t3/7z/88uy4Pb1X29Fyf/d/t/zu7+HB+9Y+zL2X5lKdni2L7
-      H/In6lcPabXPhMhkvLo8O4r0HzLa4e0fZ/syyXby/8dF8p9ldZZkoq6yzbFOz+rnTJyJcle/xlV6tpMH
-      4+JNuQ7H6lCK9Ow1q+UFVM3/L4/12S5NzyTynFapuvoqLmRC/OPsUJUvWSKTpH6Oa/l/0rN4U76kyrTt
-      z70o62ybqrNo4x6G8z0dOhzSuDrLirM4zxWZpeJ0deuv87PV/ef1/8yW87PF6uxhef/H4mZ+c/Z/Ziv5
-      7/9zNru7aX40e1x/vV+e3SxW17ezxbfV2ez29kxSy9ndejFfKdf/LNZfz5bzL7OlRO4lJX2D++769vFm
-      cfelARffHm4XMsogOLv/rBzf5svrr/Ivs0+L28X6exP+82J9N1+t/kM6zu7uz+Z/zO/WZ6uvyqOd2af5
-      2e1i9ul2fvZZ/mt2913pVg/z68Xs9h/yvJfz6/U/pOL0X/JH1/d3q/l/P0qd/M3Zzezb7Is6kYY+/bO5
-      sK+z9epexl3Ky1s93q7VZXxe3n87u71fqTM/e1zNZYzZeqZomYbylFf/kNxcnuBSnfdM/u96vbi/Uz4J
-      yNDr5Uydx938y+3iy/zueq7Y+wZY3y/lbx9XHfOPs9lysVJB7x/Xir5XziYL39/dzZvftKmv0kOeS3MW
-      86VMiG+zRvzZvBv/0eT/T/dL6ZSPTzS7uYkelvPPiz/PDrGoU3FWv5ZnMusVdbbL0krIzCMzf1mk8ibU
-      KovJTL0X6g9KlNXqaVU5rtyd7eNtVZ6lPw9x0WRC+b+sFmdx9XTcS584k49lKR8LFUg+vf/xb/+eyCe7
-      SMHT+b/xP842/w88FC3kpS/bH3gd+g/P4rN///ezSP2fzb8N1OI+2kWylIHPYfhj+4d/DMD/MxwiramW
-      Dhk8N+vbVbTNM5lU0T6VxUMyVeeSlpWhAz0irV7SiqMzSMuqysJoc9ztZHbjuAHejPByHl3wU9alATtT
-      i/rYKe3Sjj0kJfzp8CTzdJ3tU1Wz0bwa6VifZQ2Xp0yxCTtuViIgVx9yz/x3TJUVWZHVWZyfriRKjl3J
-      Sw2Eq4a48+Uyyss4iZRBtW5kU2xqIIgdzPcP8zt1QJ0Dpci0ucH4MP8WVWkXbyWbC6pOnGiFWMC8ycog
-      u8WbEV4rWYty9Q4MuQNOHxQMMdQfrxcPsuUSJanYVtmBkiVhGrSr8iE+ynK+yBKGXsdR/0a1VnhuhaLe
-      bXaQ7fuAMx8EaIwke0pFHRBjEKAx2G6P88fPqIj3KVPc0V47+6xbGHXv45+RLLIFL79bBjxKVoRGGQxo
-      lIBb4E3/Q7ULuAEdjdqr3TbkzE846n+J8yNX3rC4OeiO+u5mJqJY1jgMc0di1k1ebn90JRHPrhvAKKKW
-      bbW4Srg31eCtCPffHqI4SaJtuT9UaTNIQmyojWiAeLsqTYFfCnJETATElPnjAz39DBK2vsuFIB4kYpaw
-      AmQJ4uMmC5Qq6z9VPvgQbZ9jWb5u06ommV0c9J+H+c/H/M0R447E+RMjEOhBIrYdyOsZK8wJht3pz7qK
-      w5LMccCRRHuZnAAd6nq3z6ksHw9V9qLGv3+kb1S7IwBitC1JeW1PVXk8kCOYOODP07jSUk+QI9gCLIZ9
-      n5iRHA0Wb18mKS+EIjFr2fR4mOfewa47LeJNnkblVhxUpXjIZRecGgJyoJFE9lSkXSmgBhUksD8IZkhY
-      hsauc6HuX1GkObXGwCRurF1+FM+nR5d8YSYN2GX9TnZKxjU1lbhKuWyXbWUpQLXaPBaB/9jZPBLhEFfx
-      nuVuSMzalo2MstXCQX+bZUWt3nHQ9RqN2Pv8GW03rAC6AInRFPCCZW9RxHuquKM8EzVLbxjgKPJP8TGX
-      HcdYiFduKjmSibGio0irJK7jdwna2+Do6c+IG6pDUW+RvsoKPkl/MuU9j0UIrLdBCRwrK3ZltI3zfBNv
-      f3DiGAI4hiwM8vIpKIqlgOOowaKmhOA+QIYAj3GoyrpkDVBgEiSWvHXhsWwJEovRdjtxsJHZbtNQ2PvX
-      MVOvhZ+PdVK+spLENMBRmncS8TN1nMihYXvXzpH5WXZI2GnvWuBoxLeCAIp4cyFLGfmb7Y/2EWXdbNcC
-      R5PZN9u9BZUilsIbJ0kP9XNAkIb3RuDedg13/c1bxe4XebmNWc8gKHFjFansg9T7Q7RckYcqdBYyv9KF
-      r66nSvflS8odijBp164ORPF2K+80Va2hXm/0VJZJgLzh/RGqtEifyjpjdIUQDRKvLaZ2xzxnxRlwzL+J
-      njN6Y0lnMXMpOwVb3k3uWL+Zf5t1wUiM0BsNeJCITWekuV0i+5sXzFR44jQ/3LBjtLjHr9rqAf4W9/i7
-      QiYgRG9AorAfCs8ToSbRpjxriyLe4rjfEF+emSjiFeE5UkzJkSIsR4qxHCnCcqQYy5EiOEeKCTmya1Xy
-      8s8Jhtz1h26SY3QoS0Y1Y/JIhKZPzXI3JGY9Dd4InrrHEf+p7csef4MtYLRzdhqde9JIHjtWL5xSp0e9
-      Xtawgc0jEVhjtQOJWEX2FOdPvATpWL+ZnyS6AIkR9lYCUCBx3iPnn0/M+ZHsWpav0bH4UZSv6hXvoRt9
-      4dwkXIbFDow2xS/SXDUCObWDbYCjtO/JWfoO9Xi593/0vjfHA4coMA8SsRnajYuE8x7cEaAx+O9TxPj7
-      FDHM3GSWNDqO+IPeq4gJ71W034RkXsOARDlWlfqRagNxw5gKLI7M6vsuH/KiaAI4RvCbKDHtTZR41zdR
-      gvgmSv9991gf4vpZhMTVPUjEUjQluSxnmwFiXtraEjhWGlf5W/O+rJspwKnKAQsSLbm4vDz/Z1AoU4HE
-      4b09FL63h+rgLs5FqmaLVF31niZR96FrUztyAo454TN5qtJYYgEJaRrgKNlTIetM1VA7/xip1y1PVZyw
-      amDYhEQNeaspxt9qivC3mmLKW00R+lZTjL/VFO/xVlNMe6t5+plIZatjV8VP6qNXbixDgsQKfYMqpr1B
-      Fcw3qAJ9g9ocEWHZS+fHI0Rx9RQaRTngSIV6x9emYlAPAvKMRRRRnLyoCVsiTYLDWjI4djMlsErFoSwE
-      K1MYAiQG7/268L1fF80nJf3kWM70f9SCRBM/+pZvQFYHNHi87kPS0HiWBonXLWrBidGisPevY7YNuD0a
-      jvoDZlmICbMsRNAsCzEyy6I9XqseblnIlqV4ji8uf43Knd7PEryoY1bsbLp2u2xLyyf7uE950W0LHO1U
-      OA7zVJklHyjCYobOahETZ7Xov1NDC2VRywI6JNpg8UdTD37ynHLn1HhUSFxopje7KYjb8OhZ8aQ+VSkr
-      2aPYNysNCW5oQIXEreqDqm53WZ7youkCJEZdZdvg4SfXAkfrpjepzwcDim3XgkVj505vbjTH20P6jrAJ
-      jaqaX219qz404zZVQdHUmCHNBdzmj17H9VGEXm0vmRKLV0nYDm+kYaZfWDTDMzGieJd4whvtqAZjZPkT
-      EOqkQOLIMjt5Zukb0mcNy+amAo+Tbvnnr1jcXImYK5ao1xucNLoDiVQdedVQA8JO/iC+b/S+a4W+Q8MA
-      NnmjsubmitG5uUfV5d5RvS0F2OQz/ND2gn+nv6Az6TF7NFvdnYeFaBSjcVR7KjCOUsBxlqtZWIIZggkx
-      2MnmWqZE4yaea4GjBXzUaOGjfnbK2Y7xSO1ram7awabxqO8RD4+kun7tApL1W/Sc0cfAQYkZq1uISn+z
-      to0PqplNCYZb4GjU73R1DjOW+2jzVtM6gi4N29tvbclLtgC4x88bokAUnjjsYWfc4ol2SAPSTMEjbv1Z
-      EkGBDNNY1HZMLyxe6/BEep9hnYlKz3m0fRp2zBZH/Zy36ADu9bO+xcUceCTaBEWTxK17tZ5wRZ3ABRvw
-      KM17q22Zc16C+jx4xK6rnGe7tJlnRK3ixly+yPuUH2mf+s3EMTUAx/2BN8d7T55jEVq4WQo8Dr9IGWjY
-      non2lQe3DaPzcATid4caBvuamcO8oqNDvd6QVoWlQOOElOFirAwX71Q6icml0zCKzo3jy6EioAQS3hJI
-      hJVAYqwEEs/lMU+ijfq6qXjKU9XDYAUCPHDEuuS36k+s3xztyirgZgMaOB593MgkTSv9g2LoO+KAlfe8
-      q+4FrLjnXW2Pve6dZ807dUj1wbvJ+8fNv9JtLdR9lW1j2jDuiMqKm6sfqeWau7W9SZFseMQd5WVggMYA
-      RWn6zt2Qqao485oex3VAkeq3Q8pOKw0ecTPTyjaYUdp5Cs8ZKXF6yHKp6SPt0nUk24BZvpD1EkfWSqSf
-      JXB+IWshjqyDyFuTEFuPkL0WoWcdQsayAuBqAttjXT9X5fHpuVlfNE9p478AbvqTNE+f1O5T0bZKmwHH
-      OFf1Oqldi0qsWGWzHYXsZPwgXYTOWUZZyTI+/tEw09eOhPYzXrf1T7XWVtrs56N6YpQgYy4ocjMG21b5
-      tDsA4JY/cE3M8fUw320tTMI6mMFrYE5Y/zKtKtlGZG7v4MCW++ehrJppB6r+2ctHqJKPDikAaDCjUMft
-      3fH6fls6NSGjWcic4nNp215/0D8fpWV9lwbs+qsbVeULcgTHAEXhVXb+NUHbhcmHqfH9Ai30VAItQDT2
-      u4axdwy8tU2xdU3D3yZMeYsw/MaezcAM5WiAeN388yr96ygLPlkMEteOQCVgrJDJtogCivMu70VI70Oe
-      muUK6CuE6ZxjjLoXtUThCXN9zHf7Fgp424mrmzf6Vh4AjvoZdxCfU8tchRddgTds9d2xlXe145VsoZZ7
-      pryFAXf3QTf9JbZLe+zDxgXsEIMCjzNsjcmM0gvAGC8psfGnc5iRummGSbrW03fejPFeAHf9WkdAfcFL
-      T2tHAMRQjVqyV0GAi/4GAn17rB2I/rz88M9otb5fzps5NVnykxkCMIFRWe+q/e+ou6We9yISx4Nq5tPV
-      Guy6d+SnZQc8J/IfmXhO6a6Oc43sL7xH1qxuDr+Q6xWJuJ6+KxPlKfkZM2DXzf4qfGSd6+A1riesbx28
-      tvWEda05a1rD61m3qzieekJRXf5Ii2gjH0XVmeb0U0ZsbnTGqCO6inYzj+PUmaEv0wbgHj+zwWrzSARu
-      oWLAmPuY56FJZDmQSM2XuLVs3IlmkKbJAoIVDzQhUVXnKK6PVTp0MVkxAQ8Usc3evBaqSQN21oYlJglY
-      tcm1ZK/G+s3kiVGgwI3B/3p7bH38ZsHZTVZSnYoBTKzvv30r7PfHhBrRKLYpS3yCATe9QVRBLSKRbtVT
-      M6ylrIZGmE04nwuK3I6AGt/I0kMCEihWO7rE6vcaMOpWH1Yxnn2Txuycnt1A+qzN+DBf3eCQn9VDR0ex
-      xHNcqTE03mCLSaN2xiqmLg3ZeaUfXu4BlV23JzQ5BmqaFlV1DlgZyOOaFpn1RCAeICL3u/8n/zf/2jzi
-      +CmNxA/aPE8AB/zsF4wuDduPRfYXfYh2IEGr9t12/1KGEQLSjMXj5GDX4EYJWIZ1dJeYkB1i/LvDBOwM
-      490VRjtIn8TlwKCbU+egvfZXRuvyFWxdvtLbaq9QW+1VFlkpu0Fp0qY9K7SxVIrYAB2ntiAkUaqRjlX2
-      mKk6hVgeESXyGSZ5WsTxKDlrEMBmHXPbziIqW8h1AZWfWgjgIKiJ4DE5UQPW23Rp126MWvEmG3g0ZjzV
-      PjkeEuI40kCZtjzbVHH1Rs7MOmcZ1WZZwwtAam8KwAF/O0eonYMqyHqDNu37+Cnb9mMs/dJUNSn3oxI7
-      llq0M86jUj4o1E6/A5tu7l5k+D5kxG+BnG+AiuPe7JKT7ptLm/ZDmpIaNur3tqG5XTRJg1ieqtyqfVma
-      4cdDKWreBE6Pxon3kiVp+0NqvenAprtdFlHmtD52tMuzp+ea+gbHKwJiNqNOefqS5uQoAwp428YHT6yx
-      prkiPrqV87QytyJDdx7TDnDyNYDbfmG/9v4XceY2ojDjdIstDnPwKBEc2Har5ZJl5Lz9rIGmNlnb3Bb4
-      VUqdFG6StpWz1xK2z1LAHkve/ZWag9QB8R4CXEG71UzZo6n5zSvnjF+hMz5n3aNz5B5x9nhC93cK2dvJ
-      v69TcxT6ooEcApIAscjvmbG9o7j7RuF7RgXtFzWyV1TgPlGje0SF7w81ZW8owZsPKrD5oM1OSu2uq2oc
-      jHq+BguYebtIeXeQUgfpJU4ElTecLXbQvaGC9lEa2UMpYG8j775GYXsaje1n1BzvNnplZS4DBtzcnYVG
-      dhUK34lmyi40zW+KXVlt02bopRllEPETOZVACRCLPvMRXXNBkGfzCWA23/vs6TJ1P5egvVxG9nFRh/+V
-      /Dg/j17L6kdclceCnDo270Zgz9Mb2bkleNeWCTu2BO/WMmGnluBdWibs0MLZnQXemSVkVxb/jiyhu7GM
-      78TS/KI+kqX10fWwP/4a2duEua8JuqdJ+H4mU/YyeYd9TCbtYfIO+5dM2ruEuW8JumdJwH4l3r1K+oMh
-      0ydRCRiLOa9kbD8U/l4ovn1Q2mPD0BanDLR5KMJ77rLC2WFF0OflCWhenuDNoBLYDKrwXUqm7FDS/OY5
-      TbShZvm7XUauPkAJFIuX//Gc/z4ffVL2N3mnvU0m72sStKfJyH4m7S4kjJ4a0kML2xdlyp4o77OTyNRd
-      RLRtFZ7VayXqDDaIRyOEzKQSU2dSieCZVGLCTKrAHS1Gd7Pg7WSB7WIRuIPF6O4V3J0r8F0rmDtWoLtV
-      hO5UMb5LRfML94MlcmEGOYBI1L0wkH0weHtgYPtfhOxC4d+BQoTM0xP+eXqCPhtOQLPhWHU/XO+Tayyg
-      tlJ/Yiwbp3O4kbxYnAOb7rpUr0/5M0Ig3ozA33HEt9tI4E4jo7uMBO4wMrq7SNDOIiO7ioTvKDJlN5Hw
-      nUSm7CISsIOId/eQ0J1DxncNCd27Y3zfjuA9Oybs16FmQETPaZ6XqgNcvZ3W5CGGAR1mJMYoKziu+hrT
-      EkH93jKoKUYkhQIMx8vFx9PQAHl4yWEdM0uJuLoxN5bSYAfz+nbFu3gHNJ10GWRhXbADms5X2cWONsfd
-      TmZIhhnADf/LeXTOTlEXdt08KWbjprAL2+6LkFS48KfCBVOK2QJS4cKfCgFp4E0BjhA2BVw7cuXJRRZp
-      a5RPdVoY6qPMAwHQwZtdJJzztDDURzlPAB28sta/Xn5/WN9Hnx4/f54vm851tC0PshF2LLZTY4xoxuKp
-      9TrfIV6v8cRL0vTQnBg7VG/wRFHrIRXHPGcHOQl8MY57vv6495gPR/HMVivY4xbT1yCGWI+ZtEQgTBv2
-      1XL9IH9/v55fr9VzI//z8+J2zrm3Y6ppcUn322OZFI2YB3waM56aM7h4+NqXEfsD9cnHFFgcNYu1TnkB
-      WhY1Hw9M7fGAOeWfEp5UkZiVk2ldGrXTsqYBYk5qBjRJzEotJGzU8DYL693Nvs3ZWRkxeKMw6mZM4YvD
-      qZMxBRKHUxcDNGInPkgmiDkJC5E7IOIkfMpnc7iR+rC7MOI+lAd+KpxgzE175E0QcTYzc0MeTF2AxSAs
-      i+SArjPs8Rt78riZA88XtNL/hLgebtbCc5V4znbkO9NArotacwzQ4JpdX8tOWHQzX10vFw9r6pbECO71
-      T/+QHIS9bkLJBdOafb6Krr/Nrif7ut+bhu1mG6XFtnqbvkWZhVm+3eb84oqlNEjLWldcq0Ga1iQl6zrE
-      9KTbDefUNMzyMVyQp2Tfi9JzL0SzJHVzgPKFDYC63i4gx6uhpvdYvFbxgaocKMwWHeIkmT7FCYRNN+c8
-      4bMMOEf8DFd359Hs7julfBwQy/NpsY5Wa/X7dlsyktGGcTepqgBY3PzUfM5Wc+Udjvv5ap+VUv24KO4l
-      DFEBqNcbksoCTuVvD+zsYaCol3rGGog6ybdOJ23r/f3tfHZHPs8es3zzu8dv8+VsPb+hJ6nF4uYnYh4z
-      UdybsbW+dKDeLhPFvYKfCsKXCnUZfbrjmhvYcn9mZrLPaC77Mr+T8W4X/zu/WS9kVzBO/kUyA/xIBHrV
-      BBpGopAfGUgwEoN4E1x8xE/N7gA/EuFQEabo4IaRKNTHC+DHIxCnOI5o4HjcGs7FvX5evsJqO/MwM0+h
-      td5idslNFRNFvcTU0EHUSU0Fg7Std+v5F/UOaH+gOQcOMRJe69gcYqTfIw1EnNQmhMYhxownzDAf+W4P
-      HGIUzGsW6DWroucoi9Jff+GKOxzx05siBmlZ7x5vb+mZqacgG/Gmdwxkot7uE2S57j/91/x6rVYcIkz0
-      dUnYSk47jYONxPTrKdhGTcMBs33X63nfdby7mX8mnygg8MWgFsM27HNTC2Qb9rnpOcKmffaQRPenNzmn
-      WLDPTS1mbdhyP8i/r2efbufcJIcEIzGICe/iI35q8gM8FiEgfbwpw04TT2rw08GbApRPRgHU8q7m//04
-      v7uecwZ8LRYzc62Acc07zTVyhm12a9MmThKa1YJ97m2exgWxnIYEvhjUJq8Nw25qzYXWWacDhBktNgcb
-      Kcts2Rxi5N2pBLs/5CILL8mHlwof2Bfew6i734h2H4sfzBCGA46Up8XT9O9wXdJnJVfTDg3bqUU6WqN1
-      B+iDXTrocUbT96qFWL852h1C5BKH/cybht4ttfgtU/gBNao90+8WN0xvR+P20GdPTHr27F9Fsdi+RzTl
-      gSPKLvvj+vMVJ0iHIl5qc0jjcCP3QT+xlnn96zm3MjBR1EtsE+kg6qSmgUHaVuZbojX6loj1agh5H8R8
-      CYS++WkOJNluR9cpCrLRMw7yxojzmgh+N8R6IYS8BWK++kHf97Be8iBvdkJe5/jf4TRHZfH2lBZpFefZ
-      32miVr+iR3AddqTvD3Nya/4EQS56fjxRkI3aezlBkIucIzsIcgnOeQn4vNSK4yzZuWV7vFv8MV+u+O/+
-      IMFIDGKB4eIjfupNA3g7wvqaVUVoHGKkVxQGiVn3h2bpu6jmqXsc8dNziQYizox3rhl2juRcMHCIkV6l
-      GCRipRYLGocbOdWLizv+z1fsYsJkcTM5G2gkbqVnBh21vH8sVouAUXYX9/qJCWLDXjc1WRzastM2QtYQ
-      y9O2P2rZ/VELkJJ8Jop5Xz7ypC8fHWMdlRvKPlAWZvmyOt1HyUVGsp0gxEVZxcABMSdx2EbjQCM942gc
-      aDxyTvAInp3aSoFzS1oOMZLLDR1EnNlFwlJKDjFSSwiNg4y8i8aumHW5yLWq5TtYz0kHYk7Oc9JykLGQ
-      f+Fd9okErZybjNzhQ0xsz/YUZFMLK9NtisJs0bb+yTMqErIeC941txxkpK1UanOWcb/pVqMkvy8zSMxa
-      8LUF4G0rRZnef9PKCY2zjLLtvc/q7CWlFz4minqpj49B2tZjHaUlbfy8YwATo2UyYJavjp8uqJ/VdAxg
-      EtM3F9YZ25TuD3mzWiP11hokZqXeWB3UnI/rr/L36+/R4u7zfdR9oks6Y9QwFoVwvxB+LAIljTABFOP3
-      +ffFDTOVBhY3c1LmROJWVmr06OD9NFstrqPr+zvZ1Zot7ta0/ALTPvv01IBYn5mQIiCsuRf3UXw4NNtI
-      ZXlKWcIfQE1vv2PStq5yitUALWeexlW0y+Ppm2xaGORrl3RlWjXYcqulappNg5ufkMwmanmpyemmovxL
-      011uNrghLoeLCpAY7W7XT8e4ios6TVlhLAcQibg5tc2ZxqQ87bZI8Q2UaUvLHUUjf27yak0f0mt0A7Jc
-      OWGdmh6wHBXtLlrlZPeXKM5zqkUxpqmZyUSYaKUzrmn6Qv4DAVgOZMvBtWRFVlM9inFNezUIw0ijEwcb
-      D9Mbmxbm+tT6PDK/Tp8S5YCuk1mmWyjmleWemL7QN8S6ZuoeEDbnGKkXbl3tc/ozOe5JmblDTI+6QQUp
-      L7eEbanJNd+JMU0qGzYbfhW0FNI521g/k4vFHgJclAaexgCmZgkw0udIAIp5ibfDABFnIhsSVfnG0nYs
-      YqY+EAaIOGXHnudUIOKsCBsVOiDiJG0H4JKutaS3SDTM9BEzu5PPVSWwycroEGcVUdRzrpHRANQw10dr
-      W7QEYCHswKEzgOlA9hxciyoTN8cdVdVhrk+U2x8pOdFbyrb9JHp+2objfpNW5OdRw0CfeqJkHcJQdqRp
-      ZXR8wD7PoSRlCPlzi1fTMUgZoSUsS12Rq5UTY5mIHZ2D08+hFu5umU7NOm6eaXegFcU5VdNAgIszymOA
-      tlPQHtcGsByvvLN6Rc5JcMpuAZfcglhuC6fUFuQyWwAlttpTZU+TSMB20EtXAZatTRsuJ+xibUCASyZ9
-      swcoNQ84MOJWHYEDYaVbEEbcbC/spPbUBTiaIcijGQIYzWj+Ru1B9xDgOpBFB9dCHRkR4MiI6AYkiK0X
-      DYN9ablT/fxjVXC0A+3aC8JUCp1xTf04BDmHDCRmFYd0m8U5T9zBmJvcjbFQ18sZcxHomEvfYep2wiK9
-      ckcFVozn8pgnkey3cFLahkE3OWMMGOIjvv7QOdBIzwgaZxvbOymP0YQ9ZvkKekv4xJimOhWM4negTNtR
-      bXhNOquWMC0v1FGuF3eE64WTRC9wGr0yuj+vYP+HnKWAvNQ+usQXGz0EuTgNY5PUrHfRp9vF3U37vX7x
-      khLaLS4Ke0nZw+JgY8Y+0cxznpQxJxMzfNfrP6N0+lYdA+FYiAl3QhwP4UOtgXAstOTpCMci6riink3D
-      GKYv87vrT82cAIJqgACXIKVRzximb/d36+aEKVP1bA42ErOCwcFG2u3UMdSnigFRUz6GRAV4jF1ZRfsy
-      OeZHwY2iKeA4tMygY6gvylWfOWFqO9qwxxsRZSJ6LSuKVaNMW0KyJA5NPpEOMT1ie7EpKJYGMBybrKA5
-      WsB0yL9kJEcDAA7iIv82BxgPMd12iB3TdrNhndvA2cYk3dJUErAdz4T3/SfAduQp68J6zPbtDxnNJAHD
-      0cwJIyia37sGymL7OgOYiNXJAJkuwkSAO/Ob9Pbf1DLjhJgeWmXr1LHb8lioAvY1+jutSpVggqRzaMMu
-      8zitNGoB05G9UATZi01T0/mEmJ4j5W4bX3jJf6fFc1xs0yTaZ3muXoXFTSFXZfs4z+q3potK0E/RmfH/
-      OsY5q4Fikab1JyVN5K8NmvgUOs/frir3siFT1E/lPq3eSCqDNKxPW0pWkb826dMXnOpepBGpOHdYy1xH
-      1W778fLi1+4H55cffyXpIYET4zh96eSBcCzEJ+6EGB5Zt9HKjhYwHKSB8Tt7TPxOtRVlmUZsEQ+Q7SrS
-      p1h9kUOTnSjbVpIarS3gOAriyUjAdhzK1wuaRBGOhf7EaBRs28Wy1FKjfzythtt+YgaH+hzyb6rSpFkU
-      YVjylPaQNL83DaR9FXsAcJyTJeeGZR9X4lnWNqS3+yZm+cQPaoumZ0xTmRD7iB0BWaK/jtn0LzltzjHS
-      auGOgCwXTZ1Id7UcZGQK/T5WMwYW4DGIz7fDOuZm6FVQT7mjMFu0ydXE4IRnPdGovUy45hLI+eRyZoAQ
-      1zlLdo7ZWM+lwSLmADHi3R9zok4SkIXXgHZhx01sFJwQxyP+qogaSUCWmq5x8504bqia4waysLJEzzlG
-      RnHlllKHjNaUaAHTQcuXdp6UWYp6JR1ieGiD+/aYflHI5KHw6veugfoEDJDpOu6pTZgTAnqoCWxwrvFN
-      to+pNsUYJlonxO6BHGJV46jGX3Qs1AoapPoQoE07d4zGMxpDWuHt9HvXQJk8NiCmR6THpIyqmPTGVqMw
-      m/o/TynP2bKGmXiCzpmxTslzLu2fad1KgzON1JZR5baKKnKLqAJaQ8RNbQfCsTCGOnTM8dHGpQQwLiXo
-      41ICGpeitUjs1gixJeK0QmgtELv1oVoQ1DToEMNTl5G10SrB6MKgu9s5jSHuSNvKauoanGE80gYEjvZo
-      wJH2Aulov0E60rLC0c4LL3F+TIl1b88YJuIwljWG1f9kdyy2dVYW0TOhBAJpyC7SfEerw11U8z5+jr7N
-      v3XLfUxWGpRrI70S0RjX9FSVr1STYmBTu5sPx9eSrpXSRB8Q16M+nqleyInWYaZvn+4pb/l6wrSIuiJa
-      WsKx5Nu4JmoUAngIb4gHxPEU9MsqoOsq8rSgenL9G7/rT5+a4VDKMLHOwKZoU5Y5R9eAiJO0FalLItZy
-      W5PXXkYFWIwsad+T1oSvRnEDEuXIT6AjkkKkLqkBuS5xiLcp1dVArut4/ivVJBHQc9rz6VDJQz+nd3c9
-      CjBOnjLMOXTtF+R7LBHQE3ztrgKI8/GC7P14AXoYaaggwEV/To7Q8yH/yDgnBQGuK7LoCrIE39Qr/z0l
-      7maoIaaH8iXi6feWISN+qmNAtkts4yqJts9ZntB8Gmg65X9k078SHwjIQllB2KQsG2WFrh4AHG3FoTr1
-      09cfA2HTTZlkcvq9a4jIOX+gTBuhfdX93OSJbWoNMT2UbuHp97ph1TWv0kr1wpO0mi5zUMib1d0Kwc+x
-      oIx64QYgimoFyVOgtaJc1jSrNZfirBDdrMs3SnEC0bb98EZtRumUaaOVmSunzFw1s8Pi4o3Y3jc53Bil
-      ebonrMaF8XAElQNDo9gOIBInZeBUofeELBBxcq9/9LqjbH/Is21G7xDhDiwSrbNik4j1yNceES/54e0h
-      15XHoiY19AzM9ZUHNUpHnOUFwiNuVjZ2DWNReJ3xMdNYVF6mgRxuJFJPtUdAD79hjyrAOHnKMOcp4Log
-      J6rVU+3/GHzt/p5q9yNKT7VHQA8jDe2e6oo6hVxDQA/jnOyeavdncgEGlV0hPVXMYEah9SVWTl9ipSYJ
-      v8R5llhNVJIUVphxSL2Mld3LWLVru6iPSyiWHjJdhzT90Z5sHZOu1ABNp/iRHSgq9XvLUE9/B3P6vW2g
-      vEsYCM0yX64XnxfXs/X84f52cb2Y09b4x3h/BEIeBmm/nfDuCME1/7fZNfmjdQMCXKQE1iHARblYjbFM
-      n7OC8KD1hGVZUAqnE2A5lpTl8QbCsjweEsL6vRqiee7vPkd/zG4fSXt4mpRla76qTwXt/tsg4szLbsVB
-      lrinLXs7+y3Ppr8VtzDNt7yNbhardfRwT95JBGJxMyETOiRupWQCF9W93x/W99Gnx8+f50v5i/tbYlKA
-      uNdPOnWIxuxxnk/fJApAMS9pTMghMSs/mX0p3IyyyqqVZz7RmJ3SirJBzMnODp6c0Cwcol7mslNCN2BR
-      aCtyQaxj/va4nv9JfgEEsIiZ1GC3QcSpljshLTkH0z477R0UjCP+YxF2/hrvj8C/Bl3gxJANxe+yhqe+
-      CoNg1M3INTqKeo9NIyfaqMsTzACGw4m0Ws/Wi+vAjApLJsTi3HLE4o/Gz8SYZlK84Ovz5uz11+V8drO4
-      ibbHqqIMxsM47m8W9O22LOMG0R3+SMVxn1bZNiRQp/DHOZRZURPeQuIKJ852sz2/uFKrn1RvB+p9MWHM
-      nRYB7g523buNOnzOtVs45r8K84+ef5AddT/H8n/RxQeq9sS5xrYlotrWzabf9FY0YHCj1FVAmhjwiFv9
-      kzB+jSucOM3WaLwk0lHH+7Tdq+AxuVYYQMzJe/ZNeMTNSm9IgcXh5RkTHnGHXIM/z3Q/YjX7DBYzN33B
-      H+kbz32iMbusXqYvlAWgmJcyom6DrlMtzf/WtlHajbS47QSPyRu12xHrPcLaKm/c9kTDgxoeMCKv2NNI
-      zErekxDBQX9zXZR1nSEWNTfby/MT31aAcernZlcY+VvCUDuMu/7nWM2MpPcaB9BxqjlrsdgThR3l2tpm
-      C7m103OOMWs2oNllauPDLM6jzZEyzdXjcCLl2aaKqzdO+uqo4903g6AcrUa61nRP+HLQgByXeiZ55YVG
-      utbjPuKMQPScYyxD2umlv51eFltqoaMQx3Mo87fzjx8ueS0Ii8btjNxksLj5SHupBtKOvUoo3+4bEOJS
-      a37U2SFPryg71XgUbpx01y5sKhu9kfp5swgcaTrzmAiPmRVbbhSJOl416qA+kQhpf4AOMNL7tO0EoW0n
-      3q9tJyhtO/FObTsxuW0n2G074WnbNVtBJSFnr9GgPbD9Jaa0v0RY+0uMtb/Em2AUYx3l2OpcnEeHilp2
-      nTDNt15GN8tPX2hrbJsUYDutREsWnkDASaq2dAhwqa9NCFPvTEzzPcfXquVJHFIwqMF2M1+dBkk+TnXp
-      jGlKt5uP1OaOzTlGphDxJemFGh5mSS3WMX8MMH/0mAv6/Tkxpqlgnl+BnpsqgwiDQxoCeqJjsX1OKZtu
-      gLDrLmVD4BBXWU0+1YHUrF+jJtJkV/d71xAdjhtSAlqcaSz3h6NsdhB9A2XYKBNTup8bfL8yOO10dAz2
-      ybsR79M6rQRhKStUYMWoP5DPt0Vcz+GvJ6pHIraH2noyKchGHhEDUMN7Wsp4SFeC2YUNN2FaUPtrkyau
-      Q6ghhqedOsi6Phs1vIKe3wSU3wQ9vwkovwlWfhNIfqPsmtn93OBpE6t6QHc06S4o+2DojGZaLOfX6/vl
-      99V6Sd0fD2Jx8/QGp0viVspj5KK6d/VwO/u+nv+5JqaBycFGyrXrFGwjXbOBGb5uwmx0N/s2p16zw+Jm
-      0rVbJG6lpYGNgl5mEqBXz7pw5Jp5l4tdaTPKcaC83gFhzb2aRasFsfTQGNfU1Z5UWYe5PkoCDojraWo9
-      qqmBTFfb2FUr3Mb1sSIZLdT0JmWI2qUduzpCVCrE8bykVbZ7I5payHLJyvHmK0nUEKaFmnPdXMvqFlgc
-      YuR1DFCDHYXYVNMYwERprGmMYyI310wM9NE7CABrmgO6CCCN2KvshZG1ABzxHzd5tmXre9q0E8tcp7xl
-      d04AFjTzUtWBQTcrRW3WNAvGkyrAJ1UwnlQBPqmC96QK7EmlVi9u3ULqnHW/Nw3E7llPmBZ6BQfUboxu
-      ng4Nrvk1bxzN5nBjtMsOgqttYMPNaFGaFGwribskQCxkVvUY3akoyEZs/Tog7PxJ+b7NASEnoYQ3IMhF
-      allbGOQTrDsikDtSl9x8cyJtK7EtbUCAi1bcWJjto58YdFaUknggbAvnwtyrir587vYDk+2B5+k7yrik
-      Yy0yUR8uLn7hmS0asV/+GmLvadD+d5D9b8y+vH98oOzKrDOAiVAF6gxgolUpGgS4mu5L18sqK7LVxDF/
-      WRFWWwRQ2Cur3128ZZ51D2PuY/WSqjzCk59or50yfoXgiD9Jnzh5ZEARL/tGovexffAIC6i6JGBVfd3N
-      W0gyOwYkCj+fGDRgb1KM9I4MQAGvOK32t8unf4oB04idX5wYNGJvvnlU07DV1pBqg45dWe1ZkUCTEfX3
-      +fduPJHWN7BAxEnqxZicY5Q3PJNZqWnji3RbTV8UBxW4MUg1WEc4FmLtdUIcD2e4EkC9Xs5td3gggqo0
-      q5KcnAMIOxnjQQiO+MljQjAN2ZvnkPosOyxoTottU1wJhrlnYTNt4MglMSt5oBfBHb/acv0Q/3WkPoI9
-      5xjl/bwgTJw3Kcd2GpJlVd2wAI3Bf1y849Ldb0hDCycCsrBbMiAPRiB3nkzQcbbDwOyTtnHETx9YR3DM
-      z84fnhH27hfcVpjDgmZuWSq8ZakIKEuFtywV7LJUeMrSpjXJqGZ7DjTyc4VFw3ZuFWvCI+4o3qmD8l7L
-      rkJWxKRxwWk+5wxoLyUMyHB9m6+/3t80Nd0uS/Mkqt8OlAIG5I0I7TQRwnaMOgOYmu8iqO1eG4W8pLGp
-      noFMhNVKDQhwJZucrJIMZDrSr8/ucdBnRhkQ4GpWy3eyO3EIYEwFxM1UN7Umx2gxyCeiWH3jpz4Qrel3
-      38Rhv+xSN5U4R35iATNhV3idAUy0NhowJ63/a7mtL5rxBLKvJwFr8/eL7WZDtvYkapVxmVZJAlbxfs+F
-      oDwXbZtlf6hSIdLkXWLjOiR+XfIfJIs3InRN4Cy5KAhr6jog6BS1PJYwnC1oOJv9Po5ZXmfdU0tpTriw
-      5r65uLw8/6dqYxzibPqAoomhvtNw1/SvmlCBG4P0DlJjXBPxDaJB6bbFw2y5/k6eLu2AiHP6fGELQ3yU
-      0tniNOPdl8Ud8XoHxPGozNq+oiX2mWEc9C9D7Evc3azafXrS0uJJHhLECJDCiUO5bz3hWKr0SRY1aq+q
-      PG9K5DytqbcQdDiRRNg9FWP3VITcU4Hd0+UyWs3+mDfrdRLzt4uaXrU4Q1pVZUXrkTukz7rja3emt+0j
-      NYcpTg2DfOJNZpw9V6vTpr29DNomKjaHG6OC64wK09qsW9geEhSnzlnGY7FlX74Dm+5m3Jt6q3oIcUV5
-      s804Q9iQPiv5wQJw11+kP4dfNQtJUUO4BjOK/CP7FtqsZVY1y6fFPSfP2SxgVv/BNWssYF7O7m7Yah0G
-      3M13/SXbbuKmv9mqiPzIDBRmIz80Fur1kh8biAciNLsL8hJjQL1eXrJY/HgEXgJBEitWeVCd1H1c/SDZ
-      B8zyVWrqRROSlK11DjdG2w1XKlGPd3dge3cHy3vk5LgjmNeqNBZlwS6YAdz278sXVasTFvGxOdDYLZLE
-      Feu47Rd1WbFOWQNNp4g5aTBQlk3WttTH6cRopj8eotl8dtPs0xUTdhdwQMRJ3OkEYhEzqcdig4hTNWGm
-      r1oMoIiXstqUA3qc0WtWP0dJVqVbtZMqO4TlQSJS+uUWhxjLQ8o7aQV6nNFTXD8TZpoiPBJBpIQvU2zQ
-      44zENq5r5mnrAiRGHT+RPoABWMRMWYvSAQGneiXc7ktKtg4o4FVf8siCv3rmlHQ6jLi5KayxgLlQ67ty
-      00OHTfcn9VHOuvydMFXAoEzb9eLh63zZ3NRmqx7axy+YAI2xzQ7EB9yBcTe9znJp3E55V+6iuLeucq5X
-      oqi3Wx2O0ibEBGgM2owggMXNxFaChaLe5tX74UDrL+EKNA615WChuPeFUaBAPBqBV4aDAjTGvky4d1eh
-      qJfY0jFJ3JolXGuWoNaKsoMtxKJmEZ7HxZQ8rn4UUgL0vDdCcH40Jd5YhzhJ+AWmZgCjBNWvI3Ur9z7g
-      6R9S0vhLmaA7OnInmSULWqrwnn33uac3e6C2TvO3Zkttwno6LglZF9QKq6cwG+sUOxBy0jbrtjnTeJNu
-      5R3/FIv0118oRp0DjeopZQgVBvlIG65bGOSj3uWBgmz0O6JzkDG5JZcLBug4VQuW88BYKOhlJOYJQ328
-      0wSfmu4Y6yYNoOXMnlJBu+iGgCz0vD1gqO/P+89MpSRRK/WuGCRkJWednsJsrFOE801zaEWZxWZQmI15
-      v3sU8/LS8kRiVsZjY7GQmWvFjX/Q5ghaHG5k3i0Nxt28OzawuJmbvjpt2ucFq17XMMhHTl0Ng3zUFB0o
-      yEZPRZ2DjIx63QAdJ7det1DQy0hMuF7XDvBOEyyfu2Osm4TV699uAkaAHRh0M0Znv3neJ56OEUdlNQz1
-      Ee+VScLWZvcpjrQBQWe3tRRD2pGglTru+g17N/uN9wb1G/b+tDuwTxi2fQK6iKOF35C3ot3fyeN5Ogca
-      mc8h+gSSPpg0McfHLik8pQR5DOvEOCY1abr90pOhNGHHzbhm8GoZd8O9Ew+f5pEg7R5kUpbt9+vV1cXD
-      7/PvJFtP2bb594vmIM12olwb632ZASLOhFYv6RxipJajBog429VUftDe+7q0z16JOCrj9BDl8SbN+XFM
-      Dx6x+eH+aXdOLNgxx0ik5pQCI3WOkUiMNwmYYyySEJGI85o4f8Hn8UTs19cPSUZdgsQi1s06hxujLOFK
-      oww7U/FOz42Y/Nw0a19s23VM1Ft6bjhDMiHWU1oMH5gGBzVsnugqSWSppX5OWhRvxDMt4uG4SX8e3iNm
-      axqJGlISikkloXiHklBMKgnFO5SEYlJJKLQSrEvtwCszTISo73D7XN30+CHVAK6bEP+9Ao9HDK5/xHj9
-      EwtBHPzWMNQX3axmTKdCcW+7ZA5X3dK4fck/6yV41ptYpJyKuOMgI6daQOoAyto6GgObOCuVwTjkV+NN
-      IQFMHojQbSlMNnccbiSPCjkw6FYLmTKsCkN93FPtWdzcTBdKabNCIB6IQNxR2OZwIy85dBhws/rKSD+5
-      6X1O31XL5lAjoxQ8gZiTWW5rLGZecs92iZ3tOTNNz9E0Peem6TmepucBaXruTdNzbpqe+9K0zoV6NtRr
-      LtoaUl4LHC2q4lfWGoYehy8SfT1DXAHEYTQgwLYDfV1chwSsbQOarGwx1McrfDUWMO8z2VYrnkIaEq4C
-      iMMZz4HHctRgTGheBhy+SPy87CqAOKfhELL9BHqcvDxj0JC9+cK53a6LLtdg3N3eGa68pXF7czu48gYG
-      3IJbqwm8VhMBtZrw1mqCW6sJvFYT71KriYm1WrOCHvEtmgFCTk7PH+n3N51g1vPXk6D1b8YVO28gmz+z
-      Ug9JOeI6vyYG+F7IE9s0DPXx7ofG4uYq3arPTLnyDh/1B12B7jAjsWZoInMzObMy4fmYp78Sp+RomOuj
-      T5zC5nQyZ0qicyR5syOxeZHD34mpZ4CQk56C+PxKtcRb+11vFOdZTGpO2KxrTsjz1QfKsqkVR+JUROcX
-      V9F2s43Ec9zUUiQ5JpkYK8r2B9n2yKirXUwSjp+D2jHvHa640/jibffRJj+mdVnSJo3ilqnRoqv3iRdd
-      +SLWVfS8j0+pwY9oejwRn7Z7dhTJ+s2yefESYlf8SASZX84vgmI0hglRPgZH+YhF+ecF/z60LGJWT1Rw
-      mWRLJsYKLpN8wvFzCCmTXM14vI9Xv7xHvE7ji/cOZQTg8UTk5s2O9ZvZZYTGj0TglxGGYUKUj8FRoDJi
-      +xzL/118iA5l/nb+8cMlOYpjAKIk8kzSJP0YVmCAlqnRgoqMUSNwFsUxz/nXatCA/Wf4jfs5euf6FhTN
-      3WOIr65YvrqCfSlhBUYTg33kIgltsbQHyh3r/CQG+GSVzLkfLYb4GPejxWAf5360GOzj3A+45dIe4NyP
-      FnN9Xe1K9XUY4qPfjw6DfYz70WGwj3E/kNq6PcC4Hx1m+hgfe4FfeanCnnhPO8T1ENO+QwAPbYWRDgE9
-      Hxmij7CJk0wnDjFyEqzjQCPzFN0zVBsKqkqZIjsxpqnZRLYZQdq8kTasBFiPmfa22kJdbzs+xTtjnfWY
-      6Wesobi33PyL65Wo6X2ORVMAPcdV8hpXpJSwWdN82ua1DR3F+VNZZfUzqajFHHAk5sts/360+g9Yr7Bd
-      2rInpMVz5M9t/pLGXzp80y4nShrGNLUbt4bcb9gARWHea9/essNh1n22WdNcbS+iXz5QC++Bcm0MFeD5
-      heaw8h4137h5Ro2nXPxCdEjCtdBGd6BxnHZEiWiRhGO5pI2gtIRpUd1x1TdvJhjvY9KttlnY3D1l6mVm
-      lXD0hgCO0R47/VIcD4eyqlNWNESFxW2WuGd8NQMbtCh/rud3N/ObZoPdx9XsC3H3KBj3+gkvMiHY66bM
-      KAPpwf558bAirRzYA4AjIiwDYECD68v8br6c3UZqV7sV6Sa5JGadfmtsDjMSbogDwk7K1xg2hxgJX3rb
-      HGLk3h7P3WknY5dqKfs7QhPfo/DFeYnzY0CMBkf8vEyG5jFuFvPksGZKH8vZkIhV9IlfcO+fqfDF4d8/
-      4bl/q8dP6+Wcl711FjfTM8dA4lZGFtHQwfv195vJKwmq35pklP48xEVCEXSI46mrePqOzTqjmb7Nricb
-      5G9NkrN6k81BRsLKTQaEuAiTnGwOMFKyvQEBLsqEPQMCXITsrTOAibRekUlZNtIEuIGwLAtqKi3cFCJO
-      dtMZy0Sb4qYhlocyW7cHNMdytVIfPsbTn7yesCxpQbU0hGV5Sou0Io5eOKDl5A9SIbjl5w6NgLDtLvO3
-      j/JhfUmrmubVQNC5P+YMoaQG22K1epQ/jW4Wq3W36zylXENwr3/6MwzCXjeh7IPpwf7tZvJgifypwdGK
-      ux4wHZTC7vR707Cu4kLsympP0fSQ6aIVdgOhWy6n45cGR03PSzc9L4npeemk5yUnPS/h9Lwkp+elm57z
-      9df7G8oHFQPhWI4F3dMwg6npLlzf363Wy5l8mFbR9jmdviAuTHvslFIKhD3u6RkFQD1eQukEsZpZHvlM
-      S4KesC3Nalu0TQYdEHSSNhu1OduoNi2muRQBWaJNVtJNirJtlNt5AjTHfL26nj3Mo9XD77JRR7qZLop6
-      CXnZBlEn5cIdErYuos2vv6hGKWGIFeN9EdrvBfkRWh6LwL2JC889XDRPhWxdEpqlGI9F4GWSBZpHFtws
-      svDlEBGYDmI0HSifdrokZqV9pgixmvl+vbiey5/S8ppBQTZCDtAYyES58zo0uO4//Ve03YgLwgwTDbE8
-      tEEpDbE8e5pjb/Ok5b0HwrQktCtJ7KuQ/5GorJolav6BoLgsFPVu3kLUHW3am3cIlJ3qDMh00TYVGwjL
-      UlAzZ0uYFvmHi+1mQ9F0iOvJC6omL1wLYe6VhrgeQT4bYZ2N1FKTuENcT/2zpnokYnoE+Y4L4I5LLVXT
-      Ia6HeK86RPM8zO/Uj9TXrHGeDxOSRLQti8mdwRGNG29zzHK1zle7squgxrFw198U3yKlejsM8RHKXROD
-      fRWp9nZJwCrTOnsiGxsKsB2OsjCW7SXGdQ+o6+VcNXy9T/s625NdLYXZZB7+F8+oSNSaZLsdU6tQ1/sc
-      i+ePF1RlS7m2LP54sY0P0QNV2IOAU70waRb0K8nWAXW9bU9clQCyANiXyTGnFyCQw420l2VZuaW6Wwqz
-      kd7yASjgTfcJ/RFtKddWlMxipAddp2zEchKyw1yfqKttLFJKc9whQSsjHVsKtOXbuGboFIb4pr8JtzDQ
-      V/ATsfClYsFLxgJLx4KwZLSFub66zMvX6avvWJjmW3+dL6mTzwwIcpHqRoOCbISCRmMgE6E/b0Ca65AW
-      cBNxshg14FHaz2PYIToc97dzddn+Dnf9LzIqYSzewlBfVBz3TKdCB+/D/Fs0W92dqzJ6ck/GgBAXZWDe
-      AQHnq8whKVnYUJiNdYo9aVr/vPzwz2hx9/menJAm6bNSz9elMTsrOQDc9G/e6lSwztwkTav8z2grn7lN
-      PP19pM3Zxh+yRbYrabaWsUxl9CxPenqtZECmS43zazvMq4SmWAHc9B8q2RClrAdoQKaLmufdnN7c65uv
-      tBVGHRByrmYP7SdUv09/0wDTsD16ePxEWKwTQGEvNylOJGCdXwckhQ6Dbm5C9CRgVfvC/UY2NhRiu2LZ
-      rjCb/Pnij+YzE+oDijmgSLyExVOVnwu8eWAZ9KwtR541dbyZlceVn2DYzU3lpe85VnUk2aggxBXNHv9k
-      +RSIOa+XtzynBDHncv7fPKcEASex/QC3HE5/5dczOoy5g54Bx4BH4eZXE8f9IUnkqYPU8aB6yBagMUIS
-      yFcnqeO8eqknPdYrtvXKZw2spxAPFpGf8P5UD8s1o3lmGfzsLic8u0H1mC3AY4TcheVY+cCq106gx8mq
-      33TY5+bUczrsc3PqOx023eTBDmCco+2Uc6o6kwSt3AcFwBE/I/vaLGJmJwhcq7UHuVWaS8N2dnIgNVl7
-      kFyNaRjmu+L5rlBfSMJaggkxKFvdeiVoLH5VjErAWMwM48ktITfCew+WYeXJcqw84Va5Lo3Y2am99JZW
-      1Gp2oDAbtYI1SdRKrFpNErUSK1WT9Fmju/n/8M2KhuzETioyat7/OaDuxvup2vGwZ26kp2r8iP10+Pqq
-      xi+CEspXr4d0V2EDHiUombz1PKvLaqE+7xXfe+X1hib8hPof+BmvDYCIvDFD2wKT+uXaTwMy2EjuCr1R
-      o/doGV5eLaeUV2FtBX//3PhN0N1YjpaKvLYD3Ec3j/HaEHgv3TrOakvg/XTrOKtNMdJTN47z2ha2QYsi
-      H+/zi+jh01zNNplsNijHRvuAxYAcF2Wqk4Y4HvXG+ocsM+MiibZpNX0yDsY7EZqlHYjWhnFM3e5qhMUO
-      HdB0Xspb9fvN54uIsnSPA3qc0err7JwtbmjbftikF6wd3hEc9HP2IUdw0/9btDkWSZ6qEoOU1QwQcar8
-      l+2yrXxeeG5dYMegPnC/Ac/bb83jQr/0EwXZVGnGM55IzMpPTsgARQmLMGZXOwKHRbANdhTKt64DYVvU
-      zB61zzXl8zyXRK2kvfkgFjN3T3ma8OQ9jvtf0rw88P0djvnVveDKW9ZvnhXJPOwSXI8Z0eqAkMsoiPdH
-      oFUHLu23E+ZJI7jt72o6mrWDbFeXYWmuDrJdp9W0+oeAs175BJUdt11n6x2iekROTNU+VN8SEyOcMNAn
-      eD5h+fqVih/my8X9DfEJgmifnfL0uKzPTHpyAFhz398urr/TixMTA32Ey9ch0EW5YIOybf/9OLtlXq2B
-      ol7qVWsg6iRfvU7aVvaaUAju9VNTA10ZCjhMThV8daju+LfZw4Mi6aetkZiVk9Y6inq5J+s7V3raaqRm
-      Xd7/KZN9vly3VXazZvxqcX9HSwyvZUo0QhJ5HFMiURLOJ7FjdalMTzYNRJzUxOkxxEdOgoEbjMvZ3U0k
-      f5rGk1sqGmJ5CGN6p99bhuZjGZKjISBL9JrVzypEptaBU5sZETqCIxorHnEhBp2xTOkTLQXl721DEW/y
-      NNqV1Y/oWIh4l0ab426XUpa8GxVZMXeZ/CFlsXiTsmztEEGRRPu0fi5p6WGxlrn5wF6FJTl7yrIdyumb
-      uPWA7RDpMSkZ2V4HLadIU1qiKcBx8O+B8N4DdfSoDpf7aEcXD6jtreP6SEvDFtE815PX1ZU/Nbjm3Ai9
-      PQ3RPPorPcqKWg5oOk/v76hKnTOM/xudf7j4RS1Rodb9j+KXnxcEL0Ab9uhhtYoeZsvZN1q7GUBR7/S6
-      2AFRJ6E+dknTqj7FPvzYivPoUMm//qR4bdY0b7Lp76JOv7cMeVaovZmi6V+CW5jpa5bTleXrgXReAwXZ
-      KE+iDpku4iiXhtieXXzMa2pZ6pCmlThupiGmZ5fHT6SkbwDLQXxM3WdTX2GfsAkCgHq81EzmwLa7/hBt
-      qzqizdgCUMC7i7d1WdGlHQcYiQ/FiXFMMo1pbWkTA32yBIxk+UC98SZrmjMRlYf4ryMpY/aQ6QrY6RTB
-      ET95mweYNu3EismpjVQC08uugTJt3dZ+TT3VTCSI7mfzh2j/tDun6D2asXiq5g0Pd7KMRWveOgXGah2T
-      Il28Q6QLPFJRFik3gmJhc1sBv0NuAEXjMfn3yLVMjHbxLtGcO8XcoxeEQTerhML3oWmOUrax6wHH0Zw2
-      o81mobCX0dqyUNjbtCwq2aGlDQGgBjxKXYbFqEtfhJq6AwkIW+42v3BuqUGCVs4NNUjQGnA7IQEag3Uz
-      Xdz0C357Vvjas4LZnhVoe1Yw2rMCbM8KXntWYO1Zytyl0+9dQ3QQglwHGiDgrOJXsk4ytunvlGb526rz
-      jwfKzkADYVpoOxcMBGQJaBaCAjAG545aKOgl3tWBGmyU2bTm3Fn1L9oWWANhWSibYPWA5SBvg2VSlo22
-      EZaGGJ6Li18ICvlrmyanb884JmIanxDHQ06ZATJdl79SJJe/2jQ9bU6MY6KmTYc4Hk4eNDjc+Ckvtz8E
-      19vSjp1+L3vIcH28ouRz+WubJt/LnnFMxHt5QhwPOW0GyHBdnl8QJPLXNk1Om55xTMS0OSGOh5PPDc4x
-      klN7gDTX4uHrbPU1IpS6PaFZHma/zy/IeylbGOgjDMaZlGPrR6f34omo1FHHq9bFTFWTg6zVSM1Kmlxi
-      zytp/01detikNNufd/P1gjYfVWdcE+Fh6gnXQskUA2J5mjG2LIkWd+v5l/mSJLRYxByLLcsqOcR4zMvp
-      01Jc0raS7yt0V5v3Ctx0NFnETE7HgUOMjHTUSdtKzNVunibnaDM/P67my3YLNtIttTDQN/3SDAh0ES7S
-      pDTb+vOVuhWTM0QPWI7DkehQwOD48+Ly8nzyN9btr21aja4c4qyiWU6UY+vGq5rRsG6kkGgGDFqUyw//
-      /OOjmg2qPtdrX1BQtpfCeDCC+hI6JILBgxEIcy9NCrNFcZ7FgudsWdScZ9M/nQNQ1MtN3dGUbY9G4keI
-      XOKgnzh71CVBa3KRMYySAm2UUtjCQJ8swBg6SWE2yjInLglaswuOUVKgjZs38XzZZiredfcsaCa9kLM5
-      3BjtDlypREHvSzOromBoO9KxdnvXyBqDuPU4xjsRZIFwzshcJwzyqamsRRJXakZlnRaq0yPoesgCRpNp
-      d0wZ/obDjdGmLHOutoFH3BH5CXR4TwT6M2OwHvNx+xxXbHdDO/amAGAU6z3nGIdMwypAbNzxq7KaXqt1
-      FGjjPeEaCVtryrcWDgg62c+HCXvc9BtmsI65nfLBaOkNoOPsUp2TbXUU8NbRtv5JVjYUaOPU9j3nGpuM
-      wbrsgTSt0ez2y/2SMhHepCAbZdM5kwJtyZFjS46wjZp4Ggb6KF/eWxjo49wI7D4QxiVMCrQJ3pUK7EpV
-      Pt8nPKMEbed6vVx8elzPoxVp4AqEUfe2PBZcdcPiZtLqZSA84lZb198tboJCdI4Jke4//VdwJOmYEImw
-      ebrPgUYilz86iVrp5ZCBot5muj5lGhPG+yOUm3/JmjQkRmvwR6Fs5YbxaAR2GeEpH8glrk6iVlngnYfc
-      0573Rwi6p5rBitJ8cT97/JOe5Q0SsxJvo8ZhRupN1EHMSe4JWajtXdx9ZqTniYJs1HRsGchETr8Osl3L
-      W/q6Wy6JWanXO3CYkXzdGgg4v83XX4lrJkEsbuac74AC3jhJPkRV+lL+SBOyWYdh97kaG6COmDkw7FZH
-      OVrFAcb2Aw1xzOp0Q9bqMOQm9q46BjAlaZ6qDxMYlz6gkDfb7ehGCYEuygKLFgb5jvTUc9tx6q+sBxN5
-      IpvWimyHquUwyU4d9rhFWmVxzra3OObPY1HTJm5hPBahkHktJMLAYxHUTPe4PlbMAD0O+1mPWcfhRk6n
-      zsX9fmpXzsX9/m2V1dmWlzVthycSve/u0B47cUTaZhGz+nCW3vJ3aMTe51jq20PYAERhNLLA9tU+rrfP
-      ZFVDATZOwwdu8TCa9ScKsxHfjhog4FSDZbyFJzwKJE4mxDGtSCtAYTwSIaCaMXHEz3/exMjz1ozq86sw
-      E0f8xNmxEAuZCZ+yGRDior5iMUDIWTLaTAoCXLSP0iwM8NE+T7Mwy9evV0h+W2OQmDVglBhxTIhEbVog
-      DjQStbVvkKiV3PLHVtC0DjbL7nMaQ7DCG4dcyLm4188YTIQEaAzuI+B7AqjtAmQFUeuYCL+rYspdFWF3
-      VYzdVRF6VwV2V3mjfNgIH2ssDhmHu72///3xQZUy5FmwNoua5d+e0orekgQNaJSubcUYBEAcaCRxpGcS
-      h4bt27pinbviYCNlFVCbQ4zUfKxxsPE5FrJZmVUc64mFzZQNiGwONlKfuwGDfeL5WCfla8GRnljL3MzM
-      nN+tl4s5uSVlsZj5e0BjCpNMiUVtTmGSKbGor90xCR6L2ngzUdxLfkItFjezGlYA74/AqIRBAx4lY9t9
-      zwS1bDBR3CtS9umKtPZ6g+6mGL2bIvhuCu/dVJ8fLu9mt6wbqsGQu3n5VdTVG93co14vu/C0DaNRWMWm
-      bRiNwiowbQMUhfpC8ARBrtN7Pd6N1WnQTn+Zp3GgkVNHILVDm8701wQ2DLl5dQ5W27STtNKKbjyRiJV7
-      43sU8zYLs7KfaNswGoX1RNsGLErNfO8GCcZisC+kRt++NT9R/QK6WFGYLSrzhGdUJGTlVFpwXcVqeSBt
-      jrJI86xgPMwdCDnpnf8BQ32E5bNd0melvqGyYcjNasO5rTeZ2+fX7fem6gulWpZJtEEbSADHaEpSyobk
-      IIy66XNfLRY2Z8lP7hgNaICjVGldZelLGhgK0IzEo78nBg1wlPYtD6OBAPBWhGbXQHIboacgG7XMO0G2
-      q90s6u7+hlNMObRtf/zEu/KBg43ED8s1DPV9aBc1ZWo7GrZnrJPNkHMl3/keg32Cl5YCS0sRlJYCT8vl
-      w/1qTl0BQ+cQI2NlBptFzOSvx3TQ46TPwXBon12E6YXf37xqSLj6lvbbg86/F3hi0OsIh/bYAxLHmzJ1
-      dRT8s25oxE4vQnrOMqoVcHjvCw0SsxJLYo3DjNTSWAcBZzOVPa7riiztSZ+V06+FBGMxqP1aSDAWgzrg
-      BgngGMzlNQB81E+emgkrgDjtZwaMTSJwAxClGxJk5ViNhcz0wcQBg3zEGr5jAFOf9KybZ9CAnVXwIWVe
-      wLx3F4f951G6j7Oc4+5Q2MvLUifQ4+QWgRY/EoFTAFq8LwK9AeLiiN/In4IVw1SMxQmMgfkPxw2n0BtQ
-      xMufVQ8agCiMRgrYPuE0TeBWCX1koKcwG3X4UgdR5+7AdO6gcl6EPw1iytMg+LlV+HKrOtiNq9E7jJAA
-      icGZl26xkJk6L/0EIS7yvHQdBJx1SR8e1jjAyJhNPmCO74/73+c3/O9qIQEeg/z1m8UiZuYXrC6O+clt
-      wp5DjIzW2wAizqYZpj6d3sZqcasb6gcmHo8vYjsP9O6436QVP55uwaOxbzH8BaV1lNfkgxTjcegNP0gx
-      Hoc15dzjGYnIaXAChpEo1K8sAR6JkPFOPsPOmN626jnEqGrDd3jIXY0nXvAjbkusWKvFF3qJeIIAF/Eu
-      tgjgod69jrFN6/vlvNm3g/MGwaFROz0FDRT1trtTU5ckAPiRCMeqSgv1hUseFGjQTIvXfs7wHiFbkz8q
-      /YUXJBiN0aQAsSGLWkailXm2fYtqfu6zNf54oi6roEiNwB9DVkHqNQZx/RpM4ot1Hm2f46zgx+kE/hih
-      efx8Qt4OvZDx6xie7aDCyNB446VVVQakWsuPR5AdkEP9HBqntfij/aTPZAcNY1HUbu/NHMqwUL1mJN5B
-      Fh1Z3RUhQSENExqV/MGUiaJecntDJ1Hr4VgdSqHWZX6WTTDuiVsWNFq3928umHF63h8hpB4V4/Vo86kt
-      v5Q54X5/QHkpRstLbbmOgBidYSQKv/TqeW+EkHJYjJbDIrhkFBNKRvWbXR4/BTwXLe+N0D2lATE6gzdK
-      ne1DQijc7yfPQAF4b4Ru4+PtJiBK70Ajde0/tZPG9gczkuFAI/2dViUzgEJBrxpzZZaBJxT3sjp5HYla
-      87L8wepeDzDoZvas0V61tvIxpzjQcdzPrSFHepltl0PeW+aZd7DHzWs79Cxm5s5ChwRoDHVtzMyt47i/
-      mWsTEODEj0RountJUJBWMRJnGIIMijVo8HjssTeNRu3tgjvcu9LRXju7C28K0Bht8RfyZBuK0Tjsp1w3
-      oFEY70hteMTNazs8jbYb8jJWdVGbmzlJZArAGLx+JtbHbLpTsgbNVMA4Dxo8Q11Y5HN2PTfAmDukNBdj
-      pbkILM3FaGkuwktzMaU0F+9TmouppbkIKs3FSGmuL3N5iOtnwYxhODyReH1nf785pK/p72eKoLpOjNR1
-      IrSuE+N1nQiv68SUuk4E13ViQl0X1ucf6++H9MX9/XARUkcLfx0d2r8f79sz1gfVQcu5Xj6uyDs2DxRo
-      45SPBglayd+pDRjqo085tFjMzPh+zGJRM32Wi8WiZnqpbbGomf4cWyxopn7R1VOYjTVm7dCW/Y8ZY5+G
-      EwS4iC9R/oBWT1J/pLbDO8Y2zZeLz9+jh9ly9q3dP4XxIgyTjMaq4w1x7UTEMRLpPHouiRkYVvjiqMKv
-      YjyEmMQXi54hbdpnJxfVDj1mpxfcsGI0ziFNq3eIddKMxGMU7rBiLA696Q8rxuIE5masZjF+xHm1DAl8
-      MRiD+wDvi0Auji3Y51ajDXy5osfsjA/sEMdopLCSuFeMxskOgVGyw4QYUSy2wXGUZDRWWCnWK0bjNFV3
-      lorAWCfNSLzQkkxMKclEeEkmppRk6kcqb75DrF4zFo/TgcckY7HIr+5Bw2gUcmcDVvjiNI1GVkcX11jx
-      2F9Feb6Gag5VafOxHGPRVxeH/E3isfU67drJ3+DA3241q+HTm6kDBvrI1eyAWb5mdhV/B0cXB/2MkSQd
-      dJwqXPyDOOwxYKBvGzNs2xh00dsoGgcayW2RAQN9xDbHCUJc5LaFDsJO+rsczxucsNU/xlb+6I4zqjeD
-      BK30KkbjbCNx6WR31WT5l35aObmKtWHAzXICLuaXsugXsozVV8CVV6hf2Lpf1jYlBH1QZcAsn/yvRNvt
-      JJb/YuyaglqQaJwJShZrm6kpAqRFM37CXIjDYiFzUdazXU184WeQiPVTuqN+K2SikLddRyHaZLWoGads
-      4JCftw6Pdw2e5mC9EeoHcf5EFw+sa+YMPKCr+jQHyq040HWKcm39e/hmMkZcpTHV7BrGolA36YEEE2JE
-      afESHEdJxmKRd0cCDVOihF/SyeKJdmqvhNwmzQFE4nxNgH9dFfRN1ciXVJw1FeC1FALWUPCunRCwZoJ3
-      rYTQNRLG10bgr4ngWwuBuwYCvvZBv0xWkiaqER8dRfyUcuSWAovTLHJEH2ADeCACd/fhJ+/Ow+ooP2l8
-      KcJY0Qlde+wpZK2GJ/8aDWFrmo2tZ/YUsgbVk3/9qae96ghFcfIvmrXHLJ/Tlif3H0HDaBTyZh2wAo6j
-      0o17HSfWY+aeew+PuMnbjkACOwat0HbeXsrnM0voI5wDBvrII5wDZvmaieKnOcr0Rp6Lo/4AN+rlnzJ8
-      ttSXv+77XtUBkSlNXwRRBy3nIa5EKrvk5T7aHHc7YpHu0La9XXOjGRijiTUQdubpS5qfetNJyrFbCl8c
-      dZzRzkIccKTmuLYyCieS7RiNRJ/IhTjGIv11jPNsl6WVCIs2eOCIan0X+piUDXvczVk0d5QdYVCMxWG9
-      aEctY9GOshZ/p5CGyhO3fTTYT5btsCORi0qwjOSsE4usEcvd3Arf14q14iyy2mw3dsgYdDdIy9q9TW6m
-      LZKkOmg5uWsq4CspiIC+nfD27dRR1hC0DsJOxgC0QQJWRn8RXf03aG2/kTX9glYVHllRmLuaML6SMHkV
-      YWAFYdbqwcjKwUNfOTkSO2UminrpZa/F2mbtdpE7kjbsc5O7kg49Zid3JkGDE+VwKCu1kkc/hkWM4fBW
-      BNYoBzLGcfoztVrVONvYrmetlqKmGQfONjbTlOjVlsZZRsZsHHAeDuPLNvB7ttNXaNRFWDQON3arxola
-      PsxPXL0hMWPFNW+XIp3DjYz3DADu9xPfNwC430/cmQjAHT9znx2TdKztdtGyTcZLFRuH/JxThndx0Q7w
-      Mol3BxfrOCsxvDmEv3eLA5vul4+c2ZsD5dh4c4kM0HEy3kcOFGZjZAMH9rmJmcCBfW7Ou0nYgEYhZzSb
-      HczxRRZ9md/Nl7PbZm/mqVabM42LBwkv56sVRddDiCu6u2bpJGcaswPh0+0e0BybLKplrzzaxEl0LF7V
-      bK463cvGXlxNbkN4Jf5Yr1VZPMlGzFMmCB3gcRMQdZuXG9lTjKrzD+Q4Gus1nweYz73miwDzhdf8McD8
-      0Wv+JcD8i9d8GWC+9Jmv+OIrn/effO8/fd74J18c//SZNwe+eXPwmgPOeeM9522Aees1JxnfnGRec8A5
-      J95zFgHnLHzn/HO/5xehCva7z0Pc5yPuoBM/HzvzsFMfO/eLIPvFiP1jkP3jiP2XIPsvI/bLIPul3x6U
-      7COpHpToI2kelOQjKR6U4CPp/WuI+1e/+7cQ929+91WI+8rv/meIG2pBNJ112Wxu1wtJsird1qeZjeRY
-      PhkQu/nmOiyiqwDi1FW8V++Ci5TsH1DA2/U4qrQ+VgVZbdC4XdTx9IFXEPa5ywNfXeqtu1ScX1w9bfci
-      e4nkP6Ifk+cGAKjXG6XFNvp5HqDvDEiUJN2y3JJDjOl204Tc5OX0KU64AYsij+/FU/TzF16IHh/zX4X5
-      rxD/j2THEkvOMF5c/srNhzbq9dLzIWJAotDyocEhRm4+RAxYFE4+hPAx/1WY/wrx0/KhwRnGaFtXTf1E
-      mClhYabv+TXabrbqAqq3Q01RmqRrrauPF6ej7b0VVD2gcOLInMk4845ybF1eZBg10rXyjIitXVWmTRRi
-      NnBp0H5Kcp5do017UfJzm81C5sAch0qAWIxcp3OAkZsmeHoE5BOIRyIw8wrEGxG6AvC5WcXmV9LGZDCN
-      24PkY27Z0H97mf6WC+OhCN2h6LmsCsL7DYQ3IhRZJH/EyOYmCDnpGd0ENacozqOkjOJk8go2GmJ5VBVO
-      mb1tQICLlKd0CHBVKWlrUJsDjCJ+oesUZLt+Rtvpn2tqiOvJLrZUj0Qsz1Mqc3KcZ3+nSTNhqy6jek/S
-      ggYnilrQv8y2qSzC8nRbT9/DDeOBCLsszZPoUNPdPWlZszrdR9tyv5F/oWd2h7bsVbprXpqrh78ZsWl6
-      9pT9u0Y0WDxVjZRFyovSwZZbBN5hMXqHj/WWmUMNcrBu0vQY7ctEFiJqJnAavcQVZXEdjNciZGU3Cidk
-      s4i6eyFMm/ZdEonn8pg3I1jT5wgAqOlVq07JnKSmmapk605A/SlOEtIV+E1mVHWQnkYD5drUDHr531Rd
-      h2m+IorVwifHjXygC1GT8gnAmuYkiV7LKhEU44kxTNvy8EZWDZDhSmSDh3OtBmcY058Hed8JqhYwHLus
-      FvKBI1+kwZlG9U3kvizqp3KfEh4hh/RZI7GP85zvbnkjwlNcP6fVJcHZEYZFJkkVF08pOUFN0HQKtaZR
-      U6STrRZqe6s0j+vsJc3f1JcHpHwJ0Ib9X/G23GQEYQsYjny7Zz0zBmcaUyGi+jku9MywpKhBARKDerss
-      0rDuszxvJrbI5g+pcQ+xHnMtW5+UfaZQgRWjyOQjF71myfQFjW3ONJZJu2spI384LGim3j2Dc4yy8I02
-      sWzWXLBPGVKAcVTWJBeRLuy4Ty0z7gU4PBqBWho5rN/MTyFMg8YT6bZK66AL0hVOnFw8Zzu1QSvznjg8
-      EiEwgMe/P+YhVTumcOJwW5sOC5o5pUXPOcbj+a/sczVYyyyza/GB5GsI0yITm1U+6pxjVB37+BeiroVg
-      1xXHdQW4GHdB5xyjSlOiTCGgh9FstVHHS34AT4xj4uQQN3eUMs8UzYfQqtFZbl6y8ihkm1PesEMpZHuD
-      EGHUZUYumlEOVm/GYQ3zoXyl3bUWMByV6vXzehs26nq7Oqf5DVWss6Y5TY7bVCbNluQcKMymuk+HPOZq
-      e9zyi+xvRtpqmOnralqyUOcA4ym9m3+QvQYN2XmnC5yt2MZ1Tcv1J8T0NAOa5PPSMctXs/snDuuY6acJ
-      nuNf1dVPmU1rtdMWpXA2QdtJr3UHCHZdcVxXgIte6xqcY6TWaj3jmMh39MTYpp/sW/oTvaeMlijcCjXq
-      LnLqAbRhP3K77ke8337kNvCPeOv+lTzI+uqMspbqC34h1Np4B7UhSr5rXilNdiL8EGF7kUWz1d159Gmx
-      jlZrJZgqB1DAu7hbz7/Ml2RpxwHG+0//Nb9ek4Utpvk2m6ZLocYhi8mzFk3KtR234iLapFRdhwG+eveR
-      Jew40HjFsF2ZJvWqVv01ytOCYtM53djsHkS+Fzrl2sj3wsAAH/lemBxovGLY9HvxHMv/XTTL1b2df/xw
-      GZUHwh0BaZ9dpNPrG5jW7GpKTNnMj9nmqv+WFmra0OQSE+OHCIl6+K+v1QfiN/PV9XLxsF7c3031w7Rl
-      55Wdia/sHA5+e+BqTyRkvb+/nc/u6M6WA4zzu8dv8+VsPb8hSwcU8HaLDyz+d36zXkxftwDj8QjMVDZo
-      wL6YXTLNPQlZaTVqgtao/ZG7x9tbsk5BgItWOydY7TwcuF7P2U+XDgPuB/n39ezTLT1n9aTPyjxpiwci
-      rOb//Ti/u55Hs7vvZL0Og+41U7tGjOtfz5kp0ZOQlVMgIKXA+vsDwyUhwPV4t/hjvlyxyxSLhyKsr1kX
-      33Gg8fMV93R7FPD+sVgt+M+BQVv2x/VXCa6/y0Lt831XSZMCQAIsxu/z74sbnr1BLe+xLh/ajWp+nz7v
-      3CVN66fZanEdXd/fyeSayfKDlBoObLqv58v14vPiWtbSD/e3i+vFnGQHcMu/vI1uFqt19HBPPXMLNb03
-      Xw9xFe8FRXhiYFNEmMBmc5ZxsZT13f3yO/3hsFDbu3q4nX1fz/9c05w95vi6xCXqOgqzkRaiAlDLu5rx
-      HikD9DjJN96Gfe7py1BDrGs+bvJsy0iIE+cYo4fHT7IkI/o6CrMxklQjUSs5MQfQda4WX6g2iTgeRjF0
-      gkzX/JpxVj1kux5UhLQm7C5gc46R9RDqHG6k5heb9ZhpecZCbS/jYekhxEW/dPRJGQ5RLxp7TuY3i4fZ
-      cv2dWqDrnGX8cz2/u5nfqNZT9LiafaF5Hdq0c1ZCTNCVEO0jK67SarssVqtHSTDrX5c27Xfz9ep69jCP
-      Vg+/z64pZpPErQuudGE579cL2YCcfyb5TpDpul9/nS+pt72HTNfD79er6etODQRkoT7eAwXaaA92D7mu
-      36ie3wAH5+J+g6/til8ZALjfT0/EK0+t0BxXAzt/NKWS6nOS9SY+6melkKsYj8NIKccARWGdP3LGnHN0
-      z+pUn0QP8+Xi/oamtGDLrfrF38nZoqcg238/zm55xhNpWZf3f35vOvPtXWvq2RXxdQoqgWK1Z0PXt5xl
-      JDfKoBYZrzmGtcVYDTGkFcZreWPt7oCC1lfGsotXT8nK6ewiPd0ldxRhiY8iLENGEZb+UYRlwCjC0juK
-      sGSOIizRUQT9CCcZdNZjpieChjre6GG1imQnZfZtRdRqJGAll0VLZDRlyR5NWXpGU5bc0ZQlPpqy+lM2
-      8imuBgActJH4DjE9jyvZom+6CBTVQJk2tfY+xaN+7xqi2e2X+yXV01KYbcXTrSDfer1cfHpcz+nKEwlZ
-      H/+k+x7/BExNi4KjO4GQU7ZQ6D4JQa7lLV21vIVN5P6DASJOYvmhc4iRVnZoGOBjNTZN0mdd8bXQ00Id
-      Y+ghxBXN79bL7yxjiwJeeiWkYYCPsIOYzsAmXg4/gYiTk8M7DjEycniLgb4/7n+nTaDSOcBIfE1wYgDT
-      HzN66SUZwMS5B3D6M9LeSHcRR82KNPt0+kcbBjS40m305XP38TNh1xkLg32b7Kk47tWc+F2ap3uO21LA
-      cZJNznFLDPY1odRHeRxrD/vc4q+K75awzy3Tqk01foReAcd5qsrjIZJ/zqbvm4nxvgiU1R5g2mdvloo6
-      VtPXY/Mo4DjMHITmHTVNWK2DwJQ2LG4+NL1JrrulHbu8xbXaz3KrtnMX2ziPK7UyiyCGwTROPJHtDzlp
-      t1gH9Dijn9G2LKskK+I6ZQcwLFi0gGcMMPijPDGfBFjij8V4ph3eH0G8x9WIsatp1qhgXknLomYRxbX8
-      jbpz9RszguHwRCqLkLTSBFiMpoCQF9ys0CAzPXV1vGk2LPqhVLveq5XJePEG3h+Bn6sH3h9BZch4pw5r
-      hYcIiQkbx89CNg7CMieoMuKSG7c6Y5j4TVBfy3M41tZFLG2LGt6AKsZbr6hVHo51Gr3ezT5TnBpm+NpW
-      Iq270DOAKf3rGOdkV0MBtiJ9IrskA5lk6aYWQI32sfhBd+o0YG8/zCdrWwzyHTd02XEDmDhdCF/PQbUN
-      9MwpH1b6k4NLzFhN/V2krxT1iTFMhx/pG7UU6hnT1JR4T1CBG23eaOX4qAuI3KxUQ01vG/V6qf0SkPdH
-      IPdPEIMRRa3bUjaPavOkkhMJ5I0IXWxaYTlAkKsp+BgNKQiH/MylTFEBFKNtxPFDmPx4BH5ywR4woiCt
-      uu2AkNNc4Y2uNnkoAmuhJwQ3/W1zL/iGezR6vHaU4O+Ly1+j+OXnRb/uzW/TY6EKJA51VTMQRtykVozJ
-      IUbVXwo6Y13giaHWfQmKcRIgMdpynVSgQvSYvatfw4J0Em+spJT1UkicVoDEOOXhS1aAnh6x/xZkx56v
-      oJwE5KLk4vLy/J+M7qUNuk56Y9EGB6daFOLpORbPqhSa6jMgyNUsM0G3NRjkUzsJ0XWKgmxCiPQjXddg
-      lk+eb01OuRMEuegpN2CQj5xyPQXZ6Ck3YKZPDcRQE+7EACZysg0UYKMmWg8BLnKSDdRgyy7igPVZYNqy
-      89YnAVDAS1yJw+YAI231DAsDfLSviy1M9225K90AKOAlp+QWTckkKEclIzkq4adD4kuHhLnij0tCVtqK
-      PzYHGDlPVOJ7opKgFX8wHo/ATGVkxZ/+OHnFH5eErNSnI/E9HdQVfwwIcFHLrAQrsxL+ij8gDLjJK/64
-      pM/KPGl0xZ/+F5wVf0AYdK+Z2jViJK/445KQlVMgIKUAZcUfAwJczBV/MB6KQFvxx+ZAI3XFHwAFvKwV
-      f2Dasoes+IMKsBikFX8A1PSy1+YBYdMdsDYPglt+3to8AGp6qWvz6AxsoswttTnLyFubB0BtL3ltHgtz
-      fMS1AUwKs5HmrwOo5eV8VeeAHif5xuNf1bmHp08zhljXTP2qzuYcI3Eiv0lhNkaSgl+TWcfIiQl9TXY6
-      RJjeriGOh1EMuWvzqD+T1+YxINtFX5vH5hwj6yGE1+axj1DzC742j3OUlmfQtXnag4yHBVibx/gz/dLR
-      J4WzNo/NWUbG2jw2ZxnZa/PAtGnnrM1jc7hxxVVabRf+2jwwbdp5a/O4JG5dcKULy0ldm8eATBd5bR4D
-      Ml20tXkGArJQH29obR7t77QHG1ib5/Tn36ie3wAH5+J+g69NW/1mUexKjhlQjMehJ6hr8EYJvJLRqwi7
-      gtGzL7Ik9Ao6xXicsCtpDUAU3rpJCD7qZ6WWb90k7EeM1PKsmzT8hnX+yBlzztE9K+a6SSBsucnrJpkU
-      ZKOum+SSljV03SSvBIpFWzfJ5iwjucEMtZZ5TWWsncxqJCMtZF6vCOsTBVQbvhqDXVl46gnOQAQyCrHk
-      jvAs8RGeZcgIz9I/wrMMGOFZekd4lswRniU6wsNdNwliPWZ6IoDrJnUHGesmuSRgJZdFS2Ska8ke6Vp6
-      RrqW3JGuJT7SRVo3qQcAB+19hrNukvojfd0kkzJtlHWTTr93DbR1k0wKs614uhXko66b5JKQdfpCRzoD
-      mKjrJjkg5CSsm2RAkGt5S1ctb2ETuf+ArJtkHCKWH/C6ScYRWtkBrpvUH2A1NrF1k9xjK74Welqo4z/A
-      uknGn2nrJgEo4KVXQuC6Sf0BwrpJOgObeDncXTfJOMTJ4c66ScYRRg63103SDpDWTbI5wEh8heOum9T/
-      lbBuks4AJs49gNOfkfZ2ulfpUOrUG9ILKguFvepeM70dCnuZTstXqpdM9Ea+gek+wZ9RKXwzKp2DEXHi
-      GyIAYpDnJwp0fqIImQMo/HMAa958xRqbr/jCnwv84psL/MJ8D/aCvgd74b4He8Heg/341GwtLX8tOy+r
-      v6p6/Tq5hIJYv/l2+pa2CK757w9poQ6nsSiLVa1+fRPX8eQACI9F+CPOj9O/TodYv5mSNjA++PP0Jc2b
-      b+6KMpn8OZ1J2Tb5nxxdj2m+5yhJ83T6mh49YDrKOJenWz1RNCfGMO2qlHIu6ucGnxWCsABSDxgOwioN
-      7a9N+riPsjqdPgFGZwxTlconIX2hpMcJAT3Rj+m1q4UZPlFX6is3gqojBss++SXa5OX2R5TI51x9XptO
-      Xt8AYnXzZXc0FnuWHeaHCGW7YRW1vWJhg+/wYyvOL9T9r+I6KwsRxdtteqhjwue3PocTSX3a+TS9iDMp
-      x3bYpFFaNBuHkxacQnDT/1u0ORYJLR1OjG06xJVIo+c0JuQGlzStV835J2lz/hSpAWrOUuaOt2gbb5/T
-      trxOCPUoTGN2QknrgIhTpDVLKTncGO3jw0G2CLjmE+9EaB5uRjL0HGwkVB8W5vhUZd2soUV36ijsZVx5
-      z8HGfVxvnznKBjScb9HyL8pKpRoyeNQyONGurH5Ex0LEu1QWDLtdqlqXsshRRePktRrGTVpUzjrIFbwO
-      svqz/M9YfRpNLGUAFPYe2pdvUS0vUshr3HMiOBI4lsieiqiKXzkhTixm/jvlWf9OTSN5zQQDMlx/R+cf
-      Ln6JnuL6Oa0um9VbCFKAhuxq7ROe+URC1kLew4sqTZhqA4f88tiF+hHTb+CQX2zjuuYnuoGD/r8qrroj
-      B6s47c9OHPWxOcDIGfUBYc39HJ+zG+8gbLjVIikBdgg3/JdqLinfD+GaX/45TQ+ktV11xjJReuY9ADii
-      Q12RPQoyXcfD/1/a2S05CgJh9H7fZC5nUvs8liEmUnGEstFy3n5pNGoDZvzc29jnYFSQH6tBJL0VNPdH
-      AZzDJQ90V+ZwwWMzAwsgHVSQ6VyF/JGFESagQzdFx3TR9k2DKQIiPcdzaU7RgrYGeR58dEyj9/SFZD1F
-      NZ5QeUra+uMTG3O44IER0BQd06HPfu9bhWkWTPpqfYfOh+OlwUB1hsMFP/CMKCAI8cKA5C6cw1fe8S0O
-      I+HjmXK3zGoaXi9FfG0ig0rvmbWJYXf/7OHs/tnD/v7Z8SGgsmXQjfdSlNxz1odb1JWQlsYhhsYJ+qpM
-      SwAf4oVB+QEoYgjx0tA1nEbyBiTYllRiA1r3lUgsXVjZAEUTFLtumEXeYd8p8f0t/zMgWRhhqkZXPHtA
-      MwHC4d8dVFfkwBPaYsKnbxbQ+GhJt3eD4D484mt95Yxp7Q90GhtM+LiC9lQ+kCd5YYSpLb85l3RLrit1
-      65AqFqPSS4Uu/xaNJqTd2FCRTQF9ywUQDqPI8qy9f0KQe7DFUl9rVF2pJ+qbMeGzSgMaHy3p5fYWtuq0
-      QZqChJXmebr31DOSwjn3PIF8QvwihZXA6kpJfSX4nUmZdyaNbYU8tCF+Y7BlRYW6qtf6zWFVDCZO112+
-      llWhMNomUJ4xxKWA86kCil2nrsDOv+fe/FwMsmKbhXPu11U55d7Aq3s8mcB23M1fOx/xNR5IqCygnIsT
-      wIfNCNC0628UuXLsp/3kDOT2Cy9gZd+aL/9hvmTNFz4WFs1OXPAtnbNPadI5wyvuXtn3Zmizh13BL2XQ
-      N3+1YnnPt+Obuf1uypZ6fOMUAeVczkAbeiRg4oQXScbdvNLzEVI8qd8r9BYu3MbI35je9IM72mHVqGwe
-      ptOuPjwe2jfkSxl8v+T+A33/sINHfttxKvWwwkRUYJl1dgVRGXxQuTG0DYTZJZrxcqHcMrgR9q6o9PL4
-      O7TA/mBdQd4ITbz+t7BXEFRXUjTxNsY8yQ8bnlVx82MIHpmA+owhKWUa8ADNksQ+/vwDGuhgXgNaBAA=
+      H4sICAAAAAAC/2JvcmluZ3NzbF9wcmVmaXhfc3ltYm9scy5oAKydXXPbuJZo3+dXuO683Kk6NRM7nW73
+      fVNsJdG0Y/tIck9nXliUSNk8oUiFoOy4f/0FSIrEx94g94arTs10TK21SRDEF0Hgv/7r7DEt0iqu0+Rs
+      89r/I9qUVVY8CpFHhyrdZT+jpzRO0uo/xdNZWZx9bI6uVjdn23K/z+r/d/Y+3rz75bf4Mn3/22/vLt/H
+      v2/eXybb399d7tLzX88vkg+//fI+fndx/m//9l//dXZVHl6r7PGpPvu/2/84u3h3fvmPs89l+ZinZ4ti
+      +5/yJ+pX92m1z4TIZLy6PDuK9B8y2uH1H2f7Msl28v/HRfJfZXWWZKKuss2xTs/qp0yciXJXv8RVeraT
+      B+PiVbkOx+pQivTsJavlBVTN/y+P9dkuTc8k8pRWqbr6Ki5kQvzj7FCVz1kik6R+imv5f9KzeFM+p8q0
+      7c+9KOtsm6qzaOMehvM9HToc0rg6y4qzOM8VmaXidHXrL/Oz1d2n9f/MlvOzxersfnn35+J6fn32f2Yr
+      +e//cza7vW5+NHtYf7lbnl0vVlc3s8XX1dns5uZMUsvZ7XoxXynX/yzWX86W88+zpUTuJCV9g/v26ubh
+      enH7uQEXX+9vFjLKIDi7+6QcX+fLqy/yL7OPi5vF+lsT/tNifTtfrf5TOs5u787mf85v12erL8qjndnH
+      +dnNYvbxZn72Sf5rdvtN6Vb386vF7OYf8ryX86v1P6Ti9F/yR1d3t6v5Px+kTv7m7Hr2dfZZnUhDn/7Z
+      XNiX2Xp1J+Mu5eWtHm7W6jI+Le++nt3crdSZnz2s5jLGbD1TtExDecqrf0huLk9wqc57Jv93tV7c3Sqf
+      BGTo9XKmzuN2/vlm8Xl+ezVX7F0DrO+W8rcPq475x9lsuVipoHcPa0XfKWeThe9ub+fNb9rUV+khz6U5
+      i/lSJsTXWSP+ZN6N/2zy/8e7pXTKxyeaXV9H98v5p8VfZ4dY1Kk4q1/KM5n1ijrbZWklZOaRmb8sUnkT
+      apXFZKbeC/UHJcpq9bSqHFfuzvbxtirP0p+HuGgyofxfVouzuHo87qVPnG1SCadNIPn0/ue//Xsin+wi
+      BU/n/8b/ONv8B3goWshLX7Y/8Dr0H57FZ//+72eR+j+bfxuoxV20i2QpA5/D8Mf2D/8YgP8wHCKtqZYO
+      GTzX65tVtM0zmVTRPpXFQzJV55KWlaEDPSKtntOKozNIy6rKwmhz3O1kduO4Ad6M8HweXfBT1qUBO1OL
+      +tgp7dKOPSQl/OnwKPN0ne1TVbPRvBrpWJ9kDZenTLEJO25WIiBXH3LP/HdMlRVZkdVZnJ+uJEqOXclL
+      DYSrhrjz5TLKyziJlEG1bmRTbGogiB3Md/fzW3VAnQOlyLS5wXg//xpVaRdvJZsLqk6caIVYwLzJyiC7
+      xZsRXipZi3L1Dgy5A04fFAwx1B+vFvey5RIlqdhW2YGSJWEatKvyIT7Kcr7IEoZex1H/RrVWeG6Fot5t
+      dpDt+4AzHwRojCR7TEUdEGMQoDHYbo/z+8+oiPcpU9zRXjv7rFsYde/jn5EssgUvv1sGPEpWhEYZDGiU
+      gFvgTf9DtQu4AR2N2qvdNuTMTzjqf47zI1fesLg56I767mYmoljWOAxzR2LWTV5uv3clEc+uG8AoopZt
+      tbhKuDfV4K0Id1/vozhJom25P1RpM0hCbKiNaIB4uypNgV8KckRMBMSU+eMdPf0MEra+yYUgHiRilrAC
+      ZAni4yYLlCrrv1Q+eBdtn2JZvm7TqiaZXRz0n4f5z8f8zRHjjsT5IyMQ6EEith3IqxkrzAmG3enPuorD
+      ksxxwJFEe5mcAB3qerdPqSwfD1X2rMa/v6evVLsjAGK0LUl5bY9VeTyQI5g44M/TuNJST5Aj2AIshn2f
+      mJEcDRZvXyYpL4QiMWvZ9HiY597Brjst4k2eRuVWHFSleMhlF5waAnKgkUT2WKRdKaAGFSSwPwhmSFiG
+      xq5zoe5fUaQ5tcbAJG6sXX4UT6dHl3xhJg3YZf1OdkrGNTWVuEq5bJdtZSlAtdo8FkE9Lzy3In1W3sNs
+      80iEQ1zFe5a7ITFrW+IySmwLB/3tgyBq9eaErtdoxN7n+mi7YQXQBUiMptoQLHuLIt5TcyDKM1Gz9IYB
+      jiL/FB9z2R2NhXjhppIjmRgrOoq0SuI6fpOgvQ2Onv6MuKE6FPUW6YtsNiTpT6a857EIga0BUALHyopd
+      GW3jPN/E2++cOIYAjiELg7x8DIpiKeA4agiqKSG4D5AhwGMcqrIuWcMemASJJW9deCxbgsRitAhPHGxk
+      tgY1FPb+OGbqZfPTsU7KF1aSmAY4SvOmI36ijj45NGzvWk8yP8tuDjvtXQscjfiuEUARby5kKSN/s/3e
+      PqKsm+1a4Ggy+2a716BSxFJ44yTpoX4KCNLw3gjc267hrr95V9n9Ii+3MesZBCVurCKVPZt6f4iWK/IA
+      iM5C5he68MX1VOm+fE65Axwm7drVgSjebuWdpqo11OuNHssyCZA3vD9ClRbpY1lnjA4WokHitcXU7pjn
+      rDgDjvk30VNGbyzpLGYuZadgy7vJHes382+zLhiJEXqjAQ8SsemMNLdLZH/zgpkKT5zmhxt2jBb3+FVb
+      PcDf4h5/V8gEhOgNSBT2Q+F5ItTU3JRnbVHEWxz3G+IrORNFvCI8R4opOVKE5UgxliNFWI4UYzlSBOdI
+      MSFHdq1KXv45wZC7ftdNnYwOZcmoZkweicAaLxSe8cL22GnwRvDUPY74T21f9vgbbAGjnbPT6NyTRvLY
+      sXrmlDo96vWyhg1sHonAGqsdSMQqssc4f+QlSMf6zfwk0QVIjLB3HYACifMWOf98Ys6PZNeyfImOxfei
+      fFEvjg/d6AvnJuEyLHZgtCl+keaqEcipHWwDHKV9+87Sd6jHy73/o/e9OR44RIF5kIjN0G5cJJy3644A
+      jcF/nyLG36eIYT4os6TRccQf9F5FTHivov0mJPMaBiTKsarUj1QbiBvGVGBxZFbfd/mQF0UTwDGC30SJ
+      aW+ixJu+iRLEN1H677vH+hDXTyIkru5BIpaiKcllOdsMEPPS1pbAsdK4yl+b92Xd/ANOVQ5YkGi8t3rC
+      91ZPHdzFuUjV3JCqq3bTJOo+a21qLU7AMSd8Jo9VGkssIC1NAxwleyxkXaYaUOfvI/Ua5LGKE1bNCJuQ
+      qCFvG8X420YR/rZRTHnbKELfNorxt43iLd42imlvG08/E6lsDeyq+FF94sqNZUiQWKFvNsW0N5uC+WZT
+      oG82myMiLHvp/HiEKK4eQ6MoBxypUO/e2lQMatlDnrGIIoqTZzU9S6RJcFhLBsduJgBWqTiUhWBlCkOA
+      xOC99xa+996i+YCknwrLmeyPWpBo4nvfIg3I6oAGj9d9Nhoaz9Ig8bolLDgxWhT2/jhm24Dbo+GoP2D2
+      g5gw+0EEzX4QI7Mf2uO16nmWhWzxiaf44sOvUbnT+z+CF3XMip1N156WbVz5ZB/3KS+6bYGjnQrHYVYq
+      s+QDRVjM0NkmYuJsE/13qstfFrUsoEOiDRZ/NPXgJ08pd66LR4XEheZ1s5uCuA2PnhWP6sOUspI9in2z
+      rpDghgZUSNyqPqjqdpflKS+aLkBi1FW2DR4Wci1wtG7akfpYMKDYdi1YNHbu9OZGcxw8pO8Im9CoqvnV
+      1rfqszJuUxUUTY0Z0lzAbf7odVwfRejV9pIpsXiVhO3wRhpm4IVFMzwTI4o3iSe80Y5qMEaWPwGhTgok
+      jiyzkyeWviF91rBsbirwOOmWf/6Kxc2ViLliiXq9wUmjO5BI1ZFXDTUg7OQPrvtG1btW6Bs0DGCTNypr
+      zqwYnTN7VF3uHdXbUoBNPsP3bS/4D/qLM5Mes0ez1e15WIhGMRpHtacC4ygFHGe5moUlmCGYEIOdbK5l
+      SjRu4rkWOFrAJ4wWPupnp5ztGI/Uvj7mph1sGo/6FvHwSKrr1y4XWb9GTxl9DByUmLG6ZacitfRp/zpo
+      eP1FiTiiguNqb9q28UE17zkhXQscjfo1sM5hxnIfbV5rWgfUpWF7++0teWEYAPf4eUMjiMIThz3cjVs8
+      0Q5pQJopeMStP8MiKJBhGovajiWGxWsdnkhvM5w0Uek5j7YvxY7Z4qif8/YewL1+1re5mAOPRJuwaJK4
+      da9WLa6oE7pgAx6leV+2LXPOy1efB4/YddHzbJc2846oVeuYyxd5n/Ij7VO/mTiWB+C4P/DmeO/JUyxC
+      CzdLgcfhFykDDdsz0b5q4bZhdB6OQPwOUcNgXzOTmFd0dKjXG9KqsBRonJAyXIyV4eKNSicxuXQaRu+5
+      cXw5VASUQMJbAomwEkiMlUBC9iXyJNqor52KxzxVPRtWIMADR6xLfqv+xPrN0a6sAm42oIHj0cerTNK0
+      0j8whr4rDljfz7u2X8C6ft41/dir63lW1lOHVN+/m8x/3Pwr3dZC3VfZNqYNH4+orLi5+pFaFLpbQZwU
+      yYZH3FFeBgZoDFCUpu/cDdWqijOv6XFcBxSpfj2k7LTS4BE3M61sgxmlnR/xlJESp4csl5q20i6QR7IN
+      mOULWZVxZEVG+lkC5xey4uLIaou8lQ+xVQ/ZKx56VjtkLDMAri6wPdb1U1UeH5+aVUzzlDbuDOCmP0nz
+      9FHtcRVtq7QZ6IxzVa+T2rWoxIpVNpteyE7Gd9JF6JxllJUs42MgDTN97UhoP9N2W/9Ua2+lza5BqidG
+      CTLmgiI3Y7BtlU+7AwBu+QNX3hxfdfPNVtwkrLYZvNLmhFU206qSbUTmJhIObLl/Hsqqme6g6p+9fIQq
+      +eiQAoAGMwp13N4dr+83v1MTQZrl0ik+l7bt9Tv9c1Ja1ndpwK6/MlJVviBHcAxQFF5l518jtF3+fJiS
+      3y/YQk8l0AJEY79rGHvHwFvrFFvnNPxtwpS3CMNv7FkUzFCOBojXzXuv0h9HWfDJYpC4lgQqAWOFTPJF
+      FFCcN3kvQnof8tgsX0BfMUznHGPUvSAmCk+Y62POKbBQwNtOmN280jcMAXDUz7iD+Fxe5qq86Iq8Yavx
+      jq3Eqx2vZAu13DPlLQy4uw+86S+xXdpjH7ZHYIcYFHicYQNOZpReAMZ4TomNP53DjNStOUzStZ6++2aM
+      9wK469c6AurLYXpaOwIghmrUkr0KAlz0NxDo22PtQPTXh3e/R6v13XLezOXJkp/MEIAJjMp6V+1/R90t
+      /bwXkTgeVDOfrtZg170jPy074DmR/8jEU0p3dZxrZH9ZPrKGdXP4mVyvSMT19F2ZKE/Jz5gBu2721+gj
+      614Hr3k9Yb3r4LWuJ6xzzVnjGl7ful3V8dQTiurye1pEG/koqs40p58yYnOjM0Yd0VW1m3kcp84Mfdk2
+      APf4mQ1Wm0cicAsVA8bcxzwPTSLLgURqvgCuZeNONIM0TRYQrHigCYmqOkdxfazSoYvJigl4oIht9ua1
+      UE0asLM2MDFJwKpN6iV7NdZvJk+MAgVuDP5X42Pr5TcL0G6ykupUDGBifXfuW3G/PybUiEaxTVniEwy4
+      6Q2iCmoRiXSrnpphbWU1NMJswvlcUOR2BNT4NpceEpBAsdrRJVa/14BRt/qgi/HsmzRm5/TsBtJnbcaH
+      +eoGh/ysHjo6iiWe4kqNofEGW0watTNWNXVpyM4r/fByD6jsup2nyTFQ07SoqnPAykAe17TIrCcC8QAR
+      uesNPPrXGtDmEcePaSS+0+Z5AjjgZ79gdGnYfiyyH/Qh2oEErdr34v1LGUYISDMWj5ODXYMbJWBZ1tFd
+      Y0J2jPHvFhOwU4x3lxjtIH0SlwODbk6dg/baXxityxewdflCb6u9QG21F1lkpewGpUmb9qxgfglogI5T
+      W4iSKNVIxyp7zFSdQiyPiBL5DJM8LeJ4lJw1CGCzjrltZxGVLeS6gMpPLUBwENRE8JicqAHrfLq0azdG
+      rXiTDTwaM55qnxwPCXEcaaBMW55tqrh6JWdmnbOMavOs4QUgtTcF4IC/nSPUzkEVZL1Bm/Z9/Jht+zGW
+      fkmsmpT7UYkdSy0WGudRKR8UaqffgU03d28yfF8y4rdAzjdAxXFvdslJ982lTfshTUkNG/V729DcLpqk
+      QSxPVW7VPi3N8OOhFDVvAqdH48R7zpK0/SG13nRg090uxyhzWh872uXZ41NNfYPjFQExm1GnPH1Oc3KU
+      AQW8beODJ9ZY01wRH93KeVqZW5OhO5FpBzj5GsBtv7Bfe/+LOHMbUZhxukUehzl4lAgObLvVMs0yct5+
+      1kBTm6xtbgv8KqVOCjdJ28rZewnbdylgzyXvfkvNQeqAeA8BrqDda6bs2dT85oVzxi/QGZ+z7tE5co84
+      ez6h+z2F7PXk3+epOQp90UAOAUmAWOT3zNheUtx9pPA9pIL2jxrZOypw36jRPaPC94uasleU4M0HFdh8
+      0GZnpXYXVjUORj1fgwXMvF2lvDtKqYP0EieCyhvOljvoXlFB+yqN7KkUsNeRd5+jsD2OxvY3ao53G7+y
+      MpcBA27uTkMjuwyF70wzZVea5jfFrqy2aTP00owyiPiRnEqgBIhFn/mIrrkgyLP5BDCb7232kpm6j0zQ
+      HjIj+8eow/9Kvp+fRy9l9T2uymNBTh2bdyOw5+mN7BgTvFvMhJ1igneJmbBDTPDuMBN2huHsCgPvCBOy
+      G4x/J5jQXWDGd4BpflEfydL66HrYH3+N7KnC3E8F3UslfB+VKXuovMH+KZP2TnmDfVMm7ZnC3C8F3Sul
+      3+hEX0SS/hWZR4PE491udE+W/mDIdE1UAsZizmMZ2/eFv+eLb7+X9tgwlMYpc20eivCWu8lwdpIR9HmA
+      ApoHKHgztgQ2Yyt8N5YpO7E0v3lKE21oW/5ul5GrK1ACxeLlfzznv81HppR9XN5oD5fJ+7cE7d0ysm9L
+      u9sKo2eI9AjD9n+ZsvfL2+yYMnW3FG37iCf1Gos6Yw7i0QghM7fE1JlbInjmlpgwcytw547RXTt4O3Zg
+      u3UE7tQxuksHd4cOfHcO5s4c6K4coTtyjO/G0fzC/UCKXJhBDiASdc8PZL8P3l4f2D4fb7PHx9T9PUL2
+      9vDv6yFCZiEK/yxEQZ/rJ6C5fqyWBtzKINePQN2o/sRYFE/ncCN5KTwHNt11qV4O8+e7QLwZgb+Pi28P
+      l8D9W0b3bgnct2V0z5ag/VpG9moJ36dlyh4t4fuzTNmbJWBfFu+eLKH7sYzvxRK6I8r4bijBO6FM2AVF
+      ze+IntI8L1V3u3o9rThEDAM6zEiMMWRw1PglpiWC+r1lUBOoSAoFGI7ni/engQjyYJbDOmaWEnF1I4os
+      pcEO5vXNinfxDmg66TLIwrpgBzSdak+faHPc7WSGZJgB3PA/n0fn7BR1YdfNk2I2bgq7sO2+CEmFC38q
+      XDClmC0gFS78qRCQBt4U4AhhU8C1I1eeXGSRtgL7VKeFoT7KLBcAHbzZRcI5TwtDfZTzBNDBK2v9q+W3
+      +/Vd9PHh06f5sunKtxuU7Y7FdmqMEc1YPLUa6RvE6zWeeEmaHpoTY4fqDZ4oarWn4pjn7CAngS/Gcc/X
+      H/ce8+EonthqBXvcYvoKyxDrMZMWQIRpw75aru/l7+/W86u1em7kf35a3Mw593ZMNS0u6X57LJOiEfOA
+      T2PGUzMiF/df+jJif6A++ZgCi6Pm6NYpL0DLoubjgak9HjCn/FPCkyoSs3IyrUujdlrWNEDMSc2AJolZ
+      qYWEjRreZtnA29nXOTsrIwZvFEbdjCl8cTh1MqZA4nDqYoBG7MQHyQQxJ2GZdQdEnIQPFW0ON1IfdhdG
+      3IfywE+FE4y5aY+8CSLOZt5xyIOpC7AYhEWfHNB1hj1+Y08eN3Pg+YJW+p8Q18PNWniuEk/ZjnxnGsh1
+      UWuOARpcs6sr2QmLruerq+Xifk3dcBnBvf7pn8mDsNdNKLlgWrPPV9HV19nVZF/3e9Ow3WyjtNhWr9M3
+      YLMwy7fbnF9cspQGaVnrims1SNOapGRdh5iedLvhnJqGWT6GC/KU7HtReu6FaBbcbg5Qvh8CUNfbBeR4
+      NdT0HouXKj5QlQOF2aJDnCTTJ1SBsOnmnCd8lgHniJ/h6vY8mt1+o5SPA2J5Pi7W0Wqtft9uukYy2jDu
+      JlUVAIubH5uP9WquvMNxP1/ts1KqHxfFvYQhKgD1ekNSWcCp/PWenT0MFPVSz1gDUSf51umkbb27u5nP
+      bsnn2WOWb3778HW+nK3n1/QktVjc/EjMYyaKezO21pcO1NtlorhX8FNB+FKhLqOPt1xzA1vuT8xM9gnN
+      ZZ/ntzLezeJ/59frhewKxsm/SGaAH4lAr5pAw0gU8iMDCUZiEG+Ci4/4qdkd4EciHCrCFB3cMBKF+ngB
+      /HgE4hTHEQ0cj1vDubjXz8tXWG1nHmbmKbTWW8w+cFPFRFEvMTV0EHVSU8Egbevtev5ZvQPaH2jOgUOM
+      hNc6NocY6fdIAxEntQmhcYgx4wkzzEe+2wOHGAXzmgV6zaroOcqi9NdfuOIOR/z0pohBWtbbh5sbembq
+      KchGvOkdA5mot/sEWa67j/89v1qr9ZQIE31dEraS007jYCMx/XoKtlHTcMBs39V63ncdb6/nn8gnCgh8
+      MajFsA373NQC2YZ9bnqOsGmfPSTR/elNzikW7HNTi1kbttz38u/r2cebOTfJIcFIDGLCu/iIn5r8AI9F
+      CEgfb8qw08STGvx08KYA5QNVALW8q/k/H+a3V3POgK/FYmauFTCueae5Rs6wzW5t2sRJQrNasM+9zdO4
+      IJbTkMAXg9rktWHYTa250DrrdIAwo8XmYCNlETGbQ4y8O5Vg94dcZOEl+fBS4R37wnsYdffb7O5j8Z0Z
+      wnDAkfK0eJz+Ha5L+qzkatqhYTu1SEdrtO4AfbBLBz3OaPpOvBDrN0e7Q4hc4rCfedPQu6WW9mUK36FG
+      tSP87eKa6e1o3B767IlJz579qygW27eIpjxwRNllf1h/uuQE6VDES20OaRxu5D7oJ9Yyr38951YGJop6
+      iW0iHUSd1DQwSNvKfEu0Rt8SsV4NIe+DmC+B0Dc/zYEk2+3oOkVBNnrGQd4YcV4Twe+GWC+EkLdAzFc/
+      6Pse1kse5M1OyOsc/zuc5qgs3h7TIq3iPPs7TdRaW/QIrsOO9O1+Tm7NnyDIRc+PJwqyUXsvJwhykXNk
+      B0EuwTkvAZ+XWk+dJTu3bA+3iz/nyxX/3R8kGIlBLDBcfMRPvWkAb0dYX7GqCI1DjPSKwiAx6/7QLLQX
+      1Tx1jyN+ei7RQMSZ8c41w86RnAsGDjHSqxSDRKzUYkHjcCOnenFxx//pkl1MmCxuJmcDjcSt9Mygo5b3
+      z8VqETDK7uJePzFBbNjrpiaLQ1t22jbPGmJ52vZHLbs/arlTks9EMe/ze570+b1jrKNyQ9nlysIsX1an
+      +yi5yEi2E4S4KKsYOCDmJA7baBxopGccjQONR84JHsGzUxtFcG5JyyFGcrmhg4gzu0hYSskhRmoJoXGQ
+      kXfR2BWzLhe5VrV8B+s56UDMyXlOWg4yFvIvvMs+kaCVc5ORO3yIie3ZnoJsahlnuk1RmC3a1j95RkVC
+      1mPBu+aWg4y0dVFtzjLuN91qlOT3ZQaJWQu+tgC8baUo0/tvWjmhcZZRtr33WZ09p/TCx0RRL/XxMUjb
+      eqyjtKSNn3cMYGK0TAbM8tXx4wX1s5qOAUxi+tbJOmOb0v0hb1ZrpN5ag8Ss1Burg5rzYf1F/n79LVrc
+      frqLuk90SWeMGsaiEO4Xwo9FoKQRJoBi/DH/trhmptLA4mZOypxI3MpKjR4dvB9nq8VVdHV3K7tas8Xt
+      mpZfYNpnn54aEOszE1IEhDX34i6KD4dmk6wsTykbBgCo6e33g9rWVU6xGqDlzNO4inZ5PH0LUQuDfO2S
+      rkyrBltutVRNsyVy8xOS2UQtLzU53VSUf2m6y812OsTlcFEBEqPdy/vxGFdxUacpK4zlACIRt962OdOY
+      lKe9JCm+gTJtabmjaOTPTV6t6UN6jW5AlisnrFPTA5ajot1Fq5zs/hLFeU61KMY0NTOZCBOtdMY1TV/I
+      fyAAy4FsObiWrMhqqkcxrmmvBmEYaXTiYONhemPTwlyfWp9H5tfpU6Ic0HUyy3QLxbyy3BPTF/qGWNdM
+      3QPC5hwj9cKtq31KfybHPSkzd4jpUTeoIOXllrAtNbnmOzGmSWXDZnuxgpZCOmcb6ydysdhDgIvSwNMY
+      wNQsAUb6HAlAMS/xdhgg4kxkQ6IqX1najkXM1AfCABGn7NjznApEnBVhW0QHRJyk7QBc0rWW9BaJhpk+
+      YmZ38rmqBDZZGR3irCKKes41MhqAGub6aG2LlgAshB04dAYwHcieg2tRZeLmuKOqOsz1iXL7PSUnekvZ
+      tp9Ez0/bcNxv0or8PGoY6FNPlKxDGMqONK2Mjg/Y5zmUpAwhf27xajoGKSO0hGWpK3K1cmIsE7Gjc3D6
+      OdTC3S3TqVnHzTPtfreiOKdqGghwcUZ5DNB2Ctrj2gCW44V3Vi/IOQlO2S3gklsQy23hlNqCXGYLoMRW
+      e6rsaRIJ2A566SrAsrVpw+WEPboNCHDJpG92HKXmAQdG3KojcCCsdAvCiJvthZ3UnroARzMEeTRDAKMZ
+      zd+oPegeAlwHsujgWqgjIwIcGRHdgASx9aJhsC8td6qff6wKjnagXXtBmEqhM66pH4cg55CBxKzikG6z
+      OOeJOxhzk7sxFup6OWMuAh1z6TtM3U5YpFfuqMCK8VQe8ySS/RZOStsw6CZnjAFDfMTXHzoHGukZQeNs
+      Y3sn5TGasMcsX0FvCZ8Y01SnglH8DpRpO6rttUln1RKm5Zk6yvXsjnA9c5LoGU6jF0b35wXs/5CzFJCX
+      2keX+GKjhyAXp2Fskpr1Nvp4s7i9br/XL55TQrvFRWEvKXtYHGzMiuc4zxLKACZIo3ZmMmSeVKCMaJmY
+      4bta/xWl0zcCGQjHQrwtJ8TxED4DGwjHQkuejnAsoo4r6tk0jGH6PL+9+tjMOCCoBghwCVIa9Yxh+np3
+      u25OmDIR0OZgIzErGBxspN1OHUN9qpARNeVTS1SAx9iVVbQvk2N+FNwomgKOQ8sMOob6olz1yBOmtqMN
+      e7wRUSail7KiWDXKtCUkS+LQ5BPpENMjthebgmJpAMOxyQqaowVMh/xLRnI0AOAgbiFgc4DxENNth9gx
+      bTcb1rkNnG1M0i1NJQHb8USYTXACbEeesi6sx2zf/pDRTBIwHM2MM4Ki+b1roCzlrzOAiVidDJDpIkwz
+      uDW/eG//TS0zTojpoVW2Th27LY+FKmBfor/TqlQJJkg6hzbsMo/TSqMWMB3ZM0WQPds0NZ1PiOk5Uu62
+      8f2Y/HdaPMXFNk2ifZbn6kVb3BRyVbaXLf36tekAE/RTdGb8H8c4ZzVQLNK0/qSkify1QROfQuf521Xl
+      XjZkivqx3KfVK0llkIb1cUvJKvLXJn36PlTdizQiFecOa5nrqNpt33+4+LX7wfmH97+S9JDAiXGcvjDz
+      QDgW4hN3QgyPrNtoZUcLGA7SsPutPeJ+q9qKskwjtogHyHYV6WOsvvehyU6UbStJjdYWcBwF8WQkYDsO
+      5csFTaIIx0J/YjQKtu1iWWqpsUWeVsNtPzGDQ30O+TdVadIsijAseUp7SJrfmwbSro09ADjOyZJzw7KP
+      K/EkaxvS3AETs3ziO7VF0zOmqUyIfcSOgCzRj2M2/TtRm3OMtFq4IyDLRVMn0l0tBxmZQr+P1YyBBXgM
+      4vPtsI65GXoV1FPuKMwWbXI17TjhWU80ai8TrrkEcj65nBkgxHXOkp1jNtZzabCIOUCMePfHnKiTBGTh
+      NaBd2HETGwUnxPGIHxVRIwnIUtM1br4Txw1Vc9xAFlaW6DnHyCiu3FLqkNGaEi1gOmj50s6TMktRr6RD
+      DA9tcN8e0y8KmTwUXv3eNVCfgAEyXcc9tQlzQkAPNYENzjW+yvYx1aYYw0TrhNg9kEOsahzV+IuOhVqf
+      g1QfArRp547ReEZjSOvHnX7vGihT0wbE9Ij0mJRRFZPe2GoUZlP/5zHlOVvWMBNP0Dkz1il5zqX9M61b
+      aXCmkdoyqtxWUUVuEVVAa4i4Ze5AOBbGUIeOOT7auJQAxqUEfVxKQONStBaJ3RohtkScVgitBWK3PlQL
+      gpoGHWJ46jKytnElGF0YdHf7sjHEHWlbWU1dgzOMR9qAwNEeDTjSXiAd7TdIR1pWONp54TnOjymx7u0Z
+      w0QcxrLGsPqf7I7Fts7KInoilEAgDdlFmu9odbiLat6HT9HX+dduMZHJSoNybaRXIhrjmh6r8oVqUgxs
+      avcK4vha0rVSmugD4nrUpznVMznROsz07dM95S1fT5gWUVdES0s4lnwb10SNQgAP4Q3xgDiegn5ZBXRd
+      RZ4WVE+uf0F49fFjMxxKGSbWGdgUbcoy5+gaEHGSNjp1ScRabmvyys6oAIuRJe170prwTSpuQKIc+Ql0
+      RFKI1CU1INclDvE2pboayHUdz3+lmiQCek47Sh0qeejn9O6uRwHGyVOGOYeu/YJ8jyUCeoKv3VUAcd5f
+      kL3vL0APIw0VBLjoz8kRej7kHxnnpCDAdUkWXUKW4Jt66b+nxL0SNcT0UL5zPP3eMmTED4EMyHaJbVwl
+      0fYpyxOaTwNNp/yPbPo36AMBWSjrE5uUZaOs/9UDgKOtOFSnfvrqZiBsuimTTE6/dw0ROecPlGkjtK+6
+      n5s8sU2tIaaH0i08/V43rLrmVVqpXniSVtNlDgp5s7pbf/gpFpRRL9wARFGtIHkKtFaUy5pmtaJTnBWi
+      m3X5SilOINq2H16pzSidMm20MnPllJmrZnZYXLwS2/smhxujNE/3hLW+MB6OoHJgaBTbAUTipAycKvSe
+      kAUiTu71j153lO0PebbN6B0i3IFFonVWbBKxHvnaI+IlP7w95LryWNSkhp6Bub7yoEbpiLO8QHjEzcrG
+      rmEsCq8zPmYai8rLNJDDjUTqqfYI6OE37FEFGCdPGeY8BVwX5ES1eqr9H4Ov3d9T7X5E6an2COhhpKHd
+      U11Rp5BrCOhhnJPdU+3+TC7AoLIrpKeKGcwotL7EyulLrNQk4ebzcauJSpLCCjMOqZexsnsZq3blGPVx
+      CcXSQ6brkKbf25OtY9KVGqDpFN+zA0Wlfm8Z6unvYE6/tw2UdwkDoVnmy/Xi0+Jqtp7f390srhZz2g4C
+      GO+PQMjDIO23E94dIbjm/zq7In+0bkCAi5TAOgS4KBerMZbpU1YQHrSesCwLSuF0AizHkrL43kBYlocD
+      ZXENDdE8d7efoj9nNw+kHUJNyrI1X9Wngnb/bRBx5mW3niFL3NOWvZ39lmfT34pbmOZb3kTXi9U6ur8j
+      71MCsbiZkAkdErdSMoGL6t5v9+u76OPDp0/zpfzF3Q0xKUDc6yedOkRj9jjPp29BBaCYlzQm5JCYlZ/M
+      vhRuRlll1cozn2jMTmlF2SDmZGcHT05oFg5RL3PZKaEbsCi09b4g1jF/fVjP/yK/AAJYxExqsNsg4lTL
+      nZAWtINpn532DgrGEf+xCDt/jfdH4F+DLnBiyIbiN1nDU1+FQTDqZuQaHUW9x6aRE23U5QlmAMPhRFqt
+      Z+vFVWBGhSUTYnFuOWLxR+NnYkwzKV7w9Xlz9vrLcj67XlxH22NVUQbjYRz3N8sFdxuicYPoDn+k4rhP
+      q2wbEqhT+OMcyqyoCW8hcYUTZ7vZnl9cqtVPqtcD9b6YMOZOiwB3B7vu3UYdPufaLRzzX4b5R88/yI66
+      n2L5v+jiHVV74lxj2xJRbetmS3F6KxowuFHqKiBNDHjErf5JGL/GFU6cXVl9lw9ErbYCzh6LskqjfZw8
+      Ry/ZIS2L5qhaBk/N6aaMjXLk7rmpTeF4t09HHe/jdq8SJibXWAOIOXnlkgmPuFl5AVJgcXj52YRH3CHX
+      4M/P3Y9YTVKDxcxNP/V7+spzn2jMLqu+6Yt4ASjmpYz226DrVJsSvLbtp3YLMW4bxmPyRu32AnuLsLbK
+      G7c90fCghgeMyCv2NBKzkndjRHDQ3xTp3fJcWVkwQlgGMEqTepR1syEWNatZagG32FaAceqnZtcd+VvC
+      ywYYd/1PsZobSu83D6DjVLP2YrEnCjvKtbUNN3J7r+ccY1OsildB+foZQF1vs3HQLlMbVmZxHm2OlAnE
+      HocTKc82VVy9cu6bjjrefTO8zNFqpGtN94RvMg3IcakShVfaaaRrPe4jzthOzznGMqQHVPp7QGWxpRZm
+      CnE8hzJ/PX//7gOv/WPRuJ2RmwwWNx9prytB2rXLfoeQj/em/Mk6dQt3/FXCKHdaCHGp1Vrq7JCnl5Qd
+      jDwKN066a5eklV2CSP28Wb6PNBF9TITHzIotN4pEHa8aL1Ift4S0zkAHGOltWr6C0PIVb9fyFZSWr3ij
+      lq+Y3PIV7Jav8LR8my3CkpCz12jQHthuFFPajSKs3SjG2o285hPWcur+HmW7KH6Oszze5ClPbSicOHUu
+      zmUJTS0jT5jmWy+j6+XHz7RV2E0KsJ3WKiYLTyDgJNVhOgS41PdIhMmZJqb5nuIr1TInDuwY1GC7nq9O
+      Q1Xvp7p0xjSl2817arPN5hwjU4j4kvRCvUBgSS3WMb8PML/3mAv6/Tkxpqlgnl+Bnpsq6whDdBoCeqJj
+      sX1KKduygLDrLmWD4xBXWU0+1YHUrF+iJtJkV/d71xAdjhtSAlqcaSz3h6Ns3hB9A2XYKFOXup8bfL92
+      PO10dAz2ybsR79M6rQRhsTNUYMWo30WPJKcCXAf1mlvE9RyolgPg+EG+IokAnip75lzYiQOM5MyvY67v
+      B9X0w3ZQ28QmBdnIo8AAanhPS4sPuZhgdmHDTZim1/7apInrgmqI4Wmn8rKuz0YNr6A/mQJ6MgX9qRLQ
+      UyVY+U0g+a3p2jTf8RBlLWS6CPvtdj83eNqkyR7QHc09FJQ9bnRGMy2W86v13fLbar2k7qwJsbh5elfB
+      JXEr5ZF0Ud27ur+ZfVvP/1oT08DkYCPl2nUKtpGu2cAMXzcZPrqdfZ1Tr9lhcTPp2i0St9LSwEZBLzMJ
+      0KtnXThyzbzLxa60GQc7UF5cgrDmXs2i1YJYemiMa+pqYqqsw1wfJQEHxPU0NSjV1ECmq+2mqNWr4/pY
+      kYwWanqTMkTt0o5dHSEqFeJ4ntMq270STS1kuWTleP2FJGoI00LNuW6uZXXoLA4x8rp0qMGOQurU9QRg
+      IV+503o8/fVA9hwgyw/6dZmt0P6v1M6dDUJOYvfO4gDjD7Lrh2MhN7lNDPTRO3kAa5oDunkgjdjl3WM8
+      0gCO+I+bPNuy9T1t2ol1nVPPsTuYAAuaeanqwKCblaI2a5oFo2wTYNkmGKWSAEslwXtSBfakUqt1t04n
+      dYq735sGYre4J0wLvWEBtCoY3WsdGlzzK97Is83hxmiXHQRX28CGm9GSNynYVhJ3noFYyKxqMbpTUZgt
+      qni+qEKNgmkEr5jYM3JA2PmT8l2zA0JOQi1kQJCL1OuyMMgnWLlGILmmLrl5+0TaVmI/y4AAF61ItDDb
+      Rz8x6KwotcVA2BbOhblXFX3+1O0DKdssT9N3EnNJx1pkoj5cXPzCM1s0Yv/wa4i9p0H730H2vzH78u7h
+      PiJM3NUZwESopnUGMNGqPQ0CXG03ue2BlxXZauKYv6wIq+wCKOyVTYRdvGWedQ9j7mP1nKo8wpOfaK+d
+      MraJ4Ig/SR85eWRAES/7RqL3sX3wCAtnuyRgVf3xzWtIMjsGJAo/nxg0YG9SjPQuFkABrzit8rrLp3/m
+      BtOInV+cGDRib751Vx+JqC2B1cZMu7LasyKBJiPqH/Nv3Vgzrf9igYiT1NMyOccob3gms1LTDxHptpq+
+      GBoqcGOQarCOcCzE2uuEOB7OUDaAer2c2+7wQARVaVYlOTkHEHYyxqwQHPGTx61gGrI3zyH1WXZY0JwW
+      26a4Egxzz8Jm2uCWS2JW8mA0gjv+TETlIf5xpD6CPecY5f28IHx2Y1KO7TRszKq6YQEag/+4eMfOu9+Q
+      hhZOBGRht2RAHoxA7jyZoONsh6rZJ23jiJ8++I/gmJ+dPzxvAbpfcFthDguauWWp8JalIqAsFd6yVLDL
+      UuEpS5vWJKOa7TnQyM8VFg3buVWsCY+4o3inDsp7LbsKWRGTxgWn+ZwzoL04MSDD9XW+/nJ33S5/kKV5
+      EtWvB0oBA/JGhHYKEWEbXp0BTM3XTtR2r41CXtLYVM9AJsIq1QYEuJJNTlZJBjId6ddn9zjos+YMCHA1
+      u6Q42Z04BDCmAuJmqptak2O0GOQTUay+EFafr9f0u2/isF92qZtKnCM/sYB5f6TnMMkAJlobDZiv2P+1
+      3NYXzXgC2deTgLX5+8V2syFbexK1yrhMqyQBq3i750JQnou2zbI/VKkQafImsXEdEr8u+Q+SxRsRuiZw
+      llwUhLXUHRB0iloeSxjOFjSczT5Pxyyvs+6ppTQnXFhzX198+HD+u2pjHOJs+oCiiaG+03DX9G8VUYEb
+      g/QOUmNcE/ENokHptsX9bLn+Rp5K74CIc/pccgtDfJTS2eI04+3nxS3xegfE8ajM2r6iJfaZYRz0L0Ps
+      S9zd7NZwetLS4lEeEsQIkMKJQ7lvPeFYqvRRFjVqj8I8b0rkPK2ptxB0OJFE2D0VY/dUhNxTgd3T5TJa
+      zf6cN+s0E/O3i5petbRLWlVlReuRO6TPuuNrd6a37SM1hylODYN84lVmnD1Xq9Omvb0M2uZZNocbo4Lr
+      jArT2qwJ2x4SFKfOWcZjsWVfvgOb7mbcm3qreghxRbn6E0fYkD4r+cECcNdfpD+HXzXL3FFDuAYzivwj
+      +xbarGVWNcvHxR0nz9ksYFb/wTVrLGBezm6v2WodBtzNah0l227ipr/Zoo78yAwUZiM/NBbq9ZIfG4gH
+      IjS7yvISY0C9Xl6yWPx4BF4CQRIrVnlQndR9XH0n2QfM8lVq6kUTkpStdQ43RtsNVypRj3d3YHt3B8t7
+      5OS4I5jXqjQWZcEumAHc9u/LZ1WrE5bmsjnQ2C2xxhXruO0XtVpAn2HWQNMpYk4aDJRlk7Ut9XE6MZrp
+      z/toNp9dN/szxoRdZRwQcRJ3uIJYxEzqsdgg4lRNmOkrwgMo4qWsIeeAHmf0ktVPUZJV6ZayAviYB4lI
+      6ZdbHGIsDynvpBXocUaPcf1EmGmK8EgEkRK+TLFBjzMS27iumaetC5AYdfxI+gAGYBEzZSVbBwSc6pUw
+      bR0bAAW86kseWfBXT5ySTocRNzeFNRYwF2r1aW566LDp/qg+ylmXfxCmChiUabta3H+ZL5ub2mzRRvv4
+      BROgMbbZgfiAOzDuptdZLo3bKe/KXRT31lXO9UoU9XZrPlLahJgAjUGbEQSwuJnYSrBQ1Nu8ej8caP0l
+      XIHGobYcLBT3PjMKFIhHI/DKcFCAxtiXCffuKhT1Els6Jolbs4RrzRLUWlF2LodY1CzC87iYksfVj0JK
+      gJ73RgjOj6bEG+sQJwm/wNQMYJSg+nWkbuXeBzz9Q0oafykTdEdH7iSzZEFLFd6z7z739GYP1NZp/vYp
+      K+KcsNaSS0LWBbXC6inMxjrFDoScD6RdT2zONF6nW3nHP8Yi/fUXilHnQKN6ShlChUG+5o7RfQ0G+ah3
+      eaAgG/2O6BxkTG7I5YIBOk7VguU8MBYKehmJecJQH+80waemO8a6SQNoObPHVNAuuiEgCz1vDxjq++vu
+      E1MpSdRKvSsGCVnJWaenMBvrFOF80xxaUWaxGRRmY97vHsW8vLQ8kZiV8dhYLGTmWnHjn7Q5ghaHG5l3
+      S4NxN++ODSxu5qavTpv2ecGq1zUM8pFTV8MgHzVFBwqy0VNR5yAjo143QMfJrdctFPQyEhOu17UDvNME
+      y+fuGOsmYfX61+uAEWAHBt2M0dmvnveJp2PEUVkNQ33Ee2WSsLXZu44jbUDQ2W1Mx5B2JGiljrt+xd7N
+      fuW9Qf2KvT/tDuwThm2fgC7iaOFX5K1o93fyeJ7OgUbmc4g+gaQPJk3M8bFLCk8pQR7DOjGOSU2abr/0
+      ZChN2HEzrhm8WsbdcO/E/cd5JEh7gpmUZfvjanV5cf/H/BvJ1lO2bf7tojlIs50o18Z6X2aAiDOh1Us6
+      hxip5agBIs52NZXvtPe+Lu2zVyKOyjg9RHm8SXN+HNODR2x+uH/cnRMLdswxEqk5pcBInWMkEuNNAuYY
+      iyREJOK8Js5f8Hk8Efu9F0KSUZcgsYh1s87hxihLuNIow85UvNFzIyY/N83aF9t2HRP1lp4bzpBMiPWY
+      FsMHpsFBDZsnukoSWWqpn5MWxRvxTIt4OG7Sn4e3iNmaRqKGlIRiUkko3qAkFJNKQvEGJaGYVBIKrQTr
+      UjvwygwTIeob3D5XNz1+SDWA6ybEf6vA4xGD6x8xXv/EQhAHvzUM9UXXqxnTqVDc2y6Zw1W3NG5f8s96
+      CZ71JhYppyLuOMjIqRaQOoCyto7GwCbOSmUwDvnVeFNIAJMHInQbhZPNHYcbyaNCDgy61UKmDKvCUB/3
+      VHsWNzfThVLarBCIByIQ9wm3OdzISw4dBtysvjLST256n9N3XLM51MgoBU8g5mSW2xqLmZfcs11iZ3vO
+      TNNzNE3PuWl6jqfpeUCannvT9Jybpue+NK1zoZ4N9ZqLtoaU1wJHi6r4hbWGocfhi0RfzxBXAHEYDQiw
+      7UBfF9chAWvbgCYrWwz18QpfjQXM+0y21YrHkIaEqwDicMZz4LEcNRgTmpcBhy8SPy+7CiDOaTiEbD+B
+      Hicvzxg0ZG++cG63FKPLNRh3t3eGK29p3N7cDq68gQG34NZqAq/VRECtJry1muDWagKv1cSb1GpiYq3W
+      rKBHfItmgJCT0/NH+v1NJ5j1/PUkaP2bccXOG8jmz6zUQ1KOuM6viQG+Z/LENg1Dfbz7obG4uUq36jNT
+      rrzDR/1BV6A7zEisGZrI3EzOrEx4Pubpr8QpORrm+ugTp7A5ncyZkugcSd7sSGxe5PB3YuoZIOSkpyA+
+      v1It8dZ+1xvFeRaTmhM265oT8nz1gbJsasWROBXR+cVltN1sI/EUN7UUSY5JJsaKsv1Btj0y6moXk4Tj
+      56B2zHuDK+40vnjbfbTJj2ldlrRJo7hlarTo8m3iRZe+iHUVPe3jU2rwI5oeT8TH7Z4dRbJ+s2xePIfY
+      FT8SQeaX84ugGI1hQpT3wVHeY1F+v+Dfh5ZFzOqJCi6TbMnEWMFlkk84fg4hZZKrGY/3/vKXt4jXaXzx
+      3qCMADyeiNy82bF+M7uM0PiRCPwywjBMiPI+OApURmyfYvm/i3fRocxfz9+/+0CO4hiAKIk8kzRJ34cV
+      GKBlarSgImPUCJxFccxz/rUaNGD/GX7jfo7eub4FRXP3GOKrK5avrmBfSliB0cRgH7lIQlss7YFyxzo/
+      iQE+WSVz7keLIT7G/Wgx2Me5Hy0G+zj3A265tAc496PFXF9Xu1J9HYb46Pejw2Af4350GOxj3A+ktm4P
+      MO5Hh5k+xsde4FdeqrAn3tMOcT3EtO8QwENbYaRDQM97hug9bOIk04lDjJwE6zjQyDxF9wzVhoKqUqbI
+      ToxpajaRbUaQNq+kDSsB1mOmva22UNfbjk/xzlhnPWb6GWso7i03/+J6JWp6n2LRFEBPcZW8xBUpJWzW
+      NJ+2eW1DR3H+WFZZ/UQqajEHHIn5Mtu/H63+A9YrbJe27Alp8Rz5c5v/QOM/OHzTLidKGsY0tRu3htxv
+      2ABFYd5r396yw2HWfbZZ01xtL6Jf3lEL74FybQwV4PmF5rDyHjXfuHlGjadc/EJ0SMK10EZ3oHGcdkSJ
+      aJGEY/lAG0FpCcgS0a+qo0yb6tyrnn4zXXkfkzKOzcLm7plVr0arhKM3BHCM9tjpl+J4OJRVnbKiISos
+      brNgPuMbHNigRflrPb+9nl832/U+rGafiXtRwbjXT3gtCsFeN2V+GkgP9k+L+xVpHcIeABwRYVEBAxpc
+      n+e38+XsJlJ75K1IN8klMev0W2NzmJFwQxwQdlK+7bA5xEj4btzmECP39njuTju1u1QL498SOgwehS/O
+      c5wfA2I0OOLnZTI0j3GzmCeHNRMEWc6GRKyiT/yCe/9MhS8O//4Jz/1bPXxcL+e87K2zuJmeOQYStzKy
+      iIYO3i9/XE9el1D91iSj9OchLhKKoEMcT13F0/d/1hnN9HV2Ndkgf2uSnLWgbA4yEtaBMiDERZgyZXOA
+      kZLtDQhwUab/GRDgImRvnQFMpNWPTMqykabTDYRlWVBTaeGmEHHqnM5YJtqEOQ2xPJS5vz2gOZarlfqM
+      Mp7+5PWEZUkLqqUhLMtjWqQVcSzEAS0nf8gLwS0/d6AFhG13mb++lw/rc1rVNK8Ggs79MWcIJTXYFqvV
+      g/xpdL1Yrbs97CnlGoJ7/dOfYRD2ugllH0wP9q/Xk4de5E8Njlbc9YDpoBR2p9+bhnUVF2JXVnuKpodM
+      F62wGwjd8mE6/sHgqOn5wU3PD8T0/OCk5wdOen6A0/MDOT0/uOk5X3+5u6Z8njEQjuVY0D0NM5ia7sLV
+      3e1qvZzJh2kVbZ/S6cvrwrTHTimlQNjjnp5RANTjJZROEKuZ5ZFPtCToCdvSrN1F27LQAUEnaetSm7ON
+      agtkmksRkCXaZCXdpCjbRrmdJ0BzzNerq9n9PFrd/yEbdaSb6aKol5CXbRB1Ui7cIWHrItr8+otqlBKG
+      WDHeF6H9+pAfoeWxCNybuPDcw0XzVMjWJaFZivFYBF4mWaB5ZMHNIgtfDhGB6SBG04HyoahLYlbaR48Q
+      q5nv1ourufwpLa8ZFGQj5ACNgUyUO69Dg+vu439H2424IMxX0RDLQxuU0hDLs6c59jZPWix8IExLQruS
+      xL4K+R+JyqpZomYzCIrLQlHv5jVE3dGmvXmHQNn3zoBMF22LsoGwLAU1c7aEaZF/uNhuNhRNh7ievKBq
+      8sK1EGZyaYjrEeSzEdbZSC01iTvE9dQ/a6pHIqZHkO+4AO641FI1HeJ6iPeqQzTP/fxW/Uh9Gxvn+TC9
+      SUTbspjcGRzRuPE2xyxXq4a168QKahwLd/1N8S1SqrfDEB+h3DUx2FeRam+XBKwyrbNHsrGhANvhKAtj
+      2V5iXPeAul7OVcPX+7ivsz3Z1VKYTebhf/GMikStSbbbMbUKdb1PsXh6f0FVtpRry+L3F9v4EN1ThT0I
+      ONULk2Z5wJJsHVDX2/bEVQkgC4B9mRxzegECOdxIe1mWlVuqu6UwG+ktH4AC3nSf0B/RlnJtRcksRnrQ
+      dcpGLCchO8z1ibraxiKlNMcdErQy0rGlQFu+jWuGTmGIb/qbcAsDfQU/EQtfKha8ZCywdCwIC1BbmOur
+      y7x8mb6Wj4VpvvWX+ZI6+cyAIBepbjQoyEYoaDQGMhH68wakuQ5pATcRJ4tRAx6l/diGHaLDcX87V5ft
+      73DX/yyjEsbiLQz1RcVxz3QqdPDez79Gs9XtuSqjJ/dkDAhxUQbmHRBwvsgckpKFDYXZWKfYk6b1rw/v
+      fo8Wt5/uyAlpkj4r9XxdGrOzkgPATf/mtU4F68xN0rTK/4y28pnbxNPfR9qcbfwuW2S7kmZrGctURk/y
+      pKfXSgZkutQ4v7ZfvUpoihXATf+hkg1RyuqCBmS6qHnezenNvb7+Qluv1AEh52p2336Q9cf0Nw0wDduj
+      +4ePhKU/ART2cpPiRALW+VVAUugw6OYmRE8CVrXL3G9kY0MhtkuW7RKzyZ8v/mw+M6E+oJgDisRLWDxV
+      +bnAmweWQc/acuRZU8ebWXlc+QmG3dxUXvqeY1VHko0KQlzR7OEvlk+BmPNqecNzShBzLuf/5DklCDiJ
+      7Qe45XD6K7+e0WHMHfQMOAY8Cje/mjjuD0kiTx2kjgfVQ7YAjRGSQL46SR3n1Us96bFesq2XPmtgPYV4
+      sIj8hPeneliuGc0zy+Bndznh2Q2qx2wBHiPkLizHygdWvXYCPU5W/abDPjenntNhn5tT3+mw6SYPdgDj
+      HG2nnFPVmSRo5T4oAI74GdnXZhEzO0HgWq09yK3SXBq2s5MDqcnag+RqTMMw3yXPd4n6QhLWEkyIQdk4
+      1ytBY/GrYlQCxmJmGE9uCbkR3nuwDCtPlmPlCbfKdWnEzk7tpbe0olazA4XZqBWsSaJWYtVqkqiVWKma
+      pM8a3c7/h29WNGQndlKRUfP+zwF1N95P1Y6HPXMjPVXjR+ynw9dXNX4RlFC+ej2kuwob8ChByeSt51ld
+      Vgv1eS/53kuvNzThJ9T/wM94bQBE5I0Z2haY1C/XfhqQwUZyV+iNGr1Hy/DyajmlvAprK/j758Zvgu7G
+      crRU5LUd4D66eYzXhsB76dZxVlsC76dbx1ltipGeunGc17awDVoU+XifX0T3H+dqtslks0E5NtoHLAbk
+      uChTnTTE8ag31t9lmRkXSbRNq+mTcTDeidAs7UC0Noxj6vZqIyx26ICm84O8VX9cf7qIKEv3OKDHGa2+
+      zM7Z4oa27YdNesHaLx7BQT9nV3MEN/2/RZtjkeSpKjFIWc0AEafKf9ku28rnhefWBXYM6gP3G/C8/dY8
+      LvRLP1GQTZVmPOOJxKz85IQMUJSwCGN2tb9wWATbYEehfOs6ELZFzexRu2ZTPs9zSdRK2ukPYjFz95Sn
+      CU/e47j/Oc3LA9/f4Zhf3QuuvGX95lmRzMMuwfWYEa0OCLmMgnh/BFp14NJ+O2GeNILb/q6mo1k7yHZ1
+      GZbm6iDbdVpNq38IOKufT1DZcdt1tt4gqkfkxFTtQ/UtMTHCCQN9gucTlq9fqfh+vlzcXROfIIj22SlP
+      j8v6zKQnB4A199eP67s/5rfq9+1/kNIEpDX73c3i6hu9sDIx0EdIXB0CXZTkNCjb9s+H2Q3zag0U9VKv
+      WgNRJ/nqddK2slecQnCvn5oa6LpTwGFyquBrT3XHv87u7xVJP22NxKyctNZR1Ms9Wd+50tNWIzXr8u4v
+      mezz5bptEDQr0q8Wd8QyzGuZEo2QRB7HlEiUhPNJ7FhdKtOTTQMRJzVxegzxkZNg4AbjcnZ7HcmfpvHk
+      dpCGWB7CiOHp95ah+RSH5GgIyBK9ZPWTCpGpVebUxkuEbuaIxopHXOZBZyxT+khLQfl721DEmzyNdmX1
+      PToWIt6l0ea426WUBfVGRVbMXSZ/SFmK3qQsWzsAUSTRPq2fSlp6WKxlbj7fV2FJzp6ybIdy+oZzPWA7
+      RHpMSka210HLKdKUlmgKcBz8eyC890DUcX2kXWuLaJ6ryavryp8aXHNyhD6fhmge/cUeZV0tBzSdp7d4
+      VKXOGcb/jc7fXfyiFqpQq/9H8fPPC4IXoA17dL9aRfez5ewrrX0LoKh3ep3pgKiTUG+6pGlVH2Qfvm/F
+      eXSo5F9/Urw2a5o32fQ3UqffW4Y8K9QOTdH078EtzPQ1i+rKcvBAOq+BgmyUJ1GHTBdxrEtDbM8uPuY1
+      tcxzSNNKHD3TENOzy+NHUtI3gOUgPqbus6mvs0/YCgFAPV5qJnNg212/i7ZVHdHmbQEo4E3IugSy7A/n
+      dJGEQNcPjusH5ErJohSw7OJtXVb0hO84wJj92B/IOgUBLmIhdGIAU0H2FICFfmHQVf0gW344FvmU0npN
+      Jgb6ZB0ayRqGWnSYrGnORFQe4h9HUmbtIdMVsP8ugiN+8nYhMG3aiU0bpz2jEphe+w2Uaeu2iGxaOs2E
+      lOhuNr+P9o87Uvnk0YzFU2238HAny1i05u1lYKzWMSnSxRtEusAjFWWRciMoFja3Tbg3yA2gaDwm/x65
+      lonRLt4kmnOnmDtHgzDoZpVQ+H5GzVHKdog94Dia02a0+i0U9jLa6xYKe5u2aVXuiYM9qAGPUpdhMerS
+      F6Gm7mQDwpa7zS+cW2qQoJVzQw0StAbcTkiAxmDdTBc3/YLfIxK+HpFgtvYF2toXjBa6AFvogteeFVh7
+      ljIH7vR71xAdhCDXgQYIOKv4hayTjG36O6VZ/rbq/OOBssPUQJgW2g4YAwFZApqFoACMwbmjFgp6iXd1
+      oAYbZVa2OQdb/Yu2ldpAWBbKZmo9YDnI26mZlGWjbaimIYbn4uIXgkL+2qbJ6dszjomYxifE8ZBTZoBM
+      14dfKZIPv9o0PW1OjGOipk2HOB5OHjQ43PgxL7ffBdfb0o6dfi97yHC9v6Tkc/lrmybfy55xTMR7eUIc
+      DzltBshwfTi/IEjkr206oj0pHQFZyKlscKCRmNo6BvrIqW6CjpNzxfDVMq4UvEpOGWFwjpGVZk56Le6/
+      zFZfIkKN1ROa5X72x/yCvJ+5hYE+wkCmSTm2/t3QXjwSlTrqeNXatKlqrpG1GqlZSVOw7NlX7b+py3+b
+      lGb763a+XtDmhOuMayI8TD3hWiiZYkAsTzM+mSXR4nY9/zxfkoQWi5hjsWVZJYcYj3k5ffKWS9pW8n2F
+      7mrzToabjiaLmMnpOHCIkZGOOmlbibnazdPkHG3m5/XyYbWO2q8Nrm4W89v2thNGS3CDN8omfcyKKBPi
+      GBfbNCCYKZoQs0qTdH+g7Dc8QeWNK/+eiae3uFjLNCXqm1yu4/JHJhQOCO71E7I8THvtarROVFXgM6BZ
+      4GiL1ephvgx52kyDNwr3jmi4168yZEiAhvdGYN7zgfbaVcZO9wEBWoE3hsoR+7SO1TBw4C23VaNxA/Kz
+      a4GjtXtf929pTqfHCYmo4Ljpz0NaZfu0qKPnd5xohmA8xnlojHM4BvcRxZ9NfUobx6zzcATmQ2k8jQ+r
+      +bLdiJmUBBYG+qY3rgwIdBEu1aQ02/rTpWoMTm6S9oDlOByJDgUMjr8uPnw4n7zSUvtrm1Z54hBnFc1y
+      ohxb97axeZfZPfZEM2DQonx49/uf79VXW2rRjnZ6CWWTWYwHI6j1kEIiGDwYgfCNlElhtijOs1jwnC2L
+      mvNs+gIaAIp6uak7mrLt0Uh8D5FLHPQTv/JySdCaXGQMo6RAG6UUtjDQJwswhk5SmI2y2KFLgtbsgmOU
+      FGjj5k08X7aZinfdPQuaSdOpbA43RrsDVypR0PvczIktGNqOdKzdDpayxhDpltJDxngngiwQzhmZ64RB
+      PvUpW5HElfqiqk4LNewq6HrIAkaTaXdMGf6Gw43RpixzrraBR9wR+Ql0eE8E+jNjsB7zcfsUV2x3Qzv2
+      pgBgFOs95xiHTMMqQGzc8auyml6rdRRo4z3hGglba8o30Q4IOtnPhwl73PQbZrCOuZ2wy2jpDaDj7FKd
+      k211FPDW0bb+SVY2FGjj1PY95xqbjMG67IE0rdHs5vPdkvIhrElBNsrW0yYF2pIjx5YcYRs18TQM9FHW
+      37Iw0Me5Edh9IIxLmBRoE7wrFdiVNgOVCc8oQdu5Xi8XHx/W82hFenUGwqh7Wx4LrrphcTNpDWMQHnFH
+      m9fodnEdFKJzTIh09/G/gyNJx4RI9c86OJJ0oJHI5Y9OolZ6OWSgqLf92pYwuI7x/gjl5l+yJg2J0Rr8
+      USgbOmM8GoFdRnjKB3KJq5OoVRZ45yH3tOf9EYLuqWawojQrY80e/qJneYPErMTbqHGYkXoTdRBzkntC
+      Fmp7F7efGOl5oiAbNR1bBjKR06+DbNfyhr76rktiVur1DhxmJF+3BgLOr/P1F+LKqRCLmznnO6CAN06S
+      d1GVPpff04Rs1mHYfa7GBqgjZg4Mu9VRjlZxgLH9vFYcszrdkLU6DLmJvauOAUxJmqfqs1LGpQ8o5M12
+      O7pRQqCLssy6hUG+Iz313Hac+ivrwUSeyKa1ItuhalF8slOHPW6RVlmcs+0tjvnzWNS0qeMYj0UoZF4L
+      iTDwWAT1nWJcHytmgB6H/azHrONwI6dT5+J+P7Ur5+J+/7bK6mzLy5q2wxOJ3nd3aI+dOCJts4hZLXtC
+      b/k7NGLvcyz17SFsAKIwGllg+2of19snsqqhABun4QO3eBjN+hOF2YhvRw0QcKrBMt7Ccx4FEqeZqVmR
+      VmrFeCRCQDVj4oif/7yJkeetGdXnV2EmjviJ3+dALGQmLERgQIiL+orFACFnyWgzKQhw0ZYUsDDAR1tc
+      wMIsX7+uOPltjUFi1oBRYsQxIRK1aYE40EjU1r5BolZyyx9b6d462Gy+xWkMwQpvHHIh5+JeP2MwERKg
+      MbiPgO8JoLYLkJX+rWMi/K6KKXdVhN1VMXZXRehdFdhd5Y3yYSN8rLE4ZBzu5u7uj4d7VcqQZ8HaLGqW
+      f3tMK3pLEjSgUbq2FWMQAHGgkcSRnkkcGrZv64p17oqDjZTV+m0OMVLzscbBxqdYyGZlVnGsJxY2U7Yh
+      tTnYSH3uBgz2iadjnZQvBUd6Yi1zMzNzfrteLubklpTFYuZvAY0pTDIlFrU5hUmmxKK+dsckeCxq481E
+      cS/5CbVY3MxqWAG8PwKjEgYNeJSMbfc9E9SywURxr0jZpyvS2usNupti9G6K4LspvHdTLYCwvJ3dsG6o
+      BkPu5uVXUVevdHOPer3swtM2jEZhFZu2YTQKq8C0DVAU6gvBEwS5Tu/1eDdWp0E7/WWexoFGTh2B1A5t
+      OtNfE9gw5ObVOVht007SSiu68UQiVu6N71HM2yyrz36ibcNoFNYTbRuwKDXzvRskGIvBvpAaffvW/ET1
+      C+hiRWG2qMwTnlGRkJVTacF1FavlgbQ5yiLNs4LxMHcg5KR3/gcM9RG2z3FJn5X6hsqGITerDee23mRu
+      n1+135uqL5RqWSbRBm0gARyjKUnVHzj+Hkbd9LmvFgubs+Qnd4wGNMBRqrSusvQ5DQwFaEbi0d8TgwY4
+      SvuWh9FAAHgrQrN3OLmN0FOQjVrmnSDb1W7qent3zSmmHNq2P3zkXfnAwUbih+UahvretUvSM7UdDdsz
+      1slmyLmS73yPwT7BS0uBpaUISkuBp+Xy/m41p66AoXOIkbEyg80iZvLXYzrocdLnYDi0zy7C9MLvb141
+      JFx9S/vtQeffCzwx6HWEQ3vsAYnjTZm6Ogr+WTc0YqcXIT1nGdUKOLz3hQaJWYklscZhRmpprIOAs5nK
+      Htd1RZb2pM/K6ddCgrEY1H4tJBiLQR1wgwRwDObyGgA+6idPzYQVQJz2MwPGFl+4AYjSDQmycqzGQmb6
+      YOKAQT5iDd8xgKlPetbNM2jAzir4kDIvYN67i8P+8yjdx1nOcXco7OVlqRPocXKLQIsficApAC3eF4He
+      AHFxxG/kT8GKYSrG4gTGwPyH44ZT6A0o4uXPqgcNQBRGIwVsn3CaJnCrhD4y0FOYjTp8qYOoc3dgOndQ
+      OS/CnwYx5WkQ/NwqfLm1Wbe3HVejdxghARKDMy/dYiEzdV76CUJc5HnpOgg465I+PKxxgJExm3zAHN+f
+      d3/Mr/nf1UICPAb56zeLRczML1hdHPOT24Q9hxgZrbcBRJxNM0x9Or2N1eJW19QPTDweX8R2Hujtcb9J
+      K3483YJHY99i+AtK6yivyQcpxuPQG36QYjwOa8q5xzMSkdPgBAwjUahfWQI8EiHjnXyGnTG9bdVziFHV
+      hm/wkLsaT7zgR9yWWLFWi8/0EvEEAS7iXWwRwEO9ex1jm9Z3y3mzcxjnDYJDo3Z6Choo6m3KZ/KSBAA/
+      EuEpzoqgEEowEuNYVWqHhS3xAwJcMy1e+8nEW4RsTf6o9JdqkGA0RpMCxMYyahmJVubZ9jWq+Tnc1vjj
+      ibqsgiI1An8MWc2pVyXENXIwiS/WeeizdT7+bJ0H5/HzCXk79ELGr2N4toMKPEPjjZdWVRmQai0/HkF2
+      cg71U2ic1uKP9pM+Wx40jEWRFW07TzMsVK8ZiXeQRUdWd0VIUEjDhEYlf5RloqiX3KbRSdR6OFaHUqi1
+      n59kM4974pYFjdZM/pCVr2DG6Xl/hJB6VIzXo83nvPxS5oT7/QHlpRgtL7UlQQJidIaRKPzSq+e9EULK
+      YTFaDovgklFMKBnVb3Z5/BjwXLS8N0L3lAbE6AzeKHW2DwmhcL+fPMsF4L0R2gHXaLsJiNI70Ehd+0/t
+      1rH9zoxkONBIf6dVyQygUNCrxnWZZeAJxb2sTl5Hota8LL+zuvADDLqZvXe0566trswpDnQc93NryJFe
+      ZtvlkPeWeeYd7HHz2g49i5m5M90hARpDXRszc+s47m/m8wQEOPEjEZruXhIUpFWMxBmGOYNiDRo8Hnt8
+      T6NRe7uoD/eudLTXzu7CmwI0Rlv8hTzZhmI0Dvsp1w1oFMZ7WBsecfPaDo+j7Ya8jFVd1OZmThKZAjAG
+      r5+J9TGb7pSsQTMVMM6DBs9QFxb5nF3PDTDmDinNxVhpLgJLczFamovw0lxMKc3F25TmYmppLoJKczFS
+      mutLaR7i+kkwYxgOTyRe39nfbw7pa/r7mSKorhMjdZ0IrevEeF0nwus6MaWuE8F1nZhQ14X1+cf6+yF9
+      cX8/XITU0cJfR4f278f79ow1SHXQcrZ7q1O/iesp0MYpHw0StJK/hRsw1Eef1mixmJnxjZrFomb6TBqL
+      Rc30UttiUTP9ObZY0Ez9aqynMBtrzNqhLfufM8ZeECcIcBFfovwJrdCk/khth3eMbZovF5++Rfez5exr
+      u0cL40UYJhmNVccb4vqMiGMk0nn0VBIzMKzwxVGFX8V4CDGJLxY9Q9q0z04uqh16zE4vuGHFaJxDmlZv
+      EOukGYnHKNxhxVgcetMfVozFCczNWM1i/IjzahkS+GIwBvcB3heBXBxbsM+tRhv4ckWP2Rkf8SGO0Uhh
+      JXGvGI2THQKjZIcJMaJYbIPjKMlorLBSrFeMxmmq7iwVgbFOmpF4oSWZmFKSifCSTEwpydSPVN58g1i9
+      ZiwepwOPScZikV/dg4bRKOTOBqzwxWkajayOLq6x4rG/vPJ8cdUcqtLmgzzGwrIuDvmbxGPrddq1k7/z
+      gb8Pa1bcpzdTBwz0kavZAbN8zewq/i6RLg76GSNJOug4Vbj4O3HYY8BA3zZm2LYx6KK3UTQONJLbIgMG
+      +ohtjhOEuMhtCx2EnfR3OZ43OGErjIytLtIdZ1RvBgla6VWMxtlG4vLM7srM8i/9tHJyFWvDgJvlBFzM
+      r3HRr3AZK7yAq7tQv+J1v95tSgj6oMqAWT75X4m2o0os/8XYmQW1INE4E5Qs1jZTUwRIi2b8hLnYh8VC
+      5qKsZ7ua+MLPIBHrx3RH/VbIRCFvu1ZDtMlqUTNO2cAhP2+tH+86P83BeiPUD+L8kS4eWNfMGXhAVw5q
+      DpRbcaDrFOXa+vfwzWSMuEpjqtk1jEWhbgQECSbEiNLiOTiOkozFIu/ABBqmRAm/pJPFE+3UXgm5TZoD
+      iMT5mgD/uirom6qRL6k46zbA6zUErNPgXZ8hYF0G73oMoeswjK+/wF93wbfeAnedBXx9hX4priRNVCM+
+      Oor4MeXILQUWp1lIiT7ABvBABO4Ox4/e3Y3VUX7S+FKEsWoUur7ZY8h6EI/+dSDC1k0bWzPtMWSdq0f/
+      Glfy8J7dxtx72ph7fhtzj7cx96rbFsXJv2jOHrN8Ts+D3NsFDaNRyNuXwAo4jrrL3Os4sR4z99x7eMRN
+      3ogFEtgxaFWM865VliZZQh+PHTDQRx6PHTDL10xrP82opjdJXRz1B7hRL/+U4bOlvqp2306r7pJMafqy
+      kDpoOQ9xJdJoV5X7aHPc7YilrUPb9naFkGYYjybWQNiZp89pfur7JynHbil8cdRxRqsQccCRmuPaOi6c
+      SLZjNBJ92hniGIv04xjn2S5LKxEWbfDAEdVqNPQRNBv2uJuzaO4oO8KgGIvDmhaAWsaiHWUt/kYhDZUn
+      bvtosJ8s22FHIheVYBnJWTkXWTWXu90XvtMXaw1eZP3dbqST8YrAIC1r9+67mWRJkuqg5eSuAIGv+yAC
+      eqLC2xNVR1mdGR2EnYyujEECVkbvFl0POWi1w5FVDoPWWR5ZY5m7vjK+tjJ5XWVgTWXWesrIWspDzz45
+      EjtlJop66WWvxdpm7XaRO5I27HOTu5IOPWYndyZBgxPlcCgrte5IP+JGjOHwVgTWKAcyxnH6M7Va1Tjb
+      2K7wrRbnphkHzjY2k6ro1ZbGWUbG3CFw1hDjOzzw67vTN3PUJWM0Djd2a9yJWj7Mj1y9ITFjxTVv3yad
+      w42MtyIA7vcT344AuN9P3KsJwB0/c+chk3Ss7Qbask3GSxUbh/ycU4b3tdEO8DKJd08b6zgrMbw5hL+b
+      jQOb7uf3nLmmA+XYeDOfDNBxMt6eDhRmY2QDB/a5iZnAgX1uzptU2IBGIWc0mx3M8UUWfZ7fzpezm2a3
+      6qlWmzONi3sJL+erFUXXQ4grur1i6SRnGrMD4UPzHtAcmyyqZa882sRJdCxe1NyzOt3Lxl5cTW5DeCX+
+      WC9VWTzKRsxjJggd4HETEHWblxvZU4yq83fkOBrrNZ8HmM+95osA84XX/D7A/N5r/iXA/IvX/CHA/MFn
+      vuSLL33e3/ne333e+CdfHP/0mTcHvnlz8JoDznnjPedtgHnrNScZ35xkXnPAOSfecxYB5yx85/xzv+cX
+      oQr2u89D3Ocj7qATPx8787BTHzv3iyD7xYj9fZD9/Yj9lyD7LyP2D0H2D357ULKPpHpQoo+keVCSj6R4
+      UIKPpPevIe5f/e7fQty/+d2XIe5Lv/v3EDfUgmg667LZ3K5ukmRVuq1P8zDJsXwyIHbzhXhYRFcBxKmr
+      eK/eBRcp2T+ggLfrcVRpfawKstqgcbuo4+kDryDsc5cHvrrUW3epOL+4fNzuRfYcyX9E3yfPDQBQrzdK
+      i2308zxA3xmQKEm6ZbklhxjT7aYJucnL6VOccAMWRR7fi8fo5y+8ED0+5r8M818i/u/JjiWWnGG8+PAr
+      Nx/aqNdLz4eIAYlCy4cGhxi5+RAxYFE4+RDCx/yXYf5LxE/LhwZnGKNtXTX1E2GmhIWZvqeXaLvZqguo
+      Xg81RWmSrrWu3l+cjrb3VlD1gMKJI3Mm48w7yrF1eZFh1EjXyjMitnYNnDZRiNnApUH7Kcl5do027UXJ
+      z202C5kDcxwqAWIxcp3OAUZumuDpEZBPIB6JwMwrEG9E6ArAp2bNnV9J26jBNG4Pko+5ZUP/9Xn6Wy6M
+      hyJ0h6KnsioI7zcQ3ohQZJH8ESObmyDkpGd0E9ScojiPkjKKk8nr7WiI5VFVOGX2tgEBLlKe0iHAVaWk
+      jUxtDjCK+JmuU5Dt+hltp39cqiGuJ7vYUj0SsTyPqczJcZ79nSbNhK26jOo9SQsanChq+4Ey26ayCMvT
+      bT19xzmMByLssjRPokNNd/ekZc3qdB9ty/1G/oWe2R3aslfprnlprh7+ZsSm6dlTdhsb0WDxVDVSFikv
+      SgdbbhF4h8XoHT7WW2YONcjBuknTY7QvE1mIqJnAafQcV5SlgDBei5CV3SickM0i6l6LMG3ad0kknspj
+      3oxgTZ8jAKCmV62RJXOSmmaqkq07AfWnOElIV+A3mVHVQXoaDZRrUzPo5X9TdR2m+YooVsu0HDfygS5E
+      TconAGuakyR6KatEUIwnxjBty8MrWTVAhiuRDR7OtRqcYUx/HuR9J6hawHDsslrIB458kQZnGtU3kfuy
+      qB/LfUp4hBzSZ43EPs5zvrvljQiPcf2UVh8Izo4wLDJJqrh4TMkJaoKmU6gVmJoinWy1UNtbpXlcZ89p
+      /qq+PCDlS4A27P+Kt+UmIwhbwHDk2z3rmTE405gKEdVPcaFnhiVFDQqQGNTbZZGGdZ/leTOxRTZ/SI17
+      iPWYa9n6pOyKhQqsGEUmH7noJUumL79sc6axTNo9Vhn5w2FBM/XuGZxjlIVvtIlls+aCfcqQAoyjsia5
+      iHRhx921zN61jzs/DOrBIrKTzOHRCNTyz2FRs0i3VVoHBdAVTpxcPGU7taEsM40cHokQGMDj3x/zkMod
+      UzhxuO1NhwXNnPKi5xzj8fxX9rkarGWWj1rxjuRrCNMiE5tVQuqcY1Rd+/gXoq6FYNclx3UJuBh3Qecc
+      o0pTokwhoIfRcLVRx0t+AE+MY+LkEDd3lDLPFM2n0KrZWW6es/IoZKtT3rBDKWSLgxBh1GVGLppxDlZ/
+      xmEN86F8od21FjAcler38/obNup6uzqn+Q1VrLOmOU2O21QmzZbkHCjMpjpQhzzmanvc8ovsb0baapjp
+      62paslDnAOMpvZt/kL0GDdl5pwucrdjGdU3L9SfE9DRDmuTz0jHLV7N7KA7rmOmnCZ7jj+ryp8ymtdoZ
+      jFI4m6DtpNe6AwS7LjmuS8BFr3UNzjFSa7WecUzkO3pibNNP9i39id5TRksUboUadRc59QDasB+5nfcj
+      3nM/chv4R7x1/0IeZn1xxllL9Q2/EGp1vIPawCXfNS+VJjsRfoiwvcii2er2PPq4WEertRJMlQMo4F3c
+      ruef50uytOMA493H/55frcnCFtN8m03TpVAjkcXkeYsm5dqOW3ERbVKqrsMAX717zxJ2HGi8ZNguTZN6
+      Wav+GuVpQbHpnG5sdjsi3wudcm3ke2FggI98L0wONF4ybPq9eIrl/y6aBetez9+/+xCVB8IdAWmfXaTT
+      6xuY1uxqUkzZzJDZ5qr/lhZq4tDkEhPjhwiJevivrtQn4tfz1dVycb9e3N1O9cO0ZeeVnYmv7BwOfr3n
+      ak8kZL27u5nPbunOlgOM89uHr/PlbD2/JksHFPB2yw8s/nd+vV5MX7kA4/EIzFQ2aMC+mH1gmnsSstJq
+      1AStUfsjtw83N2SdggAXrXZOsNp5OHC1nrOfLh0G3Pfy7+vZxxt6zupJn5V50hYPRFjN//kwv72aR7Pb
+      b2S9DoPuNVO7RozrX8+ZKdGTkJVTICClwPrbPcMlIcD1cLv4c75cscsUi4cirK9YF99xoPHTJfd0exTw
+      /rlYLfjPgUFb9of1Fwmuv8lC7dNdV0mTAkACLMYf82+La569QS3vsS7v2411/pg+89wlTevH2WpxFV3d
+      3crkmsnyg5QaDmy6r+bL9eLT4krW0vd3N4urxZxkB3DLv7yJrherdXR/Rz1zCzW9118OcRXvBUV4YmBT
+      RJjCZnOWcbGU9d3d8hv94bBQ27u6v5l9W8//WtOcPeb4usQl6joKs5GWogJQy7ua8R4pA/Q4yTfehn3u
+      6QtRQ6xrPm7ybMtIiBPnGKP7h4+yJCP6OgqzMZJUI1ErOTEH0HWuFp+pNok4HkYxdIJM1/yKcVY9ZLvu
+      VYS0JuwvYHOOkfUQ6hxupOYXm/WYaXnGQm0v42HpIcRFv3T0SRkOUS8ae07m14v72XL9jVqg65xl/Gs9
+      v72eX6vWU/Swmn2meR3atHPWQkzQtRDtIyuu0mq7LFarB0kw61+XNu238/XqanY/j1b3f8yuKGaTxK0L
+      rnRhOe/WC9mAnH8i+U6Q6bpbf5kvqbe9h0zX/R9Xq+krTw0EZKE+3gMF2mgPdg+5rt+ont8AB+fifoOv
+      7ZJfGQC4309PxEtPrdAcVwM7fzalkupzkvUmPupnpZCrGI/DSCnHAEVhnT9yxpxzdM/qVJ9E9/Pl4u6a
+      prRgy636xd/I2aKnINs/H2Y3POOJtKzLu7++NZ359q419eyK+DoFlUCx2rOh61vOMpIbZVCLjNccw9pi
+      rIYY0grjtbyxdndAQesrY9nFq6dk5XR2kZ7ukjuKsMRHEZYhowhL/yjCMmAUYekdRVgyRxGW6CiCfoST
+      DDrrMdMTQUMdb3S/WkWykzL7uiJqNRKwksuiJTKasmSPpiw9oylL7mjKEh9NWf0lG/kUVwMADtpIfIeY
+      noeVbNE3XQSKaqBMm1p9n+JRv3cN0ezm892S6mkpzLbi6VaQb71eLj4+rOd05YmErA9/0X0PfwGmpkXB
+      0Z1AyClbKHSfhCDX8oauWt7AJnL/wQARJ7H80DnESCs7NAzwsRqbJumzrvha6GmhjjH0EOKK5rfr5TeW
+      sUUBL70S0jDAR9hDTGdgEy+Hn0DEycnhHYcYGTm8xUDfn3d/0CZQ6RxgJL4mODGA6c8ZvfSSDGDi3AM4
+      /Rlpb6S7iKNmTZp9Ov2jDQMaXOk2+vyp+/yZsO+MhcG+ZJNzfBKDfbs0T/fd9uOv9fQti30OX6T9MeeH
+      kLDPLX5UfLeEfe66DE2fkwGO8liVx0Mk/5xN3zkT430RKOs9wLTP3iwWdaymr8jmUcBx1BlEhypVH1ly
+      gug8HIGZQ9G8qSYiq7UWmNKG9Znr7RNfLWHcHZDMGu7xN33tsEvQHU4k+TDUau/PbZmk6vu/PK7UKjbU
+      hxjTOPFEtj/kzea40c9oW5ZVkhVxTb3ziAWLFliCIxZ/NGZpCDqwSAElImDwR3lklluwxB+LUQI7vD+C
+      eIurEWNX06wowrySlkXNIopVSa3uXP3KjGA4PJHKIiStNAEW41BmRd2s5cYLMfD+CPx8NfD+CCpLyKc2
+      7MaAKm9cEaU/jnEeEK4zGFHinfqvbq2wuCDHAHkoQvutON3ccpBRJtwpLF2rwaab2vnRGcO0yR6LY1O+
+      NwU9wWeRiLWtgVnaFjW8AZW1t4ZWTZ9jnUYvt7NPFKeGGb620qR1J3sGMFHzu0YBNlbzw9vmaA8W6SNZ
+      KBnIJMtptfRutI/Fd7pTpwE7+SHXMch33NBlxw1gUs2sJv+TfT2JWFl3G2z1qZaT/iDJgoWsRx2jkcjl
+      CS4xYzXtqCJ9oahPjGF6isWTSrmmnREd3l/+Ev3cq1WC4w/nF5EQL8coqeJd/e43QqjpUt+5fLg4R7Bf
+      +efikYLn0vXJ7Gvgp4lf6D0H69z5aeEXGufAHBRBx0L6Ro08jbbZQLC68IibPACAKYw4h+/pK7U90zOm
+      qWmxNtXUsVBpVaVCpJR6GDEAUZr1z6jlkY16vdSxKJAfi0C7n7DAH4Oe2zHFSJxmfCkoTGOYEiU84dDR
+      sFOvi9hK0THQV58ewKE2FAw/pAHiMVodJmg62/vPSBUDNJxqzbqyaS42rUXyowzyRoTuTtM6AgMEuZpG
+      PXWTBQSH/KzOgcOiZvqSiqgAipEVz++CYlgCMIYg7S7igJDTXMeWrjZ5KAKtczZAkKtdQZGuaznISH6s
+      DQ40kjplAwS5GEWZRSLWkFuOrDGK/EBlbH6pgarMuO04oYh33VAeJZDNmuZ2fDD8Ifd5PBHfJCmnGfWz
+      aN9m/X3x4dcofv550a9kSegloQokDnWdYhBG3KQiyOQQo2x/hJ2xLvDEUCs5BsU4CZAYbcOH1EyA6DE7
+      uX/okXhjJaVs24bEaQVIjFMe/sAK0NMj9t+C7NjzFZSTgFyUXHz4cP4744WADbpOeqfcBgenWubtsRks
+      kaXQVJ8BQa5m4Ti6rcEgn9odlK5TFGQTQqTv6boGs3zyfGtyyp0gyEVPuQGDfOSU6ynIRk+5ATN9zagZ
+      MeFODGAiJ9tAATZqovUQ4CIn2UANtuwiDlhxEaYtO2/FQQAFvMS19WwOMNLWw7MwwEdbL8jCdN+Wu3Yl
+      gAJeckpu0ZRMgnJUMpKjEn46JL50SJhreLokZKWt4WlzgJHzRCW+JyoJWsMT4/EIzFRG1vDsj5PX8HRJ
+      yEp9OhLf00Fdw9OAABe1zEqwMivhr+EJwoCbvIanS/qszJNG1/Dsf8FZwxOEQfeaqV0jRvIani4JWTkF
+      AlIKUNbwNCDAxVzDE+OhCLQ1PG0ONFLX8ARQwMtawxOmLXvIGp6oAItBWsMTQE0ve7VNEDbdAattIrjl
+      5622CaCml7raps7AJsrXYjZnGXmrbQKo7SWvtmlhjo+42pdJYTbSF6kAank562Q4oMdJvvH4Ohnu4ekf
+      DkKsa6auk2FzjpH4aa5JYTZGkoLrQ1jHyIkJrQ9xOkT4YFVDHA+jGHJX21R/Jq+2aUC2i77aps05RtZD
+      CK+2aR+h5hd8tU3nKC3PoKtttgcZDwuw2qbxZ/qlo08KZ7VNm7OMjNU2bc4yslfbhGnTzllt0+Zw44qr
+      tNou/NU2Ydq081bbdEncuuBKF5aTutqmAZku8mqbBmS6aKttDgRkoT7e0Gqb2t9pDzaw2ubpz79RPb8B
+      Ds7F/QZfm7ae5aLYlRwzoBiPQ09Q1+CNEnglo1cRdgWjZ19kSegVdIrxOGFX0hqAKLyVUBF81M9KLd9K
+      qNiPGKnlWQl1+A3r/JEz5pyje1bMlVBB2HKTV0I1KchGXQnVJS1r6EqoXgkUi7YSqs1ZRnKDGWot85rK
+      WDuZ1UhGWsi8XhHWJwqoNnw1Bruy8NQTnIEIZBRiyR3hWeIjPMuQEZ6lf4RnGTDCs/SO8CyZIzxLdISH
+      uxIqxHrM9EQAV0LtDjJWQnVJwEoui5bISNeSPdK19Ix0LbkjXUt8pIu0EmoPAA7a+wxnJVT1R/pKqCZl
+      2igroZ5+7xpoK6GaFGZb8XQryEddCdUlIev0pUt1BjBRV0J1QMhJWAnVgCDX8oauWt7AJnL/AVkJ1ThE
+      LD/glVCNI7SyA1wJtT/AamxiK6G6x1Z8LfS0UMd/gJVQjT/TVkIFUMBLr4TAlVD7A4SVUHUGNvFyuLsS
+      qnGIk8OdlVCNI4wcbq+Eqh0grYRqc4CR+ArHXQm1/ythJVSdAUycewCnPyPt/39rZ9DjugkE4Hv/SW/P
+      2bdqz1WPlSp1q14RsUlixbFZwHnZ/fVliGN78ODnIXuLYr5vHBsIGAzxdTdqqnXcnjVAFaG0F+51pndA
+      aW+mM/J1MMjEb+QjbO6z+TMq7dqMysVBwZz4lhAQMdjzE21yfqJ9Zg6gXZ8D6PLmK7rUfMVr/lzg69pc
+      4GvmONg1OQ52zR0Hu6bGwc5/dKZujz6177y8vRv374/NNRTFrpv/Uu0zco/P/H9r1cJhJW3XvjlI/ad0
+      cnOABJ+K8J9s+u1v8lLsuplzbWh88jfqqprwzl3bVZtfp8NUbPMfc3QjNvOdRKUatX0VthHAjk42/nTN
+      kaN5MMh0MIpzLpAc8XVrGYtkjgByMFaQuqfGdH8RtVPbJ8DMGWQyypcEdeVcjwdCesR5+79rhCGfdQbe
+      cmOoBmKyXKrvYt905VlUvpzD67Vq86odFDs3vw5Hpb1k2Wl+itDdt6DltlcibPLpc2mLHdx/I13dtVbI
+      slTaScbrt2uORSR4tfO4vYrD1MKm90qotjQfmrckagLH/t/Evm8r3nV4MLFJS2OVOCnJyA1LElt/D+df
+      qXD+HCkCZ87L3nVn1Qp10998PvQ19mbrEk15y6ZWrQt3lL9UzAZVKq7PPpA/WRVR2pCKUlvbK/Mlv45U
+      peIanz/ywgCZstr62OZZgUxZ+/aJvDXAtLvIz7WFWPV+Wa4tOLm2eDrXFhtybRHWuPTtmc4IfyrON4Bz
+      Q0WaVLwvKyUFp5QU2aWkWCklRXYpKVZKSfFMKSmIUtL5f/4PUcrypO5t8YrRR6LplJ3Ril6ACadVLkvp
+      ubRRXKTWnMye4BcRQsMt4zKMHG1kdA0ibOGDjlhY0ZrvnKO0N+OXjxxtvHCWSlyAyPkh/nnn7PoyQyYP
+      LNwH9dzZF7Sw4tS+PxwUPDnwzUlo9m4utj83zaLm7Fpl6F2r4Gv/UcKyF8wWJIHSXn2fWCGc/5HW/8ZL
+      ToSFhI4FNakw8kdOiAebMn+qPOunwkb2ejgIQq5PUXzbfRdH6U7KvIaVuRhSgqbssK5VnvlBUtbW38Od
+      UVWmGuGU3x/bQaJMP8Ipvy2lc/kXHeGk/93kqgdyslrf7c95oh9zhDHniT4Jz9wnWWQ/mCFh5IYFsJ6w
+      Uzjyw3rdT/gpfOb3XyulWTvLzJnIxHnqOgKEQ2hn2B6AsKvXHEmvEX1gtJKH5JhnNFeG5IjnPfUdAeyw
+      wnbGKc4PGRlkYjTo7qljWrR90/AUAcGe7TtQ3FMjWnec/OBTxzT3nj4Q0uN7VBkqT2Fbv/2h9ZAc8Ywe
+      0D11TIc2+6FvS55mxLDvVB9Y5wPpsaFjlRlIjvgrjHYxBCE9MnDWYB6ST7yDWxx6wtv3l5kzk+n6+FPk
+      jzsTKPbmjDvHXNr4lqt8SzsZhY1AZ94XIaHlXG+uUScCWxrHMTQO0fuyay2DD+mRofQdUI4hpMcG08D6
+      wBVjuytMLWyM2n0iFhYTRq2ZojsUuyqeBd9h3yjx7S3/NUMyMsikbk6ce4bmDiCH/++wJ2Ud84TmGPLV
+      lWZofGpMt4eOg/vkEX+q97AaZvvBOo0ZhnxQQHsrj5ycPDLI1MoLbEDRWmckbBrIEMYo9lpRy1fR1JZT
+      b8yoyFYy2pYjgBxdaTWMyPocwrkHc2zpa7vypMoz1zdgyKfLmqHxqTE93l6hlak7TlWwYLF5eNyblUeW
+      MOUeHiBniB8kslpmcbWL8mrZ/5mW+M+0t1ZxMm1IPzNoqawo9+VjbH6zKgYXTmdeduOIf+htW6acMMRR
+      mM9TERS7sq5A4tdDa34IwxlOJGHK/bgqWe4ZPLlvmYuT35Jrkw9HfIlnLJaPIMoFI49h4JG7rcOKgoqj
+      C13Azg96xw8wsavmlyfML6T5Jez1B4NmGRd8TlP2+24YsHo33z2x62bWJmpJwU9i2AvMSGRudPZzExl1
+      +842CKJcrmON3S/AhZM9SHJL7hkwHLElc7+hmJsZ4f2Bqj5CQzuMGsnm2JnanTb3h9IGOsrVt0sOH6y5
+      bQk88msD22SEESZrBW/VtKQgigEHS3cLdYPl2TFKeCEo1AzuxvZOKPZC/zvUwP7gSbG8Ebrw+u/Ym0AR
+      6MLbdN3Z+m7DWYnK9yGgZ8LUE4ZFlHuHh1EtYezXX/4HGHo/JLOABAA=
     EOF
 
     # We are renaming openssl to openssl_grpc so that there is no conflict with openssl if it exists
index a707cea..de72595 100644 (file)
 #import "GRPCTransport.h"
 #import "private/GRPCTransport+Private.h"
 
-NSString *const kGRPCHeadersKey = @"io.grpc.HeadersKey";
-NSString *const kGRPCTrailersKey = @"io.grpc.TrailersKey";
-
-NSString *const kGRPCErrorDomain = @"io.grpc";
-
 /**
  * The response dispatcher creates its own serial dispatch queue and target the queue to the
  * dispatch queue of a user provided response handler. It removes the requirement of having to use
index a096a85..812f346 100644 (file)
@@ -16,6 +16,8 @@
  *
  */
 
+#import <Foundation/Foundation.h>
+
 /**
  * gRPC error codes.
  * Note that a few of these are never produced by the gRPC libraries, but are of
similarity index 63%
rename from src/core/lib/gprpp/optional.h
rename to src/objective-c/GRPCClient/GRPCTypes.m
index f4535bb..b5cf6cb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2019 gRPC authors.
+ * Copyright 2015 gRPC authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  */
 
-#ifndef GRPC_CORE_LIB_GPRPP_OPTIONAL_H
-#define GRPC_CORE_LIB_GPRPP_OPTIONAL_H
+#import "GRPCTypes.h"
 
-#include <grpc/support/port_platform.h>
+NSString *const kGRPCHeadersKey = @"io.grpc.HeadersKey";
+NSString *const kGRPCTrailersKey = @"io.grpc.TrailersKey";
 
-#include "absl/types/optional.h"
-
-namespace grpc_core {
-
-template <typename T>
-using Optional = absl::optional<T>;
-
-}  // namespace grpc_core
-
-#endif /* GRPC_CORE_LIB_GPRPP_OPTIONAL_H */
+NSString *const kGRPCErrorDomain = @"io.grpc";
index 2ed1237..16ab2c6 100644 (file)
@@ -22,4 +22,4 @@
 // instead. This file can be regenerated from the template by running
 // `tools/buildgen/generate_projects.sh`.
 
-#define GRPC_OBJC_VERSION_STRING @"1.29.1"
+#define GRPC_OBJC_VERSION_STRING @"1.30.0"
index d4d2682..94a43ff 100644 (file)
@@ -23,8 +23,18 @@ platforms, you can turn it on with macro `GRPC_CFSTREAM=1` for the pod 'gRPC-Cor
 case of problem and you want to disable CFStream on iOS, you can set environment variable
 "grpc\_cfstream=0".
 
+## Caveats
+It is known to us that the CFStream API has some bug (FB6162039) which will cause gRPC's CFStream
+networking layer to stall occasionally. The issue mostly occur on MacOS systems (including iOS
+simulators on MacOS); iOS may be affected too but we have not seen issue there. gRPC provides a
+workaround to this problem with an alternative poller based on CFRunLoop. The poller can be enabled
+by setting environment variable `GRPC_CFSTREAM_RUN_LOOP=1`. Note that the poller is a client side
+only poller that does not support running a server on it. That means if an app opts in to the
+CFRunLoop-based poller, the app cannot host a gRPC server (gRPC Objective-C does not support running
+a server but other languages running on iOS do support it).
+
 ## Notes
 
 - Currently we do not support platforms other than iOS, although it is likely that this integration
   can run on MacOS targets with Apple's compiler.
-- Let us know if you meet any issue by filing issue and ping @muxi.
+- Let us know if you meet any issue by filing issue and ping @stanleycheung.
index f2715af..9ed7b7d 100644 (file)
@@ -52,7 +52,7 @@
 #import "../ConfigureCronet.h"
 
 struct fullstack_secure_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
 };
 
 static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
@@ -62,7 +62,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
   fullstack_secure_fixture_data *ffd = new fullstack_secure_fixture_data();
   memset(&f, 0, sizeof(f));
 
-  grpc_core::JoinHostPort(&ffd->localaddr, "127.0.0.1", port);
+  ffd->localaddr = grpc_core::JoinHostPort("127.0.0.1", port);
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(NULL);
@@ -83,7 +83,7 @@ static void cronet_init_client_secure_fullstack(grpc_end2end_test_fixture *f,
                                                 stream_engine *cronetEngine) {
   fullstack_secure_fixture_data *ffd = (fullstack_secure_fixture_data *)f->fixture_data;
   f->client =
-      grpc_cronet_secure_channel_create(cronetEngine, ffd->localaddr.get(), client_args, NULL);
+      grpc_cronet_secure_channel_create(cronetEngine, ffd->localaddr.c_str(), client_args, NULL);
   GPR_ASSERT(f->client != NULL);
 }
 
@@ -96,7 +96,7 @@ static void chttp2_init_server_secure_fullstack(grpc_end2end_test_fixture *f,
   }
   f->server = grpc_server_create(server_args, NULL);
   grpc_server_register_completion_queue(f->server, f->cq, NULL);
-  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr.get(), server_creds));
+  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr.c_str(), server_creds));
   grpc_server_credentials_release(server_creds);
   grpc_server_start(f->server);
 }
index 82c9952..f3bf73e 100644 (file)
@@ -130,11 +130,10 @@ unsigned int parse_h2_length(const char *field) {
                               {{NULL, NULL, NULL, NULL}}}};
 
   int port = grpc_pick_unused_port_or_die();
-  grpc_core::UniquePtr<char> addr;
-  grpc_core::JoinHostPort(&addr, "127.0.0.1", port);
+  std::string addr = grpc_core::JoinHostPort("127.0.0.1", port);
   grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   stream_engine *cronetEngine = [Cronet getGlobalEngine];
-  grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr.get(), NULL, NULL);
+  grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr.c_str(), NULL, NULL);
 
   cq_verifier *cqv = cq_verifier_create(cq);
   grpc_op ops[6];
@@ -261,11 +260,10 @@ unsigned int parse_h2_length(const char *field) {
                               {{NULL, NULL, NULL, NULL}}}};
 
   int port = grpc_pick_unused_port_or_die();
-  grpc_core::UniquePtr<char> addr;
-  grpc_core::JoinHostPort(&addr, "127.0.0.1", port);
+  std::string addr = grpc_core::JoinHostPort("127.0.0.1", port);
   grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   stream_engine *cronetEngine = [Cronet getGlobalEngine];
-  grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr.get(), args, NULL);
+  grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr.c_str(), args, NULL);
 
   cq_verifier *cqv = cq_verifier_create(cq);
   grpc_op ops[6];
index 43ffb0e..762af5e 100755 (executable)
@@ -49,6 +49,7 @@ if [ "$SCHEME" == "tvOS-sample" ]; then
     -derivedDataPath Build/Build \
     CODE_SIGN_IDENTITY="" \
     CODE_SIGNING_REQUIRED=NO \
+    CODE_SIGNING_ALLOWED=NO \
     | $TEST_PATH/verbose_time.sh \
     | egrep -v "$XCODEBUILD_FILTER" \
     | egrep -v "^$" -
@@ -61,6 +62,7 @@ else
     -derivedDataPath Build/Build \
     CODE_SIGN_IDENTITY="" \
     CODE_SIGNING_REQUIRED=NO \
+    CODE_SIGNING_ALLOWED=NO \
     | $TEST_PATH/verbose_time.sh \
     | egrep -v "$XCODEBUILD_FILTER" \
     | egrep -v "^$" -
index e36bcbb..52d74b3 100644 (file)
@@ -22,5 +22,5 @@
 // instead. This file can be regenerated from the template by running
 // `tools/buildgen/generate_projects.sh`.
 
-#define GRPC_OBJC_VERSION_STRING @"1.29.1"
+#define GRPC_OBJC_VERSION_STRING @"1.30.0"
 #define GRPC_C_VERSION_STRING @"10.0.0"
index e589408..9aa6689 100644 (file)
@@ -275,12 +275,8 @@ $ composer install
 
 ### Client Stub
 
-Generate client stub classes from `.proto` files
-
-```sh
-$ cd grpc/src/php
-$ ./bin/generate_proto_php.sh
-```
+The generate client stub classes have already been generated from `.proto` files
+by the `./bin/generate_proto_php.sh` script.
 
 ### Run test server
 
@@ -369,4 +365,30 @@ $client = new Helloworld\GreeterClient('localhost:50051', [
 ]);
 ```
 
+### Compression 
+
+You can customize the compression behavior on the client side, by specifying the following options when constructing your PHP client.
+
+``` 
+Possible values for grpc.default_compression_algorithm:
+0 - No compression
+1 - Compress with DEFLATE algorithm
+2 - Compress with GZIP algorithm
+3 - Stream compression with GZIP algorithm
+```
+```
+Possible values for grpc.default_compression_level:
+0 - None
+1 - Low level
+2 - Medium level
+3 - High level
+```
+Here's an example on how you can put them all together:
+```
+$client = new Helloworld\GreeterClient('localhost:50051', [
+        'credentials' => Grpc\ChannelCredentials::createInsecure(),
+        'grpc.default_compression_algorithm' => 2,  
+        'grpc.default_compression_level' => 2,
+]);
+
 [Node]:https://github.com/grpc/grpc/tree/master/src/node/examples
index 3a64438..09bb1d6 100755 (executable)
@@ -16,7 +16,7 @@
 set -e
 cd $(dirname $0)/../../..
 
-ALL_IMAGES=( grpc-ext grpc-src alpine php5 php-src php-future php-zts
+ALL_IMAGES=( grpc-ext grpc-src alpine centos7 php5 php-src php-future php-zts
              fork-support )
 
 if [[ "$1" == "--cmds" ]]; then
index 0b09b85..5dd22f6 100755 (executable)
 set -e
 cd $(dirname $0)/../../..
 
-# TODO(jtattermusch): unlike for e.g. ruby and csharp,
-# PHP runs the code generator as part of the build, so we cannot
-# easily use bazel-built "protoc" and "grpc_php_plugin" binaries.
-# TODO(jtattermusch): the generated code for qps tests
-# is actually checked into the repository, but for other tests
-# (e.g. interop or unit tests) it's not. This should made consistent.
-protoc --proto_path=src/proto/math \
+# protoc and grpc_*_plugin binaries can be obtained by running
+# $ bazel build @com_google_protobuf//:protoc //src/compiler:all
+PROTOC=bazel-bin/external/com_google_protobuf/protoc
+PLUGIN=protoc-gen-grpc=bazel-bin/src/compiler/grpc_php_plugin
+
+$PROTOC --proto_path=src/proto/math \
        --php_out=src/php/tests/generated_code \
        --grpc_out=src/php/tests/generated_code \
-       --plugin=protoc-gen-grpc=bins/opt/grpc_php_plugin \
+       --plugin=$PLUGIN \
        src/proto/math/math.proto
 
 # replace the Empty message with EmptyMessage
@@ -38,10 +37,11 @@ sed 's/grpc\.testing\.Empty/grpc\.testing\.EmptyMessage/g' \
   src/proto/grpc/testing/test.proto > $output_file
 mv $output_file ./src/proto/grpc/testing/test.proto
 
-protoc --proto_path=. \
+# interop test protos
+$PROTOC --proto_path=. \
        --php_out=src/php/tests/interop \
        --grpc_out=src/php/tests/interop \
-       --plugin=protoc-gen-grpc=bins/opt/grpc_php_plugin \
+       --plugin=$PLUGIN \
        src/proto/grpc/testing/messages.proto \
        src/proto/grpc/testing/empty.proto \
        src/proto/grpc/testing/test.proto
@@ -54,3 +54,11 @@ sed 's/grpc\.testing\.EmptyMessage/grpc\.testing\.Empty/g' \
   src/proto/grpc/testing/test.proto > $output_file
 mv $output_file ./src/proto/grpc/testing/test.proto
 
+# Hack for xDS interop: need this to be a separate file in the correct namespace.
+# To be removed when grpc_php_plugin generates service stubs.
+echo '<?php
+// DO NOT EDIT
+namespace Grpc\Testing;
+class LoadBalancerStatsServiceStub {
+}
+' > ./src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceStub.php
index 0882ecc..5859d08 100755 (executable)
@@ -16,7 +16,7 @@
 set -e
 cd $(dirname $0)/../../..
 
-ALL_IMAGES=( grpc-ext grpc-src alpine php5 php-src php-future php-zts
+ALL_IMAGES=( grpc-ext grpc-src alpine centos7 php5 php-src php-future php-zts
              fork-support )
 
 if [[ "$1" == "--cmds" ]]; then
index 31506c5..0408a91 100755 (executable)
@@ -29,7 +29,8 @@ for arg in "$@"
 do
   if [[ "$arg" == "--skip-persistent-channel-tests" ]]; then
     SKIP_PERSISTENT_CHANNEL_TESTS=true
-    break
+  elif [[ "$arg" == "--ignore-valgrind-undef-errors" ]]; then
+    VALGRIND_UNDEF_VALUE_ERRORS="--undef-value-errors=no"
   fi
 done
 
@@ -43,6 +44,7 @@ export USE_ZEND_ALLOC=0
 # Detect whether valgrind is executable
 if [ -x "$(command -v valgrind)" ]; then
   $(which valgrind) --error-exitcode=10 --leak-check=yes \
+    $VALGRIND_UNDEF_VALUE_ERRORS \
     $(which php) $extension_dir -d max_execution_time=300 \
     ../tests/MemoryLeakTest/MemoryLeakTest.php
 fi
index f0d78e5..41a7d9a 100644 (file)
@@ -2,7 +2,7 @@
   "name": "grpc/grpc-dev",
   "description": "gRPC library for PHP - for Development use only",
   "license": "Apache-2.0",
-  "version": "1.29.1",
+  "version": "1.30.0",
   "require": {
     "php": ">=5.5.0",
     "google/protobuf": "^v3.3.0"
index ab5acf8..638d65c 100644 (file)
@@ -95,6 +95,20 @@ Run image:
 ```sh
 $ docker run -it --rm grpc-php/alpine
 ```
+### `centos7`
+
+This image builds the `grpc` extension against the GCC version in Centos7 base image. The default version of gcc in centos7 is gcc-4.8.5. Run `scl enable devtoolset-7 bash` command to enable gcc-7.3.1.
+
+Build `centos7` docker image:
+```sh
+$ cd grpc
+$ docker build -t grpc-gcc7/centos -f ./src/php/docker/centos7/Dockerfile .
+```
+
+Run image:
+```sh
+$ docker run -it --rm grpc-gcc7/centos
+```
 
 ### `php-src`
 
diff --git a/src/php/docker/centos7/Dockerfile b/src/php/docker/centos7/Dockerfile
new file mode 100644 (file)
index 0000000..e6df3ef
--- /dev/null
@@ -0,0 +1,51 @@
+# Copyright 2019 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FROM centos:centos7
+
+RUN yum update -y && \
+  yum install -y centos-release-scl && \
+  yum install -y devtoolset-7-gcc*
+
+SHELL [ "/usr/bin/scl", "enable", "devtoolset-7"]
+
+RUN yum install epel-release -y && \
+  rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm && \
+  rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm && \
+  yum --enablerepo=remi-php72 install php -y && \
+  yum-config-manager --enable remi-php72 > /dev/null && \
+  yum install -y make wget which \
+    gmp-devel libmpc-devel mpfr-devel yum-utils \                                                            
+    php-devel php-fpm php-pear && \                                                                          
+  yum clean all -y  
+
+ARG MAKEFLAGS=-j8
+
+
+WORKDIR /tmp
+
+RUN wget https://phar.phpunit.de/phpunit-5.7.27.phar && \
+  mv phpunit-5.7.27.phar /usr/local/bin/phpunit && \
+  chmod +x /usr/local/bin/phpunit
+
+
+WORKDIR /github/grpc
+
+COPY . .
+
+RUN pear package && \
+  find . -name grpc-*.tgz | xargs -I{} pecl install {}
+
+
+CMD ["/github/grpc/src/php/bin/run_tests.sh", "--skip-persistent-channel-tests"]
index b0f6c88..b55513e 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FROM php:7.4.0RC1-buster
+FROM php:7.4.5-buster
 
 RUN apt-get -qq update && apt-get -qq install -y \
   autoconf automake git libtool pkg-config \
-  wget zlib1g-dev
+  valgrind wget zlib1g-dev
 
 ARG MAKEFLAGS=-j8
 
@@ -36,4 +36,4 @@ RUN pear package && \
   find . -name grpc-*.tgz | xargs -I{} pecl install {}
 
 
-CMD ["/github/grpc/src/php/bin/run_tests.sh", "--skip-persistent-channel-tests"]
+CMD ["/github/grpc/src/php/bin/run_tests.sh", "--skip-persistent-channel-tests", "--ignore-valgrind-undef-errors"]
index 6dcfef0..87099f4 100644 (file)
@@ -162,35 +162,30 @@ void destroy_grpc_channels() {
   PHP_GRPC_HASH_FOREACH_END()
 }
 
-void restart_channels() {
-  zval *data;
-  PHP_GRPC_HASH_FOREACH_VAL_START(&grpc_persistent_list, data)
-    php_grpc_zend_resource *rsrc  =
-                (php_grpc_zend_resource*) PHP_GRPC_HASH_VALPTR_TO_VAL(data)
-    if (rsrc == NULL) {
-      break;
-    }
-    channel_persistent_le_t* le = rsrc->ptr;
-
-    wrapped_grpc_channel wrapped_channel;
-    wrapped_channel.wrapper = le->channel;
-    grpc_channel_wrapper *channel = wrapped_channel.wrapper;
-    create_new_channel(&wrapped_channel, channel->target, channel->args,
-                       channel->creds);
-    gpr_mu_unlock(&channel->mu);
-  PHP_GRPC_HASH_FOREACH_END()
-}
-
 void prefork() {
   acquire_persistent_locks();
 }
 
+// Clean all channels in the persistent list
+// Called at post fork
+void php_grpc_clean_persistent_list(TSRMLS_D) {
+    zend_hash_clean(&grpc_persistent_list);
+    zend_hash_destroy(&grpc_persistent_list);
+    zend_hash_clean(&grpc_target_upper_bound_map);
+    zend_hash_destroy(&grpc_target_upper_bound_map);
+}
+
 void postfork_child() {
   TSRMLS_FETCH();
 
   // loop through persistent list and destroy all underlying grpc_channel objs
   destroy_grpc_channels();
 
+  release_persistent_locks();
+  
+  // clean all channels in the persistent list
+  php_grpc_clean_persistent_list(TSRMLS_C);
+
   // clear completion queue
   grpc_php_shutdown_completion_queue(TSRMLS_C);
 
@@ -205,10 +200,6 @@ void postfork_child() {
   // restart grpc_core
   grpc_init();
   grpc_php_init_completion_queue(TSRMLS_C);
-
-  // re-create grpc_channel and point wrapped to it
-  // unlock wrapped grpc channel mutex
-  restart_channels();
 }
 
 void postfork_parent() {
index 38f6e98..d16e08a 100644 (file)
@@ -20,6 +20,6 @@
 #ifndef VERSION_H
 #define VERSION_H
 
-#define PHP_GRPC_VERSION "1.29.1"
+#define PHP_GRPC_VERSION "1.30.0"
 
 #endif /* VERSION_H */
index d1c75cb..d1a186a 100644 (file)
@@ -114,14 +114,7 @@ abstract class AbstractCall
     protected function _serializeMessage($data)
     {
         // Proto3 implementation
-        if (method_exists($data, 'encode')) {
-            return $data->encode();
-        } elseif (method_exists($data, 'serializeToString')) {
-            return $data->serializeToString();
-        }
-
-        // Protobuf-PHP implementation
-        return $data->serialize();
+        return $data->serializeToString();
     }
 
     /**
@@ -136,22 +129,10 @@ abstract class AbstractCall
         if ($value === null) {
             return;
         }
-
-        // Proto3 implementation
-        if (is_array($this->deserialize)) {
-            list($className, $deserializeFunc) = $this->deserialize;
-            $obj = new $className();
-            if (method_exists($obj, $deserializeFunc)) {
-                $obj->$deserializeFunc($value);
-            } else {
-                $obj->mergeFromString($value);
-            }
-
-            return $obj;
-        }
-
-        // Protobuf-PHP implementation
-        return call_user_func($this->deserialize, $value);
+        list($className, $deserializeFunc) = $this->deserialize;
+        $obj = new $className();
+        $obj->mergeFromString($value);
+        return $obj;
     }
 
     /**
diff --git a/src/php/lib/Grpc/RpcServer.php b/src/php/lib/Grpc/RpcServer.php
new file mode 100644 (file)
index 0000000..4c88b2e
--- /dev/null
@@ -0,0 +1,168 @@
+<?php
+/*
+ *
+ * Copyright 2020 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Grpc;
+
+/**
+ * This is an experimental and incomplete implementation of gRPC server
+ * for PHP. APIs are _definitely_ going to be changed.
+ *
+ * DO NOT USE in production.
+ */
+
+/**
+ * Class RpcServer
+ * @package Grpc
+ */
+class RpcServer extends Server
+{
+    protected $call;
+    // [ <String method_full_path> => [
+    //   'service' => <Object service>,
+    //   'method'  => <String method_name>,
+    //   'request' => <Object request>,
+    // ] ]
+    protected $paths_map;
+
+    private function waitForNextEvent() {
+        return $this->requestCall();
+    }
+
+    private function loadRequest($request) {
+        if (!$this->call) {
+            throw new Exception("serverCall is not ready");
+        }
+        $event = $this->call->startBatch([
+            OP_RECV_MESSAGE => true,
+        ]);
+        if (!$event->message) {
+            throw new Exception("Did not receive a proper message");
+        }
+        $request->mergeFromString($event->message);
+        return $request;
+    }
+
+    protected function sendOkResponse($response) {
+        if (!$this->call) {
+            throw new Exception("serverCall is not ready");
+        }
+        $this->call->startBatch([
+            OP_SEND_INITIAL_METADATA => [],
+            OP_SEND_MESSAGE => ['message' =>
+                                $response->serializeToString()],
+            OP_SEND_STATUS_FROM_SERVER => [
+                'metadata' => [],
+                'code' => STATUS_OK,
+                'details' => 'OK',
+            ],
+            OP_RECV_CLOSE_ON_SERVER => true,
+        ]);
+    }
+
+    /**
+     * Add a service to this server
+     *
+     * @param Object   $service      The service to be added
+     */
+    public function handle($service) {
+        $rf = new \ReflectionClass($service);
+
+        // If input does not have a parent class, which should be the
+        // generated stub, don't proceeed. This might change in the
+        // future.
+        if (!$rf->getParentClass()) return;
+
+        // The input class name needs to match the service name
+        $service_name = $rf->getName();
+        $namespace = $rf->getParentClass()->getNamespaceName();
+        $prefix = "";
+        if ($namespace) {
+            $parts = explode("\\", $namespace);
+            foreach ($parts as $part) {
+                $prefix .= lcfirst($part) . ".";
+            }
+        }
+        $base_path = "/" . $prefix . $service_name;
+
+        // Right now, assume all the methods in the class are RPC method
+        // implementations. Might change in the future.
+        $methods = $rf->getMethods();
+        foreach ($methods as $method) {
+            $method_name = $method->getName();
+            $full_path = $base_path . "/" . ucfirst($method_name);
+
+            $method_params = $method->getParameters();
+            // RPC should have exactly 1 request param
+            if (count($method_params) != 1) continue;
+            $request_param = $method_params[0];
+            // Method implementation must have type hint for request param
+            if (!$request_param->getType()) continue;
+            $request_type = $request_param->getType()->getName();
+
+            // $full_path needs to match the incoming event->method
+            // from requestCall() for us to know how to handle the request
+            $this->paths_map[$full_path] = [
+                'service' => $service,
+                'method' => $method_name,
+                'request' => new $request_type(),
+            ];
+        }
+    }
+
+    public function run() {
+        $this->start();
+        while (true) {
+            // This blocks until the server receives a request
+            $event = $this->waitForNextEvent();
+            if (!$event) {
+                throw new Exception(
+                    "Unexpected error: server->waitForNextEvent delivers"
+                    . " an empty event");
+            }
+            if (!$event->call) {
+                throw new Exception(
+                    "Unexpected error: server->waitForNextEvent delivers"
+                    . " an event without a call");
+            }
+            $this->call = $event->call;
+            $full_path = $event->method;
+
+            // TODO: Can send a proper UNIMPLEMENTED response in the future
+            if (!array_key_exists($full_path, $this->paths_map)) continue;
+
+            $service = $this->paths_map[$full_path]['service'];
+            $method = $this->paths_map[$full_path]['method'];
+            $request = $this->paths_map[$full_path]['request'];
+
+            $request = $this->loadRequest($request);
+            if (!$request) {
+                throw new Exception("Unexpected error: fail to parse request");
+            }
+            if (!method_exists($service, $method)) {
+                // TODO: Can send a proper UNIMPLEMENTED response in the future
+                throw new Exception("Method not implemented");
+            }
+
+            // Dispatch to actual server logic
+            $response = $service->$method($request);
+            $this->sendOkResponse($response);
+            $this->call = null;
+        }
+    }
+}
diff --git a/src/php/tests/generated_code/GPBMetadata/Math.php b/src/php/tests/generated_code/GPBMetadata/Math.php
new file mode 100644 (file)
index 0000000..10f0436
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: math.proto
+
+namespace GPBMetadata;
+
+class Math
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0ae9020a0a6d6174682e70726f746f12046d617468222c0a074469764172677312100a086469766964656e64180120012803120f0a0764697669736f72180220012803222f0a084469765265706c7912100a0871756f7469656e7418012001280312110a0972656d61696e64657218022001280322180a0746696241726773120d0a056c696d697418012001280322120a034e756d120b0a036e756d18012001280322190a084669625265706c79120d0a05636f756e7418012001280332a4010a044d61746812260a03446976120d2e6d6174682e446976417267731a0e2e6d6174682e4469765265706c792200122e0a074469764d616e79120d2e6d6174682e446976417267731a0e2e6d6174682e4469765265706c7922002801300112230a03466962120d2e6d6174682e466962417267731a092e6d6174682e4e756d22003001121f0a0353756d12092e6d6174682e4e756d1a092e6d6174682e4e756d22002801620670726f746f33"
+        ), true);
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/src/php/tests/generated_code/Math/DivArgs.php b/src/php/tests/generated_code/Math/DivArgs.php
new file mode 100644 (file)
index 0000000..21fb1d7
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: math.proto
+
+namespace Math;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>math.DivArgs</code>
+ */
+class DivArgs extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>int64 dividend = 1;</code>
+     */
+    protected $dividend = 0;
+    /**
+     * Generated from protobuf field <code>int64 divisor = 2;</code>
+     */
+    protected $divisor = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $dividend
+     *     @type int|string $divisor
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Math::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 dividend = 1;</code>
+     * @return int|string
+     */
+    public function getDividend()
+    {
+        return $this->dividend;
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 dividend = 1;</code>
+     * @param int|string $var
+     * @return $this
+     */
+    public function setDividend($var)
+    {
+        GPBUtil::checkInt64($var);
+        $this->dividend = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 divisor = 2;</code>
+     * @return int|string
+     */
+    public function getDivisor()
+    {
+        return $this->divisor;
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 divisor = 2;</code>
+     * @param int|string $var
+     * @return $this
+     */
+    public function setDivisor($var)
+    {
+        GPBUtil::checkInt64($var);
+        $this->divisor = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/generated_code/Math/DivReply.php b/src/php/tests/generated_code/Math/DivReply.php
new file mode 100644 (file)
index 0000000..c4d7575
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: math.proto
+
+namespace Math;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>math.DivReply</code>
+ */
+class DivReply extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>int64 quotient = 1;</code>
+     */
+    protected $quotient = 0;
+    /**
+     * Generated from protobuf field <code>int64 remainder = 2;</code>
+     */
+    protected $remainder = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $quotient
+     *     @type int|string $remainder
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Math::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 quotient = 1;</code>
+     * @return int|string
+     */
+    public function getQuotient()
+    {
+        return $this->quotient;
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 quotient = 1;</code>
+     * @param int|string $var
+     * @return $this
+     */
+    public function setQuotient($var)
+    {
+        GPBUtil::checkInt64($var);
+        $this->quotient = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 remainder = 2;</code>
+     * @return int|string
+     */
+    public function getRemainder()
+    {
+        return $this->remainder;
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 remainder = 2;</code>
+     * @param int|string $var
+     * @return $this
+     */
+    public function setRemainder($var)
+    {
+        GPBUtil::checkInt64($var);
+        $this->remainder = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/generated_code/Math/FibArgs.php b/src/php/tests/generated_code/Math/FibArgs.php
new file mode 100644 (file)
index 0000000..39bb4fa
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: math.proto
+
+namespace Math;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>math.FibArgs</code>
+ */
+class FibArgs extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>int64 limit = 1;</code>
+     */
+    protected $limit = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $limit
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Math::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 limit = 1;</code>
+     * @return int|string
+     */
+    public function getLimit()
+    {
+        return $this->limit;
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 limit = 1;</code>
+     * @param int|string $var
+     * @return $this
+     */
+    public function setLimit($var)
+    {
+        GPBUtil::checkInt64($var);
+        $this->limit = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/generated_code/Math/FibReply.php b/src/php/tests/generated_code/Math/FibReply.php
new file mode 100644 (file)
index 0000000..d9ad9cd
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: math.proto
+
+namespace Math;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>math.FibReply</code>
+ */
+class FibReply extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>int64 count = 1;</code>
+     */
+    protected $count = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $count
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Math::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 count = 1;</code>
+     * @return int|string
+     */
+    public function getCount()
+    {
+        return $this->count;
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 count = 1;</code>
+     * @param int|string $var
+     * @return $this
+     */
+    public function setCount($var)
+    {
+        GPBUtil::checkInt64($var);
+        $this->count = $var;
+
+        return $this;
+    }
+
+}
+
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-namespace Grpc\Testing;
+namespace Math;
 
 /**
  */
-class EchoTestServiceClient extends \Grpc\BaseStub {
+class MathClient extends \Grpc\BaseStub {
 
     /**
      * @param string $hostname hostname
@@ -32,61 +32,63 @@ class EchoTestServiceClient extends \Grpc\BaseStub {
     }
 
     /**
-     * @param \Grpc\Testing\EchoRequest $argument input argument
+     * Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
+     * and remainder.
+     * @param \Math\DivArgs $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Math\DivReply
      */
-    public function Echo(\Grpc\Testing\EchoRequest $argument,
+    public function Div(\Math\DivArgs $argument,
       $metadata = [], $options = []) {
-        return $this->_simpleRequest('/grpc.testing.EchoTestService/Echo',
+        return $this->_simpleRequest('/math.Math/Div',
         $argument,
-        ['\Grpc\Testing\EchoResponse', 'decode'],
+        ['\Math\DivReply', 'decode'],
         $metadata, $options);
     }
 
     /**
+     * DivMany accepts an arbitrary number of division args from the client stream
+     * and sends back the results in the reply stream.  The stream continues until
+     * the client closes its end; the server does the same after sending all the
+     * replies.  The stream ends immediately if either end aborts.
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Math\DivReply
      */
-    public function RequestStream($metadata = [], $options = []) {
-        return $this->_clientStreamRequest('/grpc.testing.EchoTestService/RequestStream',
-        ['\Grpc\Testing\EchoResponse','decode'],
+    public function DivMany($metadata = [], $options = []) {
+        return $this->_bidiRequest('/math.Math/DivMany',
+        ['\Math\DivReply','decode'],
         $metadata, $options);
     }
 
     /**
-     * @param \Grpc\Testing\EchoRequest $argument input argument
+     * Fib generates numbers in the Fibonacci sequence.  If FibArgs.limit > 0, Fib
+     * generates up to limit numbers; otherwise it continues until the call is
+     * canceled.  Unlike Fib above, Fib has no final FibReply.
+     * @param \Math\FibArgs $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Math\Num
      */
-    public function ResponseStream(\Grpc\Testing\EchoRequest $argument,
+    public function Fib(\Math\FibArgs $argument,
       $metadata = [], $options = []) {
-        return $this->_serverStreamRequest('/grpc.testing.EchoTestService/ResponseStream',
+        return $this->_serverStreamRequest('/math.Math/Fib',
         $argument,
-        ['\Grpc\Testing\EchoResponse', 'decode'],
+        ['\Math\Num', 'decode'],
         $metadata, $options);
     }
 
     /**
+     * Sum sums a stream of numbers, returning the final result once the stream
+     * is closed.
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Math\Num
      */
-    public function BidiStream($metadata = [], $options = []) {
-        return $this->_bidiRequest('/grpc.testing.EchoTestService/BidiStream',
-        ['\Grpc\Testing\EchoResponse','decode'],
-        $metadata, $options);
-    }
-
-    /**
-     * @param \Grpc\Testing\EchoRequest $argument input argument
-     * @param array $metadata metadata
-     * @param array $options call options
-     */
-    public function Unimplemented(\Grpc\Testing\EchoRequest $argument,
-      $metadata = [], $options = []) {
-        return $this->_simpleRequest('/grpc.testing.EchoTestService/Unimplemented',
-        $argument,
-        ['\Grpc\Testing\EchoResponse', 'decode'],
+    public function Sum($metadata = [], $options = []) {
+        return $this->_clientStreamRequest('/math.Math/Sum',
+        ['\Math\Num','decode'],
         $metadata, $options);
     }
 
diff --git a/src/php/tests/generated_code/Math/Num.php b/src/php/tests/generated_code/Math/Num.php
new file mode 100644 (file)
index 0000000..356b328
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: math.proto
+
+namespace Math;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>math.Num</code>
+ */
+class Num extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>int64 num = 1;</code>
+     */
+    protected $num = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $num
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Math::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 num = 1;</code>
+     * @return int|string
+     */
+    public function getNum()
+    {
+        return $this->num;
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 num = 1;</code>
+     * @param int|string $var
+     * @return $this
+     */
+    public function setNum($var)
+    {
+        GPBUtil::checkInt64($var);
+        $this->num = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php b/src/php/tests/interop/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php
new file mode 100644 (file)
index 0000000..91a9c7b
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class Messages
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0ad70e0a257372632f70726f746f2f677270632f74657374696e672f6d657373616765732e70726f746f120c677270632e74657374696e67221a0a09426f6f6c56616c7565120d0a0576616c756518012001280822400a075061796c6f616412270a047479706518012001280e32192e677270632e74657374696e672e5061796c6f616454797065120c0a04626f647918022001280c222b0a0a4563686f537461747573120c0a04636f6465180120012805120f0a076d6573736167651802200128092286030a0d53696d706c655265717565737412300a0d726573706f6e73655f7479706518012001280e32192e677270632e74657374696e672e5061796c6f61645479706512150a0d726573706f6e73655f73697a6518022001280512260a077061796c6f616418032001280b32152e677270632e74657374696e672e5061796c6f616412150a0d66696c6c5f757365726e616d6518042001280812180a1066696c6c5f6f617574685f73636f706518052001280812340a13726573706f6e73655f636f6d7072657373656418062001280b32172e677270632e74657374696e672e426f6f6c56616c756512310a0f726573706f6e73655f73746174757318072001280b32182e677270632e74657374696e672e4563686f53746174757312320a116578706563745f636f6d7072657373656418082001280b32172e677270632e74657374696e672e426f6f6c56616c756512160a0e66696c6c5f7365727665725f6964180920012808121e0a1666696c6c5f677270636c625f726f7574655f74797065180a2001280822be010a0e53696d706c65526573706f6e736512260a077061796c6f616418012001280b32152e677270632e74657374696e672e5061796c6f616412100a08757365726e616d6518022001280912130a0b6f617574685f73636f706518032001280912110a097365727665725f696418042001280912380a11677270636c625f726f7574655f7479706518052001280e321d2e677270632e74657374696e672e477270636c62526f7574655479706512100a08686f73746e616d6518062001280922770a1953747265616d696e67496e70757443616c6c5265717565737412260a077061796c6f616418012001280b32152e677270632e74657374696e672e5061796c6f616412320a116578706563745f636f6d7072657373656418022001280b32172e677270632e74657374696e672e426f6f6c56616c7565223d0a1a53747265616d696e67496e70757443616c6c526573706f6e7365121f0a17616767726567617465645f7061796c6f61645f73697a6518012001280522640a12526573706f6e7365506172616d6574657273120c0a0473697a6518012001280512130a0b696e74657276616c5f7573180220012805122b0a0a636f6d7072657373656418032001280b32172e677270632e74657374696e672e426f6f6c56616c756522e8010a1a53747265616d696e674f757470757443616c6c5265717565737412300a0d726573706f6e73655f7479706518012001280e32192e677270632e74657374696e672e5061796c6f616454797065123d0a13726573706f6e73655f706172616d657465727318022003280b32202e677270632e74657374696e672e526573706f6e7365506172616d657465727312260a077061796c6f616418032001280b32152e677270632e74657374696e672e5061796c6f616412310a0f726573706f6e73655f73746174757318072001280b32182e677270632e74657374696e672e4563686f53746174757322450a1b53747265616d696e674f757470757443616c6c526573706f6e736512260a077061796c6f616418012001280b32152e677270632e74657374696e672e5061796c6f616422330a0f5265636f6e6e656374506172616d7312200a186d61785f7265636f6e6e6563745f6261636b6f66665f6d7318012001280522330a0d5265636f6e6e656374496e666f120e0a0670617373656418012001280812120a0a6261636b6f66665f6d7318022003280522410a184c6f616442616c616e63657253746174735265717565737412100a086e756d5f7270637318012001280512130a0b74696d656f75745f73656318022001280522b3010a194c6f616442616c616e6365725374617473526573706f6e7365124d0a0c727063735f62795f7065657218012003280b32372e677270632e74657374696e672e4c6f616442616c616e6365725374617473526573706f6e73652e52706373427950656572456e74727912140a0c6e756d5f6661696c757265731802200128051a310a0f52706373427950656572456e747279120b0a036b6579180120012809120d0a0576616c75651802200128053a0238012a1f0a0b5061796c6f61645479706512100a0c434f4d505245535341424c4510002a6f0a0f477270636c62526f75746554797065121d0a19475250434c425f524f5554455f545950455f554e4b4e4f574e1000121e0a1a475250434c425f524f5554455f545950455f46414c4c4241434b1001121d0a19475250434c425f524f5554455f545950455f4241434b454e441002620670726f746f33"
+        ), true);
+
+        static::$is_initialized = true;
+    }
+}
+
@@ -4,7 +4,7 @@
 
 namespace GPBMetadata\Src\Proto\Grpc\Testing;
 
-class GPBEmpty
+class PBEmpty
 {
     public static $is_initialized = false;
 
@@ -15,10 +15,8 @@ class GPBEmpty
           return;
         }
         $pool->internalAddGeneratedFile(hex2bin(
-            "0a430a227372632f70726f746f2f677270632f74657374696e672f656d70" .
-            "74792e70726f746f120c677270632e74657374696e6722070a05456d7074" .
-            "79620670726f746f33"
-        ));
+            "0a4a0a227372632f70726f746f2f677270632f74657374696e672f656d7074792e70726f746f120c677270632e74657374696e67220e0a0c456d7074794d657373616765620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
diff --git a/src/php/tests/interop/GPBMetadata/Src/Proto/Grpc/Testing/Test.php b/src/php/tests/interop/GPBMetadata/Src/Proto/Grpc/Testing/Test.php
new file mode 100644 (file)
index 0000000..2ae2dad
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/test.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class Test
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        \GPBMetadata\Src\Proto\Grpc\Testing\PBEmpty::initOnce();
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0aca090a217372632f70726f746f2f677270632f74657374696e672f746573742e70726f746f120c677270632e74657374696e671a257372632f70726f746f2f677270632f74657374696e672f6d657373616765732e70726f746f32e7050a0b546573745365727669636512430a09456d70747943616c6c121a2e677270632e74657374696e672e456d7074794d6573736167651a1a2e677270632e74657374696e672e456d7074794d65737361676512460a09556e61727943616c6c121b2e677270632e74657374696e672e53696d706c65526571756573741a1c2e677270632e74657374696e672e53696d706c65526573706f6e7365124f0a12436163686561626c65556e61727943616c6c121b2e677270632e74657374696e672e53696d706c65526571756573741a1c2e677270632e74657374696e672e53696d706c65526573706f6e7365126c0a1353747265616d696e674f757470757443616c6c12282e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526571756573741a292e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526573706f6e7365300112690a1253747265616d696e67496e70757443616c6c12272e677270632e74657374696e672e53747265616d696e67496e70757443616c6c526571756573741a282e677270632e74657374696e672e53747265616d696e67496e70757443616c6c526573706f6e7365280112690a0e46756c6c4475706c657843616c6c12282e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526571756573741a292e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526573706f6e73652801300112690a0e48616c664475706c657843616c6c12282e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526571756573741a292e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526573706f6e736528013001124b0a11556e696d706c656d656e74656443616c6c121a2e677270632e74657374696e672e456d7074794d6573736167651a1a2e677270632e74657374696e672e456d7074794d65737361676532630a14556e696d706c656d656e74656453657276696365124b0a11556e696d706c656d656e74656443616c6c121a2e677270632e74657374696e672e456d7074794d6573736167651a1a2e677270632e74657374696e672e456d7074794d6573736167653297010a105265636f6e6e6563745365727669636512420a055374617274121d2e677270632e74657374696e672e5265636f6e6e656374506172616d731a1a2e677270632e74657374696e672e456d7074794d657373616765123f0a0453746f70121a2e677270632e74657374696e672e456d7074794d6573736167651a1b2e677270632e74657374696e672e5265636f6e6e656374496e666f327f0a184c6f616442616c616e63657253746174735365727669636512630a0e476574436c69656e74537461747312262e677270632e74657374696e672e4c6f616442616c616e6365725374617473526571756573741a272e677270632e74657374696e672e4c6f616442616c616e6365725374617473526573706f6e73652200620670726f746f33"
+        ), true);
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/BoolValue.php b/src/php/tests/interop/Grpc/Testing/BoolValue.php
new file mode 100644 (file)
index 0000000..a1fd08d
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * TODO(dgq): Go back to using well-known types once
+ * https://github.com/grpc/grpc/issues/6980 has been fixed.
+ * import "google/protobuf/wrappers.proto";
+ *
+ * Generated from protobuf message <code>grpc.testing.BoolValue</code>
+ */
+class BoolValue extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * The bool value.
+     *
+     * Generated from protobuf field <code>bool value = 1;</code>
+     */
+    protected $value = false;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type bool $value
+     *           The bool value.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * The bool value.
+     *
+     * Generated from protobuf field <code>bool value = 1;</code>
+     * @return bool
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /**
+     * The bool value.
+     *
+     * Generated from protobuf field <code>bool value = 1;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setValue($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->value = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/EchoStatus.php b/src/php/tests/interop/Grpc/Testing/EchoStatus.php
new file mode 100644 (file)
index 0000000..31fd6dd
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * A protobuf representation for grpc status. This is used by test
+ * clients to specify a status that the server should attempt to return.
+ *
+ * Generated from protobuf message <code>grpc.testing.EchoStatus</code>
+ */
+class EchoStatus extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>int32 code = 1;</code>
+     */
+    protected $code = 0;
+    /**
+     * Generated from protobuf field <code>string message = 2;</code>
+     */
+    protected $message = '';
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $code
+     *     @type string $message
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 code = 1;</code>
+     * @return int
+     */
+    public function getCode()
+    {
+        return $this->code;
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 code = 1;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setCode($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->code = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>string message = 2;</code>
+     * @return string
+     */
+    public function getMessage()
+    {
+        return $this->message;
+    }
+
+    /**
+     * Generated from protobuf field <code>string message = 2;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setMessage($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->message = $var;
+
+        return $this;
+    }
+
+}
+
@@ -16,14 +16,22 @@ use Google\Protobuf\Internal\GPBUtil;
  *     rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { };
  *   };
  *
- * Generated from protobuf message <code>grpc.testing.Empty</code>
+ * Generated from protobuf message <code>grpc.testing.EmptyMessage</code>
  */
-class PBEmpty extends \Google\Protobuf\Internal\Message
+class EmptyMessage extends \Google\Protobuf\Internal\Message
 {
 
-    public function __construct() {
-        \GPBMetadata\Src\Proto\Grpc\Testing\GPBEmpty::initOnce();
-        parent::__construct();
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\PBEmpty::initOnce();
+        parent::__construct($data);
     }
 
 }
diff --git a/src/php/tests/interop/Grpc/Testing/EmptyMessageMessage.php b/src/php/tests/interop/Grpc/Testing/EmptyMessageMessage.php
new file mode 100644 (file)
index 0000000..678b6ca
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/empty.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * 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) { };
+ *   };
+ *
+ * Generated from protobuf message <code>grpc.testing.EmptyMessageMessage</code>
+ */
+class EmptyMessageMessage extends \Google\Protobuf\Internal\Message
+{
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\PBEmpty::initOnce();
+        parent::__construct($data);
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/GrpclbRouteType.php b/src/php/tests/interop/Grpc/Testing/GrpclbRouteType.php
new file mode 100644 (file)
index 0000000..f8bff1c
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use UnexpectedValueException;
+
+/**
+ * The type of route that a client took to reach a server w.r.t. gRPCLB.
+ * The server must fill in "fallback" if it detects that the RPC reached
+ * the server via the "gRPCLB fallback" path, and "backend" if it detects
+ * that the RPC reached the server via "gRPCLB backend" path (i.e. if it got
+ * the address of this server from the gRPCLB server BalanceLoad RPC). Exactly
+ * how this detection is done is context and server dependent.
+ *
+ * Protobuf type <code>grpc.testing.GrpclbRouteType</code>
+ */
+class GrpclbRouteType
+{
+    /**
+     * Server didn't detect the route that a client took to reach it.
+     *
+     * Generated from protobuf enum <code>GRPCLB_ROUTE_TYPE_UNKNOWN = 0;</code>
+     */
+    const GRPCLB_ROUTE_TYPE_UNKNOWN = 0;
+    /**
+     * Indicates that a client reached a server via gRPCLB fallback.
+     *
+     * Generated from protobuf enum <code>GRPCLB_ROUTE_TYPE_FALLBACK = 1;</code>
+     */
+    const GRPCLB_ROUTE_TYPE_FALLBACK = 1;
+    /**
+     * Indicates that a client reached a server as a gRPCLB-given backend.
+     *
+     * Generated from protobuf enum <code>GRPCLB_ROUTE_TYPE_BACKEND = 2;</code>
+     */
+    const GRPCLB_ROUTE_TYPE_BACKEND = 2;
+
+    private static $valueToName = [
+        self::GRPCLB_ROUTE_TYPE_UNKNOWN => 'GRPCLB_ROUTE_TYPE_UNKNOWN',
+        self::GRPCLB_ROUTE_TYPE_FALLBACK => 'GRPCLB_ROUTE_TYPE_FALLBACK',
+        self::GRPCLB_ROUTE_TYPE_BACKEND => 'GRPCLB_ROUTE_TYPE_BACKEND',
+    ];
+
+    public static function name($value)
+    {
+        if (!isset(self::$valueToName[$value])) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no name defined for value %s', __CLASS__, $value));
+        }
+        return self::$valueToName[$value];
+    }
+
+
+    public static function value($name)
+    {
+        $const = __CLASS__ . '::' . strtoupper($name);
+        if (!defined($const)) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no value defined for name %s', __CLASS__, $name));
+        }
+        return constant($const);
+    }
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsRequest.php b/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsRequest.php
new file mode 100644 (file)
index 0000000..02a1530
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.LoadBalancerStatsRequest</code>
+ */
+class LoadBalancerStatsRequest extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Request stats for the next num_rpcs sent by client.
+     *
+     * Generated from protobuf field <code>int32 num_rpcs = 1;</code>
+     */
+    protected $num_rpcs = 0;
+    /**
+     * If num_rpcs have not completed within timeout_sec, return partial results.
+     *
+     * Generated from protobuf field <code>int32 timeout_sec = 2;</code>
+     */
+    protected $timeout_sec = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $num_rpcs
+     *           Request stats for the next num_rpcs sent by client.
+     *     @type int $timeout_sec
+     *           If num_rpcs have not completed within timeout_sec, return partial results.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Request stats for the next num_rpcs sent by client.
+     *
+     * Generated from protobuf field <code>int32 num_rpcs = 1;</code>
+     * @return int
+     */
+    public function getNumRpcs()
+    {
+        return $this->num_rpcs;
+    }
+
+    /**
+     * Request stats for the next num_rpcs sent by client.
+     *
+     * Generated from protobuf field <code>int32 num_rpcs = 1;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setNumRpcs($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->num_rpcs = $var;
+
+        return $this;
+    }
+
+    /**
+     * If num_rpcs have not completed within timeout_sec, return partial results.
+     *
+     * Generated from protobuf field <code>int32 timeout_sec = 2;</code>
+     * @return int
+     */
+    public function getTimeoutSec()
+    {
+        return $this->timeout_sec;
+    }
+
+    /**
+     * If num_rpcs have not completed within timeout_sec, return partial results.
+     *
+     * Generated from protobuf field <code>int32 timeout_sec = 2;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setTimeoutSec($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->timeout_sec = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsResponse.php b/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsResponse.php
new file mode 100644 (file)
index 0000000..270189e
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.LoadBalancerStatsResponse</code>
+ */
+class LoadBalancerStatsResponse extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * The number of completed RPCs for each peer.
+     *
+     * Generated from protobuf field <code>map<string, int32> rpcs_by_peer = 1;</code>
+     */
+    private $rpcs_by_peer;
+    /**
+     * The number of RPCs that failed to record a remote peer.
+     *
+     * Generated from protobuf field <code>int32 num_failures = 2;</code>
+     */
+    protected $num_failures = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type array|\Google\Protobuf\Internal\MapField $rpcs_by_peer
+     *           The number of completed RPCs for each peer.
+     *     @type int $num_failures
+     *           The number of RPCs that failed to record a remote peer.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * The number of completed RPCs for each peer.
+     *
+     * Generated from protobuf field <code>map<string, int32> rpcs_by_peer = 1;</code>
+     * @return \Google\Protobuf\Internal\MapField
+     */
+    public function getRpcsByPeer()
+    {
+        return $this->rpcs_by_peer;
+    }
+
+    /**
+     * The number of completed RPCs for each peer.
+     *
+     * Generated from protobuf field <code>map<string, int32> rpcs_by_peer = 1;</code>
+     * @param array|\Google\Protobuf\Internal\MapField $var
+     * @return $this
+     */
+    public function setRpcsByPeer($var)
+    {
+        $arr = GPBUtil::checkMapField($var, \Google\Protobuf\Internal\GPBType::STRING, \Google\Protobuf\Internal\GPBType::INT32);
+        $this->rpcs_by_peer = $arr;
+
+        return $this;
+    }
+
+    /**
+     * The number of RPCs that failed to record a remote peer.
+     *
+     * Generated from protobuf field <code>int32 num_failures = 2;</code>
+     * @return int
+     */
+    public function getNumFailures()
+    {
+        return $this->num_failures;
+    }
+
+    /**
+     * The number of RPCs that failed to record a remote peer.
+     *
+     * Generated from protobuf field <code>int32 num_failures = 2;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setNumFailures($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->num_failures = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceClient.php b/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceClient.php
new file mode 100644 (file)
index 0000000..cfbd0fd
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015-2016 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+//
+namespace Grpc\Testing;
+
+/**
+ * A service used to obtain stats for verifying LB behavior.
+ */
+class LoadBalancerStatsServiceClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * Gets the backend distribution for RPCs sent by a test client.
+     * @param \Grpc\Testing\LoadBalancerStatsRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\Testing\LoadBalancerStatsResponse
+     */
+    public function GetClientStats(\Grpc\Testing\LoadBalancerStatsRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.LoadBalancerStatsService/GetClientStats',
+        $argument,
+        ['\Grpc\Testing\LoadBalancerStatsResponse', 'decode'],
+        $metadata, $options);
+    }
+
+}
diff --git a/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceStub.php b/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceStub.php
new file mode 100644 (file)
index 0000000..529f5b0
--- /dev/null
@@ -0,0 +1,6 @@
+<?php
+// DO NOT EDIT
+namespace Grpc\Testing;
+class LoadBalancerStatsServiceStub {
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/Payload.php b/src/php/tests/interop/Grpc/Testing/Payload.php
new file mode 100644 (file)
index 0000000..65a007e
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * A block of data, to simply increase gRPC message size.
+ *
+ * Generated from protobuf message <code>grpc.testing.Payload</code>
+ */
+class Payload extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * The type of data in body.
+     *
+     * Generated from protobuf field <code>.grpc.testing.PayloadType type = 1;</code>
+     */
+    protected $type = 0;
+    /**
+     * Primary contents of payload.
+     *
+     * Generated from protobuf field <code>bytes body = 2;</code>
+     */
+    protected $body = '';
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $type
+     *           The type of data in body.
+     *     @type string $body
+     *           Primary contents of payload.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * The type of data in body.
+     *
+     * Generated from protobuf field <code>.grpc.testing.PayloadType type = 1;</code>
+     * @return int
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * The type of data in body.
+     *
+     * Generated from protobuf field <code>.grpc.testing.PayloadType type = 1;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setType($var)
+    {
+        GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class);
+        $this->type = $var;
+
+        return $this;
+    }
+
+    /**
+     * Primary contents of payload.
+     *
+     * Generated from protobuf field <code>bytes body = 2;</code>
+     * @return string
+     */
+    public function getBody()
+    {
+        return $this->body;
+    }
+
+    /**
+     * Primary contents of payload.
+     *
+     * Generated from protobuf field <code>bytes body = 2;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setBody($var)
+    {
+        GPBUtil::checkString($var, False);
+        $this->body = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/PayloadType.php b/src/php/tests/interop/Grpc/Testing/PayloadType.php
new file mode 100644 (file)
index 0000000..dc246b3
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use UnexpectedValueException;
+
+/**
+ * The type of payload that should be returned.
+ *
+ * Protobuf type <code>grpc.testing.PayloadType</code>
+ */
+class PayloadType
+{
+    /**
+     * Compressable text format.
+     *
+     * Generated from protobuf enum <code>COMPRESSABLE = 0;</code>
+     */
+    const COMPRESSABLE = 0;
+
+    private static $valueToName = [
+        self::COMPRESSABLE => 'COMPRESSABLE',
+    ];
+
+    public static function name($value)
+    {
+        if (!isset(self::$valueToName[$value])) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no name defined for value %s', __CLASS__, $value));
+        }
+        return self::$valueToName[$value];
+    }
+
+
+    public static function value($name)
+    {
+        $const = __CLASS__ . '::' . strtoupper($name);
+        if (!defined($const)) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no value defined for name %s', __CLASS__, $name));
+        }
+        return constant($const);
+    }
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/ReconnectInfo.php b/src/php/tests/interop/Grpc/Testing/ReconnectInfo.php
new file mode 100644 (file)
index 0000000..58ac838
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * For reconnect interop test only.
+ * Server tells client whether its reconnects are following the spec and the
+ * reconnect backoffs it saw.
+ *
+ * Generated from protobuf message <code>grpc.testing.ReconnectInfo</code>
+ */
+class ReconnectInfo extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>bool passed = 1;</code>
+     */
+    protected $passed = false;
+    /**
+     * Generated from protobuf field <code>repeated int32 backoff_ms = 2;</code>
+     */
+    private $backoff_ms;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type bool $passed
+     *     @type int[]|\Google\Protobuf\Internal\RepeatedField $backoff_ms
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>bool passed = 1;</code>
+     * @return bool
+     */
+    public function getPassed()
+    {
+        return $this->passed;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool passed = 1;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setPassed($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->passed = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>repeated int32 backoff_ms = 2;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
+     */
+    public function getBackoffMs()
+    {
+        return $this->backoff_ms;
+    }
+
+    /**
+     * Generated from protobuf field <code>repeated int32 backoff_ms = 2;</code>
+     * @param int[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
+     */
+    public function setBackoffMs($var)
+    {
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
+        $this->backoff_ms = $arr;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/ReconnectParams.php b/src/php/tests/interop/Grpc/Testing/ReconnectParams.php
new file mode 100644 (file)
index 0000000..599b13d
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * For reconnect interop test only.
+ * Client tells server what reconnection parameters it used.
+ *
+ * Generated from protobuf message <code>grpc.testing.ReconnectParams</code>
+ */
+class ReconnectParams extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>int32 max_reconnect_backoff_ms = 1;</code>
+     */
+    protected $max_reconnect_backoff_ms = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $max_reconnect_backoff_ms
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 max_reconnect_backoff_ms = 1;</code>
+     * @return int
+     */
+    public function getMaxReconnectBackoffMs()
+    {
+        return $this->max_reconnect_backoff_ms;
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 max_reconnect_backoff_ms = 1;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setMaxReconnectBackoffMs($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->max_reconnect_backoff_ms = $var;
+
+        return $this;
+    }
+
+}
+
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-// Contains the definitions for a metrics service and the type of metrics
-// exposed by the service.
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
 //
-// Currently, 'Gauge' (i.e a metric that represents the measured value of
-// something at an instant of time) is the only metric type supported by the
-// service.
 namespace Grpc\Testing;
 
 /**
+ * A service used to control reconnect server.
  */
-class MetricsServiceClient extends \Grpc\BaseStub {
+class ReconnectServiceClient extends \Grpc\BaseStub {
 
     /**
      * @param string $hostname hostname
@@ -38,31 +36,30 @@ class MetricsServiceClient extends \Grpc\BaseStub {
     }
 
     /**
-     * Returns the values of all the gauges that are currently being maintained by
-     * the service
-     * @param \Grpc\Testing\EmptyMessage $argument input argument
+     * @param \Grpc\Testing\ReconnectParams $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\EmptyMessage
      */
-    public function GetAllGauges(\Grpc\Testing\EmptyMessage $argument,
+    public function Start(\Grpc\Testing\ReconnectParams $argument,
       $metadata = [], $options = []) {
-        return $this->_serverStreamRequest('/grpc.testing.MetricsService/GetAllGauges',
+        return $this->_simpleRequest('/grpc.testing.ReconnectService/Start',
         $argument,
-        ['\Grpc\Testing\GaugeResponse', 'decode'],
+        ['\Grpc\Testing\EmptyMessage', 'decode'],
         $metadata, $options);
     }
 
     /**
-     * Returns the value of one gauge
-     * @param \Grpc\Testing\GaugeRequest $argument input argument
+     * @param \Grpc\Testing\EmptyMessage $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\ReconnectInfo
      */
-    public function GetGauge(\Grpc\Testing\GaugeRequest $argument,
+    public function Stop(\Grpc\Testing\EmptyMessage $argument,
       $metadata = [], $options = []) {
-        return $this->_simpleRequest('/grpc.testing.MetricsService/GetGauge',
+        return $this->_simpleRequest('/grpc.testing.ReconnectService/Stop',
         $argument,
-        ['\Grpc\Testing\GaugeResponse', 'decode'],
+        ['\Grpc\Testing\ReconnectInfo', 'decode'],
         $metadata, $options);
     }
 
diff --git a/src/php/tests/interop/Grpc/Testing/ResponseParameters.php b/src/php/tests/interop/Grpc/Testing/ResponseParameters.php
new file mode 100644 (file)
index 0000000..4703493
--- /dev/null
@@ -0,0 +1,151 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Configuration for a particular response.
+ *
+ * Generated from protobuf message <code>grpc.testing.ResponseParameters</code>
+ */
+class ResponseParameters extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Desired payload sizes in responses from the server.
+     *
+     * Generated from protobuf field <code>int32 size = 1;</code>
+     */
+    protected $size = 0;
+    /**
+     * Desired interval between consecutive responses in the response stream in
+     * microseconds.
+     *
+     * Generated from protobuf field <code>int32 interval_us = 2;</code>
+     */
+    protected $interval_us = 0;
+    /**
+     * Whether to request the server to compress the response. This field is
+     * "nullable" in order to interoperate seamlessly with clients not able to
+     * implement the full compression tests by introspecting the call to verify
+     * the response's compression status.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue compressed = 3;</code>
+     */
+    protected $compressed = null;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $size
+     *           Desired payload sizes in responses from the server.
+     *     @type int $interval_us
+     *           Desired interval between consecutive responses in the response stream in
+     *           microseconds.
+     *     @type \Grpc\Testing\BoolValue $compressed
+     *           Whether to request the server to compress the response. This field is
+     *           "nullable" in order to interoperate seamlessly with clients not able to
+     *           implement the full compression tests by introspecting the call to verify
+     *           the response's compression status.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Desired payload sizes in responses from the server.
+     *
+     * Generated from protobuf field <code>int32 size = 1;</code>
+     * @return int
+     */
+    public function getSize()
+    {
+        return $this->size;
+    }
+
+    /**
+     * Desired payload sizes in responses from the server.
+     *
+     * Generated from protobuf field <code>int32 size = 1;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setSize($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->size = $var;
+
+        return $this;
+    }
+
+    /**
+     * Desired interval between consecutive responses in the response stream in
+     * microseconds.
+     *
+     * Generated from protobuf field <code>int32 interval_us = 2;</code>
+     * @return int
+     */
+    public function getIntervalUs()
+    {
+        return $this->interval_us;
+    }
+
+    /**
+     * Desired interval between consecutive responses in the response stream in
+     * microseconds.
+     *
+     * Generated from protobuf field <code>int32 interval_us = 2;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setIntervalUs($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->interval_us = $var;
+
+        return $this;
+    }
+
+    /**
+     * Whether to request the server to compress the response. This field is
+     * "nullable" in order to interoperate seamlessly with clients not able to
+     * implement the full compression tests by introspecting the call to verify
+     * the response's compression status.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue compressed = 3;</code>
+     * @return \Grpc\Testing\BoolValue
+     */
+    public function getCompressed()
+    {
+        return $this->compressed;
+    }
+
+    /**
+     * Whether to request the server to compress the response. This field is
+     * "nullable" in order to interoperate seamlessly with clients not able to
+     * implement the full compression tests by introspecting the call to verify
+     * the response's compression status.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue compressed = 3;</code>
+     * @param \Grpc\Testing\BoolValue $var
+     * @return $this
+     */
+    public function setCompressed($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class);
+        $this->compressed = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/SimpleRequest.php b/src/php/tests/interop/Grpc/Testing/SimpleRequest.php
new file mode 100644 (file)
index 0000000..9539365
--- /dev/null
@@ -0,0 +1,389 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Unary request.
+ *
+ * Generated from protobuf message <code>grpc.testing.SimpleRequest</code>
+ */
+class SimpleRequest extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Desired payload type in the response from the server.
+     * If response_type is RANDOM, server randomly chooses one from other formats.
+     *
+     * Generated from protobuf field <code>.grpc.testing.PayloadType response_type = 1;</code>
+     */
+    protected $response_type = 0;
+    /**
+     * Desired payload size in the response from the server.
+     *
+     * Generated from protobuf field <code>int32 response_size = 2;</code>
+     */
+    protected $response_size = 0;
+    /**
+     * Optional input payload sent along with the request.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 3;</code>
+     */
+    protected $payload = null;
+    /**
+     * Whether SimpleResponse should include username.
+     *
+     * Generated from protobuf field <code>bool fill_username = 4;</code>
+     */
+    protected $fill_username = false;
+    /**
+     * Whether SimpleResponse should include OAuth scope.
+     *
+     * Generated from protobuf field <code>bool fill_oauth_scope = 5;</code>
+     */
+    protected $fill_oauth_scope = false;
+    /**
+     * Whether to request the server to compress the response. This field is
+     * "nullable" in order to interoperate seamlessly with clients not able to
+     * implement the full compression tests by introspecting the call to verify
+     * the response's compression status.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue response_compressed = 6;</code>
+     */
+    protected $response_compressed = null;
+    /**
+     * Whether server should return a given status
+     *
+     * Generated from protobuf field <code>.grpc.testing.EchoStatus response_status = 7;</code>
+     */
+    protected $response_status = null;
+    /**
+     * Whether the server should expect this request to be compressed.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue expect_compressed = 8;</code>
+     */
+    protected $expect_compressed = null;
+    /**
+     * Whether SimpleResponse should include server_id.
+     *
+     * Generated from protobuf field <code>bool fill_server_id = 9;</code>
+     */
+    protected $fill_server_id = false;
+    /**
+     * Whether SimpleResponse should include grpclb_route_type.
+     *
+     * Generated from protobuf field <code>bool fill_grpclb_route_type = 10;</code>
+     */
+    protected $fill_grpclb_route_type = false;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $response_type
+     *           Desired payload type in the response from the server.
+     *           If response_type is RANDOM, server randomly chooses one from other formats.
+     *     @type int $response_size
+     *           Desired payload size in the response from the server.
+     *     @type \Grpc\Testing\Payload $payload
+     *           Optional input payload sent along with the request.
+     *     @type bool $fill_username
+     *           Whether SimpleResponse should include username.
+     *     @type bool $fill_oauth_scope
+     *           Whether SimpleResponse should include OAuth scope.
+     *     @type \Grpc\Testing\BoolValue $response_compressed
+     *           Whether to request the server to compress the response. This field is
+     *           "nullable" in order to interoperate seamlessly with clients not able to
+     *           implement the full compression tests by introspecting the call to verify
+     *           the response's compression status.
+     *     @type \Grpc\Testing\EchoStatus $response_status
+     *           Whether server should return a given status
+     *     @type \Grpc\Testing\BoolValue $expect_compressed
+     *           Whether the server should expect this request to be compressed.
+     *     @type bool $fill_server_id
+     *           Whether SimpleResponse should include server_id.
+     *     @type bool $fill_grpclb_route_type
+     *           Whether SimpleResponse should include grpclb_route_type.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Desired payload type in the response from the server.
+     * If response_type is RANDOM, server randomly chooses one from other formats.
+     *
+     * Generated from protobuf field <code>.grpc.testing.PayloadType response_type = 1;</code>
+     * @return int
+     */
+    public function getResponseType()
+    {
+        return $this->response_type;
+    }
+
+    /**
+     * Desired payload type in the response from the server.
+     * If response_type is RANDOM, server randomly chooses one from other formats.
+     *
+     * Generated from protobuf field <code>.grpc.testing.PayloadType response_type = 1;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setResponseType($var)
+    {
+        GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class);
+        $this->response_type = $var;
+
+        return $this;
+    }
+
+    /**
+     * Desired payload size in the response from the server.
+     *
+     * Generated from protobuf field <code>int32 response_size = 2;</code>
+     * @return int
+     */
+    public function getResponseSize()
+    {
+        return $this->response_size;
+    }
+
+    /**
+     * Desired payload size in the response from the server.
+     *
+     * Generated from protobuf field <code>int32 response_size = 2;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setResponseSize($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->response_size = $var;
+
+        return $this;
+    }
+
+    /**
+     * Optional input payload sent along with the request.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 3;</code>
+     * @return \Grpc\Testing\Payload
+     */
+    public function getPayload()
+    {
+        return $this->payload;
+    }
+
+    /**
+     * Optional input payload sent along with the request.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 3;</code>
+     * @param \Grpc\Testing\Payload $var
+     * @return $this
+     */
+    public function setPayload($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class);
+        $this->payload = $var;
+
+        return $this;
+    }
+
+    /**
+     * Whether SimpleResponse should include username.
+     *
+     * Generated from protobuf field <code>bool fill_username = 4;</code>
+     * @return bool
+     */
+    public function getFillUsername()
+    {
+        return $this->fill_username;
+    }
+
+    /**
+     * Whether SimpleResponse should include username.
+     *
+     * Generated from protobuf field <code>bool fill_username = 4;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setFillUsername($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->fill_username = $var;
+
+        return $this;
+    }
+
+    /**
+     * Whether SimpleResponse should include OAuth scope.
+     *
+     * Generated from protobuf field <code>bool fill_oauth_scope = 5;</code>
+     * @return bool
+     */
+    public function getFillOauthScope()
+    {
+        return $this->fill_oauth_scope;
+    }
+
+    /**
+     * Whether SimpleResponse should include OAuth scope.
+     *
+     * Generated from protobuf field <code>bool fill_oauth_scope = 5;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setFillOauthScope($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->fill_oauth_scope = $var;
+
+        return $this;
+    }
+
+    /**
+     * Whether to request the server to compress the response. This field is
+     * "nullable" in order to interoperate seamlessly with clients not able to
+     * implement the full compression tests by introspecting the call to verify
+     * the response's compression status.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue response_compressed = 6;</code>
+     * @return \Grpc\Testing\BoolValue
+     */
+    public function getResponseCompressed()
+    {
+        return $this->response_compressed;
+    }
+
+    /**
+     * Whether to request the server to compress the response. This field is
+     * "nullable" in order to interoperate seamlessly with clients not able to
+     * implement the full compression tests by introspecting the call to verify
+     * the response's compression status.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue response_compressed = 6;</code>
+     * @param \Grpc\Testing\BoolValue $var
+     * @return $this
+     */
+    public function setResponseCompressed($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class);
+        $this->response_compressed = $var;
+
+        return $this;
+    }
+
+    /**
+     * Whether server should return a given status
+     *
+     * Generated from protobuf field <code>.grpc.testing.EchoStatus response_status = 7;</code>
+     * @return \Grpc\Testing\EchoStatus
+     */
+    public function getResponseStatus()
+    {
+        return $this->response_status;
+    }
+
+    /**
+     * Whether server should return a given status
+     *
+     * Generated from protobuf field <code>.grpc.testing.EchoStatus response_status = 7;</code>
+     * @param \Grpc\Testing\EchoStatus $var
+     * @return $this
+     */
+    public function setResponseStatus($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\EchoStatus::class);
+        $this->response_status = $var;
+
+        return $this;
+    }
+
+    /**
+     * Whether the server should expect this request to be compressed.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue expect_compressed = 8;</code>
+     * @return \Grpc\Testing\BoolValue
+     */
+    public function getExpectCompressed()
+    {
+        return $this->expect_compressed;
+    }
+
+    /**
+     * Whether the server should expect this request to be compressed.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue expect_compressed = 8;</code>
+     * @param \Grpc\Testing\BoolValue $var
+     * @return $this
+     */
+    public function setExpectCompressed($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class);
+        $this->expect_compressed = $var;
+
+        return $this;
+    }
+
+    /**
+     * Whether SimpleResponse should include server_id.
+     *
+     * Generated from protobuf field <code>bool fill_server_id = 9;</code>
+     * @return bool
+     */
+    public function getFillServerId()
+    {
+        return $this->fill_server_id;
+    }
+
+    /**
+     * Whether SimpleResponse should include server_id.
+     *
+     * Generated from protobuf field <code>bool fill_server_id = 9;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setFillServerId($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->fill_server_id = $var;
+
+        return $this;
+    }
+
+    /**
+     * Whether SimpleResponse should include grpclb_route_type.
+     *
+     * Generated from protobuf field <code>bool fill_grpclb_route_type = 10;</code>
+     * @return bool
+     */
+    public function getFillGrpclbRouteType()
+    {
+        return $this->fill_grpclb_route_type;
+    }
+
+    /**
+     * Whether SimpleResponse should include grpclb_route_type.
+     *
+     * Generated from protobuf field <code>bool fill_grpclb_route_type = 10;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setFillGrpclbRouteType($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->fill_grpclb_route_type = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/SimpleResponse.php b/src/php/tests/interop/Grpc/Testing/SimpleResponse.php
new file mode 100644 (file)
index 0000000..7121fc2
--- /dev/null
@@ -0,0 +1,245 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Unary response, as configured by the request.
+ *
+ * Generated from protobuf message <code>grpc.testing.SimpleResponse</code>
+ */
+class SimpleResponse extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Payload to increase message size.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
+     */
+    protected $payload = null;
+    /**
+     * The user the request came from, for verifying authentication was
+     * successful when the client expected it.
+     *
+     * Generated from protobuf field <code>string username = 2;</code>
+     */
+    protected $username = '';
+    /**
+     * OAuth scope.
+     *
+     * Generated from protobuf field <code>string oauth_scope = 3;</code>
+     */
+    protected $oauth_scope = '';
+    /**
+     * Server ID. This must be unique among different server instances,
+     * but the same across all RPC's made to a particular server instance.
+     *
+     * Generated from protobuf field <code>string server_id = 4;</code>
+     */
+    protected $server_id = '';
+    /**
+     * gRPCLB Path.
+     *
+     * Generated from protobuf field <code>.grpc.testing.GrpclbRouteType grpclb_route_type = 5;</code>
+     */
+    protected $grpclb_route_type = 0;
+    /**
+     * Server hostname.
+     *
+     * Generated from protobuf field <code>string hostname = 6;</code>
+     */
+    protected $hostname = '';
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\Payload $payload
+     *           Payload to increase message size.
+     *     @type string $username
+     *           The user the request came from, for verifying authentication was
+     *           successful when the client expected it.
+     *     @type string $oauth_scope
+     *           OAuth scope.
+     *     @type string $server_id
+     *           Server ID. This must be unique among different server instances,
+     *           but the same across all RPC's made to a particular server instance.
+     *     @type int $grpclb_route_type
+     *           gRPCLB Path.
+     *     @type string $hostname
+     *           Server hostname.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Payload to increase message size.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
+     * @return \Grpc\Testing\Payload
+     */
+    public function getPayload()
+    {
+        return $this->payload;
+    }
+
+    /**
+     * Payload to increase message size.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
+     * @param \Grpc\Testing\Payload $var
+     * @return $this
+     */
+    public function setPayload($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class);
+        $this->payload = $var;
+
+        return $this;
+    }
+
+    /**
+     * The user the request came from, for verifying authentication was
+     * successful when the client expected it.
+     *
+     * Generated from protobuf field <code>string username = 2;</code>
+     * @return string
+     */
+    public function getUsername()
+    {
+        return $this->username;
+    }
+
+    /**
+     * The user the request came from, for verifying authentication was
+     * successful when the client expected it.
+     *
+     * Generated from protobuf field <code>string username = 2;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setUsername($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->username = $var;
+
+        return $this;
+    }
+
+    /**
+     * OAuth scope.
+     *
+     * Generated from protobuf field <code>string oauth_scope = 3;</code>
+     * @return string
+     */
+    public function getOauthScope()
+    {
+        return $this->oauth_scope;
+    }
+
+    /**
+     * OAuth scope.
+     *
+     * Generated from protobuf field <code>string oauth_scope = 3;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setOauthScope($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->oauth_scope = $var;
+
+        return $this;
+    }
+
+    /**
+     * Server ID. This must be unique among different server instances,
+     * but the same across all RPC's made to a particular server instance.
+     *
+     * Generated from protobuf field <code>string server_id = 4;</code>
+     * @return string
+     */
+    public function getServerId()
+    {
+        return $this->server_id;
+    }
+
+    /**
+     * Server ID. This must be unique among different server instances,
+     * but the same across all RPC's made to a particular server instance.
+     *
+     * Generated from protobuf field <code>string server_id = 4;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setServerId($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->server_id = $var;
+
+        return $this;
+    }
+
+    /**
+     * gRPCLB Path.
+     *
+     * Generated from protobuf field <code>.grpc.testing.GrpclbRouteType grpclb_route_type = 5;</code>
+     * @return int
+     */
+    public function getGrpclbRouteType()
+    {
+        return $this->grpclb_route_type;
+    }
+
+    /**
+     * gRPCLB Path.
+     *
+     * Generated from protobuf field <code>.grpc.testing.GrpclbRouteType grpclb_route_type = 5;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setGrpclbRouteType($var)
+    {
+        GPBUtil::checkEnum($var, \Grpc\Testing\GrpclbRouteType::class);
+        $this->grpclb_route_type = $var;
+
+        return $this;
+    }
+
+    /**
+     * Server hostname.
+     *
+     * Generated from protobuf field <code>string hostname = 6;</code>
+     * @return string
+     */
+    public function getHostname()
+    {
+        return $this->hostname;
+    }
+
+    /**
+     * Server hostname.
+     *
+     * Generated from protobuf field <code>string hostname = 6;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setHostname($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->hostname = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/StreamingInputCallRequest.php b/src/php/tests/interop/Grpc/Testing/StreamingInputCallRequest.php
new file mode 100644 (file)
index 0000000..00c754b
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Client-streaming request.
+ *
+ * Generated from protobuf message <code>grpc.testing.StreamingInputCallRequest</code>
+ */
+class StreamingInputCallRequest extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Optional input payload sent along with the request.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
+     */
+    protected $payload = null;
+    /**
+     * Whether the server should expect this request to be compressed. This field
+     * is "nullable" in order to interoperate seamlessly with servers not able to
+     * implement the full compression tests by introspecting the call to verify
+     * the request's compression status.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue expect_compressed = 2;</code>
+     */
+    protected $expect_compressed = null;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\Payload $payload
+     *           Optional input payload sent along with the request.
+     *     @type \Grpc\Testing\BoolValue $expect_compressed
+     *           Whether the server should expect this request to be compressed. This field
+     *           is "nullable" in order to interoperate seamlessly with servers not able to
+     *           implement the full compression tests by introspecting the call to verify
+     *           the request's compression status.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Optional input payload sent along with the request.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
+     * @return \Grpc\Testing\Payload
+     */
+    public function getPayload()
+    {
+        return $this->payload;
+    }
+
+    /**
+     * Optional input payload sent along with the request.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
+     * @param \Grpc\Testing\Payload $var
+     * @return $this
+     */
+    public function setPayload($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class);
+        $this->payload = $var;
+
+        return $this;
+    }
+
+    /**
+     * Whether the server should expect this request to be compressed. This field
+     * is "nullable" in order to interoperate seamlessly with servers not able to
+     * implement the full compression tests by introspecting the call to verify
+     * the request's compression status.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue expect_compressed = 2;</code>
+     * @return \Grpc\Testing\BoolValue
+     */
+    public function getExpectCompressed()
+    {
+        return $this->expect_compressed;
+    }
+
+    /**
+     * Whether the server should expect this request to be compressed. This field
+     * is "nullable" in order to interoperate seamlessly with servers not able to
+     * implement the full compression tests by introspecting the call to verify
+     * the request's compression status.
+     *
+     * Generated from protobuf field <code>.grpc.testing.BoolValue expect_compressed = 2;</code>
+     * @param \Grpc\Testing\BoolValue $var
+     * @return $this
+     */
+    public function setExpectCompressed($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class);
+        $this->expect_compressed = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/StreamingInputCallResponse.php b/src/php/tests/interop/Grpc/Testing/StreamingInputCallResponse.php
new file mode 100644 (file)
index 0000000..f7ff87c
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Client-streaming response.
+ *
+ * Generated from protobuf message <code>grpc.testing.StreamingInputCallResponse</code>
+ */
+class StreamingInputCallResponse extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Aggregated size of payloads received from the client.
+     *
+     * Generated from protobuf field <code>int32 aggregated_payload_size = 1;</code>
+     */
+    protected $aggregated_payload_size = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $aggregated_payload_size
+     *           Aggregated size of payloads received from the client.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Aggregated size of payloads received from the client.
+     *
+     * Generated from protobuf field <code>int32 aggregated_payload_size = 1;</code>
+     * @return int
+     */
+    public function getAggregatedPayloadSize()
+    {
+        return $this->aggregated_payload_size;
+    }
+
+    /**
+     * Aggregated size of payloads received from the client.
+     *
+     * Generated from protobuf field <code>int32 aggregated_payload_size = 1;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setAggregatedPayloadSize($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->aggregated_payload_size = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/StreamingOutputCallRequest.php b/src/php/tests/interop/Grpc/Testing/StreamingOutputCallRequest.php
new file mode 100644 (file)
index 0000000..552e96d
--- /dev/null
@@ -0,0 +1,181 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Server-streaming request.
+ *
+ * Generated from protobuf message <code>grpc.testing.StreamingOutputCallRequest</code>
+ */
+class StreamingOutputCallRequest extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Desired payload type in the response from the server.
+     * If response_type is RANDOM, the payload from each response in the stream
+     * might be of different types. This is to simulate a mixed type of payload
+     * stream.
+     *
+     * Generated from protobuf field <code>.grpc.testing.PayloadType response_type = 1;</code>
+     */
+    protected $response_type = 0;
+    /**
+     * Configuration for each expected response message.
+     *
+     * Generated from protobuf field <code>repeated .grpc.testing.ResponseParameters response_parameters = 2;</code>
+     */
+    private $response_parameters;
+    /**
+     * Optional input payload sent along with the request.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 3;</code>
+     */
+    protected $payload = null;
+    /**
+     * Whether server should return a given status
+     *
+     * Generated from protobuf field <code>.grpc.testing.EchoStatus response_status = 7;</code>
+     */
+    protected $response_status = null;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $response_type
+     *           Desired payload type in the response from the server.
+     *           If response_type is RANDOM, the payload from each response in the stream
+     *           might be of different types. This is to simulate a mixed type of payload
+     *           stream.
+     *     @type \Grpc\Testing\ResponseParameters[]|\Google\Protobuf\Internal\RepeatedField $response_parameters
+     *           Configuration for each expected response message.
+     *     @type \Grpc\Testing\Payload $payload
+     *           Optional input payload sent along with the request.
+     *     @type \Grpc\Testing\EchoStatus $response_status
+     *           Whether server should return a given status
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Desired payload type in the response from the server.
+     * If response_type is RANDOM, the payload from each response in the stream
+     * might be of different types. This is to simulate a mixed type of payload
+     * stream.
+     *
+     * Generated from protobuf field <code>.grpc.testing.PayloadType response_type = 1;</code>
+     * @return int
+     */
+    public function getResponseType()
+    {
+        return $this->response_type;
+    }
+
+    /**
+     * Desired payload type in the response from the server.
+     * If response_type is RANDOM, the payload from each response in the stream
+     * might be of different types. This is to simulate a mixed type of payload
+     * stream.
+     *
+     * Generated from protobuf field <code>.grpc.testing.PayloadType response_type = 1;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setResponseType($var)
+    {
+        GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class);
+        $this->response_type = $var;
+
+        return $this;
+    }
+
+    /**
+     * Configuration for each expected response message.
+     *
+     * Generated from protobuf field <code>repeated .grpc.testing.ResponseParameters response_parameters = 2;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
+     */
+    public function getResponseParameters()
+    {
+        return $this->response_parameters;
+    }
+
+    /**
+     * Configuration for each expected response message.
+     *
+     * Generated from protobuf field <code>repeated .grpc.testing.ResponseParameters response_parameters = 2;</code>
+     * @param \Grpc\Testing\ResponseParameters[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
+     */
+    public function setResponseParameters($var)
+    {
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ResponseParameters::class);
+        $this->response_parameters = $arr;
+
+        return $this;
+    }
+
+    /**
+     * Optional input payload sent along with the request.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 3;</code>
+     * @return \Grpc\Testing\Payload
+     */
+    public function getPayload()
+    {
+        return $this->payload;
+    }
+
+    /**
+     * Optional input payload sent along with the request.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 3;</code>
+     * @param \Grpc\Testing\Payload $var
+     * @return $this
+     */
+    public function setPayload($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class);
+        $this->payload = $var;
+
+        return $this;
+    }
+
+    /**
+     * Whether server should return a given status
+     *
+     * Generated from protobuf field <code>.grpc.testing.EchoStatus response_status = 7;</code>
+     * @return \Grpc\Testing\EchoStatus
+     */
+    public function getResponseStatus()
+    {
+        return $this->response_status;
+    }
+
+    /**
+     * Whether server should return a given status
+     *
+     * Generated from protobuf field <code>.grpc.testing.EchoStatus response_status = 7;</code>
+     * @param \Grpc\Testing\EchoStatus $var
+     * @return $this
+     */
+    public function setResponseStatus($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\EchoStatus::class);
+        $this->response_status = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/StreamingOutputCallResponse.php b/src/php/tests/interop/Grpc/Testing/StreamingOutputCallResponse.php
new file mode 100644 (file)
index 0000000..b28b906
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Server-streaming response, as configured by the request and parameters.
+ *
+ * Generated from protobuf message <code>grpc.testing.StreamingOutputCallResponse</code>
+ */
+class StreamingOutputCallResponse extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Payload to increase response size.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
+     */
+    protected $payload = null;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\Payload $payload
+     *           Payload to increase response size.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Payload to increase response size.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
+     * @return \Grpc\Testing\Payload
+     */
+    public function getPayload()
+    {
+        return $this->payload;
+    }
+
+    /**
+     * Payload to increase response size.
+     *
+     * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
+     * @param \Grpc\Testing\Payload $var
+     * @return $this
+     */
+    public function setPayload($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class);
+        $this->payload = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/interop/Grpc/Testing/TestServiceClient.php b/src/php/tests/interop/Grpc/Testing/TestServiceClient.php
new file mode 100644 (file)
index 0000000..770c609
--- /dev/null
@@ -0,0 +1,160 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015-2016 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+//
+namespace Grpc\Testing;
+
+/**
+ * A simple service to test the various types of RPCs and experiment with
+ * performance with various types of payload.
+ */
+class TestServiceClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * One empty request followed by one empty response.
+     * @param \Grpc\Testing\EmptyMessage $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\Testing\EmptyMessage
+     */
+    public function EmptyCall(\Grpc\Testing\EmptyMessage $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.TestService/EmptyCall',
+        $argument,
+        ['\Grpc\Testing\EmptyMessage', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * One request followed by one response.
+     * @param \Grpc\Testing\SimpleRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\Testing\SimpleResponse
+     */
+    public function UnaryCall(\Grpc\Testing\SimpleRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.TestService/UnaryCall',
+        $argument,
+        ['\Grpc\Testing\SimpleResponse', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * One request followed by one response. Response has cache control
+     * headers set such that a caching HTTP proxy (such as GFE) can
+     * satisfy subsequent requests.
+     * @param \Grpc\Testing\SimpleRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\Testing\SimpleResponse
+     */
+    public function CacheableUnaryCall(\Grpc\Testing\SimpleRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.TestService/CacheableUnaryCall',
+        $argument,
+        ['\Grpc\Testing\SimpleResponse', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * One request followed by a sequence of responses (streamed download).
+     * The server returns the payload with client desired type and sizes.
+     * @param \Grpc\Testing\StreamingOutputCallRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\Testing\StreamingOutputCallResponse
+     */
+    public function StreamingOutputCall(\Grpc\Testing\StreamingOutputCallRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_serverStreamRequest('/grpc.testing.TestService/StreamingOutputCall',
+        $argument,
+        ['\Grpc\Testing\StreamingOutputCallResponse', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * A sequence of requests followed by one response (streamed upload).
+     * The server returns the aggregated size of client payload as the result.
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\Testing\StreamingInputCallResponse
+     */
+    public function StreamingInputCall($metadata = [], $options = []) {
+        return $this->_clientStreamRequest('/grpc.testing.TestService/StreamingInputCall',
+        ['\Grpc\Testing\StreamingInputCallResponse','decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * A sequence of requests with each request served by the server immediately.
+     * As one request could lead to multiple responses, this interface
+     * demonstrates the idea of full duplexing.
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\Testing\StreamingOutputCallResponse
+     */
+    public function FullDuplexCall($metadata = [], $options = []) {
+        return $this->_bidiRequest('/grpc.testing.TestService/FullDuplexCall',
+        ['\Grpc\Testing\StreamingOutputCallResponse','decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * A sequence of requests followed by a sequence of responses.
+     * The server buffers all the client requests and then serves them in order. A
+     * stream of responses are returned to the client when the server starts with
+     * first request.
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\Testing\StreamingOutputCallResponse
+     */
+    public function HalfDuplexCall($metadata = [], $options = []) {
+        return $this->_bidiRequest('/grpc.testing.TestService/HalfDuplexCall',
+        ['\Grpc\Testing\StreamingOutputCallResponse','decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * The test server will not implement this method. It will be used
+     * to test the behavior when clients call unimplemented methods.
+     * @param \Grpc\Testing\EmptyMessage $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\Testing\EmptyMessage
+     */
+    public function UnimplementedCall(\Grpc\Testing\EmptyMessage $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.TestService/UnimplementedCall',
+        $argument,
+        ['\Grpc\Testing\EmptyMessage', 'decode'],
+        $metadata, $options);
+    }
+
+}
@@ -2,7 +2,7 @@
 // GENERATED CODE -- DO NOT EDIT!
 
 // Original file comments:
-// Copyright 2015 gRPC authors.
+// Copyright 2015-2016 gRPC authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+//
 namespace Grpc\Testing;
 
 /**
+ * A simple service NOT implemented at servers so clients can test for
+ * that case.
  */
-class UnimplementedEchoServiceClient extends \Grpc\BaseStub {
+class UnimplementedServiceClient extends \Grpc\BaseStub {
 
     /**
      * @param string $hostname hostname
@@ -32,15 +37,17 @@ class UnimplementedEchoServiceClient extends \Grpc\BaseStub {
     }
 
     /**
-     * @param \Grpc\Testing\EchoRequest $argument input argument
+     * A call that no server should implement
+     * @param \Grpc\Testing\EmptyMessage $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\EmptyMessage
      */
-    public function Unimplemented(\Grpc\Testing\EchoRequest $argument,
+    public function UnimplementedCall(\Grpc\Testing\EmptyMessage $argument,
       $metadata = [], $options = []) {
-        return $this->_simpleRequest('/grpc.testing.UnimplementedEchoService/Unimplemented',
+        return $this->_simpleRequest('/grpc.testing.UnimplementedService/UnimplementedCall',
         $argument,
-        ['\Grpc\Testing\EchoResponse', 'decode'],
+        ['\Grpc\Testing\EmptyMessage', 'decode'],
         $metadata, $options);
     }
 
index e475047..f6ae683 100755 (executable)
@@ -117,6 +117,53 @@ function performLargeUnary($stub, $fillUsername = false,
 }
 
 /**
+ * Run the client_compressed_unary test.
+ *
+ * @param $stub Stub object that has service methods
+ */
+function clientCompressedUnary($stub)
+{
+    $request_len = 271828;
+    $response_len = 314159;
+    $falseBoolValue = new Grpc\Testing\BoolValue(['value' => false]);
+    $trueBoolValue = new Grpc\Testing\BoolValue(['value' => true]);
+    // 1. Probing for compression-checks support
+    $payload = new Grpc\Testing\Payload([
+        'body' => str_repeat("\0", $request_len),
+    ]);
+    $request = new Grpc\Testing\SimpleRequest([
+        'payload' => $payload,
+        'response_size' => $response_len,
+        'expect_compressed' => $trueBoolValue, // lie
+    ]);
+    list($result, $status) = $stub->UnaryCall($request, [], [])->wait();
+    hardAssert(
+        $status->code === GRPC\STATUS_INVALID_ARGUMENT,
+        'Received unexpected UnaryCall status code: ' .
+            $status->code
+    );
+    // 2. with/without compressed message
+    foreach ([true, false] as $compression) {
+        $request->setExpectCompressed($compression ? $trueBoolValue : $falseBoolValue);
+        $metadata = $compression ? [
+            'grpc-internal-encoding-request' => ['gzip'],
+        ] : [];
+        list($result, $status) = $stub->UnaryCall($request, $metadata, [])->wait();
+        hardAssertIfStatusOk($status);
+        hardAssert($result !== null, 'Call returned a null response');
+        $payload = $result->getPayload();
+        hardAssert(
+            strlen($payload->getBody()) === $response_len,
+            'Payload had the wrong length'
+        );
+        hardAssert(
+            $payload->getBody() === str_repeat("\0", $response_len),
+            'Payload had the wrong content'
+        );
+    }
+}
+
+/**
  * Run the service account credentials auth test.
  *
  * @param $stub Stub object that has service methods
@@ -257,6 +304,68 @@ function clientStreaming($stub)
 }
 
 /**
+ * Run the client_compressed_streaming test.
+ *
+ * @param $stub Stub object that has service methods
+ */
+function clientCompressedStreaming($stub)
+{
+    $request_len = 27182;
+    $request2_len = 45904;
+    $response_len = 73086;
+    $falseBoolValue = new Grpc\Testing\BoolValue(['value' => false]);
+    $trueBoolValue = new Grpc\Testing\BoolValue(['value' => true]);
+
+    // 1. Probing for compression-checks support
+
+    $payload = new Grpc\Testing\Payload([
+        'body' => str_repeat("\0", $request_len),
+    ]);
+    $request = new Grpc\Testing\StreamingInputCallRequest([
+        'payload' => $payload,
+        'expect_compressed' => $trueBoolValue, // lie
+    ]);
+
+    $call = $stub->StreamingInputCall();
+    $call->write($request);
+    list($result, $status) = $call->wait();
+    hardAssert(
+        $status->code === GRPC\STATUS_INVALID_ARGUMENT,
+        'Received unexpected StreamingInputCall status code: ' .
+            $status->code
+    );
+
+    // 2. write compressed message
+
+    $call = $stub->StreamingInputCall([
+        'grpc-internal-encoding-request' => ['gzip'],
+    ]);
+    $request->setExpectCompressed($trueBoolValue);
+    $call->write($request);
+
+    // 3. write uncompressed message
+
+    $payload2 = new Grpc\Testing\Payload([
+        'body' => str_repeat("\0", $request2_len),
+    ]);
+    $request->setPayload($payload2);
+    $request->setExpectCompressed($falseBoolValue);
+    $call->write($request, [
+        'flags' => 0x02 // GRPC_WRITE_NO_COMPRESS
+    ]);
+
+    // 4. verify response
+
+    list($result, $status) = $call->wait();
+
+    hardAssertIfStatusOk($status);
+    hardAssert(
+        $result->getAggregatedPayloadSize() === $response_len,
+        'aggregated_payload_size was incorrect'
+    );
+}
+
+/**
  * Run the server_streaming test.
  *
  * @param $stub Stub object that has service methods.
@@ -673,6 +782,12 @@ function interop_main($args, $stub = false)
         case 'per_rpc_creds':
             perRpcCreds($stub, $args);
             break;
+        case 'client_compressed_unary':
+            clientCompressedUnary($stub);
+            break;
+        case 'client_compressed_streaming':
+            clientCompressedStreaming($stub);
+            break;
         default:
             echo "Unsupported test case $test_case\n";
             exit(1);
diff --git a/src/php/tests/interop/xds_client.php b/src/php/tests/interop/xds_client.php
new file mode 100644 (file)
index 0000000..6e967d2
--- /dev/null
@@ -0,0 +1,158 @@
+<?php
+/*
+ *
+ * Copyright 2020 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This is the PHP xDS Interop test client. This script is meant to be run by
+ * the main xDS Interep test runner "run_xds_tests.py", not to be run
+ * by itself standalone.
+ */
+$autoload_path = realpath(dirname(__FILE__).'/../../vendor/autoload.php');
+require_once $autoload_path;
+
+// The main xds interop test runner will ping this service to ask for
+// the stats of the distribution of the backends, for the next X rpcs.
+class LoadBalancerStatsService
+    extends \Grpc\Testing\LoadBalancerStatsServiceStub
+{
+    function getClientStats(\Grpc\Testing\LoadBalancerStatsRequest $request) {
+        $num_rpcs = $request->getNumRpcs();
+        $timeout_sec = $request->getTimeoutSec();
+        $rpcs_by_peer = [];
+        $num_failures = $num_rpcs;
+
+        // Heavy limitation now: the server is blocking, until all
+        // the necessary num_rpcs are finished, or timeout is reached
+        global $client_thread;
+        $start_id = count($client_thread->results) + 1;
+        $end_id = $start_id + $num_rpcs;
+        $now = hrtime(true);
+        $timeout = $now[0] + ($now[1] / 1e9) + $timeout_sec;
+        while (true) {
+            $curr_hr = hrtime(true);
+            $curr_time = $curr_hr[0] + ($curr_hr[1] / 1e9);
+            if ($curr_time > $timeout) {
+                break;
+            }
+            // Thread variable seems to be read-only
+            $curr_id = count($client_thread->results);
+            if ($curr_id >= $end_id) {
+                break;
+            }
+            usleep(50000);
+        }
+
+        // Tally up results
+        $end_id = min($end_id, count($client_thread->results));
+        for ($i = $start_id; $i < $end_id; $i++) {
+            $hostname = $client_thread->results[$i];
+            if ($hostname) {
+                $num_failures -= 1;
+                if (!array_key_exists($hostname, $rpcs_by_peer)) {
+                    $rpcs_by_peer[$hostname] = 0;
+                }
+                $rpcs_by_peer[$hostname] += 1;
+            }
+        }
+        $response = new Grpc\Testing\LoadBalancerStatsResponse();
+        $response->setRpcsByPeer($rpcs_by_peer);
+        $response->setNumFailures($num_failures);
+        return $response;
+    }
+}
+
+// This client thread blindly sends a unary RPC to the server once
+// every 1 / qps seconds.
+class ClientThread extends Thread {
+    private $server_address_;
+    private $target_seconds_between_rpcs_;
+    private $fail_on_failed_rpcs_;
+    private $autoload_path_;
+    public $results;
+    
+    public function __construct($server_address, $qps, $fail_on_failed_rpcs,
+                                $autoload_path) {
+        $this->server_address_ = $server_address;
+        $this->target_seconds_between_rpcs_ = 1.0 / $qps;
+        $this->fail_on_failed_rpcs_ = $fail_on_failed_rpcs;
+        $this->autoload_path_ = $autoload_path;
+        $this->results = [];
+    }
+
+    public function run() {
+        // Autoloaded classes do not get inherited in threads.
+        // Hence we need to do this.
+        require_once($this->autoload_path_);
+        $TIMEOUT_US = 30 * 1e6; // 30 seconds
+
+        $stub = new Grpc\Testing\TestServiceClient($this->server_address_, [
+            'credentials' => Grpc\ChannelCredentials::createInsecure()
+        ]);
+        $request = new Grpc\Testing\SimpleRequest();
+        $target_next_start_us = hrtime(true) / 1000; # hrtime returns nanoseconds
+        while (true) {
+            $now_us = hrtime(true) / 1000;
+            $sleep_us = $target_next_start_us - $now_us;
+            if ($sleep_us < 0) {
+                $target_next_start_us =
+                        $now_us + ($this->target_seconds_between_rpcs_ * 1e6);
+                echo sprintf(
+                    "php xds: warning, rpc takes too long to finish. "
+                    . "Deficit %.1fms."
+                    . "If you consistently see this, the qps is too high.\n",
+                    round(abs($sleep_us / 1000), 1));
+            } else {
+                $target_next_start_us +=
+                        ($this->target_seconds_between_rpcs_ * 1e6);
+                usleep($sleep_us);
+            }
+            list($response, $status)
+                = $stub->UnaryCall($request, [],
+                                   ['timeout' => $TIMEOUT_US])->wait();
+            if ($status->code == Grpc\STATUS_OK) {
+                $this->results[] = $response->getHostname();
+            } else {
+                if ($this->fail_on_failed_rpcs_) {
+                    throw new Exception('UnaryCall failed with status '
+                                        . $status->code);
+                }
+                $this->results[] = "";
+            }
+        }
+    }
+
+    // This is needed for loading autoload_path in the child thread
+    public function start(int $options = PTHREADS_INHERIT_ALL) {
+        return parent::start(PTHREADS_INHERIT_NONE);
+    }
+}
+
+
+// Note: num_channels are currently ignored for now
+$args = getopt('', ['fail_on_failed_rpcs:', 'num_channels:',
+                    'server:', 'stats_port:', 'qps:']);
+
+$client_thread = new ClientThread($args['server'], $args['qps'],
+                                  $args['fail_on_failed_rpcs'],
+                                  $autoload_path);
+$client_thread->start();
+
+$server = new Grpc\RpcServer();
+$server->addHttp2Port('0.0.0.0:'.$args['stats_port']);
+$server->handle(new LoadBalancerStatsService());
+$server->run();
index f9c710c..9c98324 100644 (file)
@@ -15,17 +15,8 @@ class Stats
           return;
         }
         $pool->internalAddGeneratedFile(hex2bin(
-            "0a97020a1f7372632f70726f746f2f677270632f636f72652f7374617473" .
-            "2e70726f746f1209677270632e636f726522260a064275636b6574120d0a" .
-            "057374617274180120012801120d0a05636f756e74180220012804222f0a" .
-            "09486973746f6772616d12220a076275636b65747318012003280b32112e" .
-            "677270632e636f72652e4275636b6574225b0a064d6574726963120c0a04" .
-            "6e616d65180120012809120f0a05636f756e74180a20012804480012290a" .
-            "09686973746f6772616d180b2001280b32142e677270632e636f72652e48" .
-            "6973746f6772616d480042070a0576616c7565222b0a0553746174731222" .
-            "0a076d65747269637318012003280b32112e677270632e636f72652e4d65" .
-            "74726963620670726f746f33"
-        ));
+            "0a97020a1f7372632f70726f746f2f677270632f636f72652f73746174732e70726f746f1209677270632e636f726522260a064275636b6574120d0a057374617274180120012801120d0a05636f756e74180220012804222f0a09486973746f6772616d12220a076275636b65747318012003280b32112e677270632e636f72652e4275636b6574225b0a064d6574726963120c0a046e616d65180120012809120f0a05636f756e74180a20012804480012290a09686973746f6772616d180b2001280b32142e677270632e636f72652e486973746f6772616d480042070a0576616c7565222b0a05537461747312220a076d65747269637318012003280b32112e677270632e636f72652e4d6574726963620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
index 906f6a2..ab8c356 100644 (file)
@@ -16,24 +16,8 @@ class BenchmarkService
         }
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
         $pool->internalAddGeneratedFile(hex2bin(
-            "0aef030a2e7372632f70726f746f2f677270632f74657374696e672f6265" .
-            "6e63686d61726b5f736572766963652e70726f746f120c677270632e7465" .
-            "7374696e6732a6030a1042656e63686d61726b5365727669636512460a09" .
-            "556e61727943616c6c121b2e677270632e74657374696e672e53696d706c" .
-            "65526571756573741a1c2e677270632e74657374696e672e53696d706c65" .
-            "526573706f6e7365124e0a0d53747265616d696e6743616c6c121b2e6772" .
-            "70632e74657374696e672e53696d706c65526571756573741a1c2e677270" .
-            "632e74657374696e672e53696d706c65526573706f6e7365280130011252" .
-            "0a1353747265616d696e6746726f6d436c69656e74121b2e677270632e74" .
-            "657374696e672e53696d706c65526571756573741a1c2e677270632e7465" .
-            "7374696e672e53696d706c65526573706f6e7365280112520a1353747265" .
-            "616d696e6746726f6d536572766572121b2e677270632e74657374696e67" .
-            "2e53696d706c65526571756573741a1c2e677270632e74657374696e672e" .
-            "53696d706c65526573706f6e7365300112520a1153747265616d696e6742" .
-            "6f746857617973121b2e677270632e74657374696e672e53696d706c6552" .
-            "6571756573741a1c2e677270632e74657374696e672e53696d706c655265" .
-            "73706f6e736528013001620670726f746f33"
-        ));
+            "0aef030a2e7372632f70726f746f2f677270632f74657374696e672f62656e63686d61726b5f736572766963652e70726f746f120c677270632e74657374696e6732a6030a1042656e63686d61726b5365727669636512460a09556e61727943616c6c121b2e677270632e74657374696e672e53696d706c65526571756573741a1c2e677270632e74657374696e672e53696d706c65526573706f6e7365124e0a0d53747265616d696e6743616c6c121b2e677270632e74657374696e672e53696d706c65526571756573741a1c2e677270632e74657374696e672e53696d706c65526573706f6e73652801300112520a1353747265616d696e6746726f6d436c69656e74121b2e677270632e74657374696e672e53696d706c65526571756573741a1c2e677270632e74657374696e672e53696d706c65526573706f6e7365280112520a1353747265616d696e6746726f6d536572766572121b2e677270632e74657374696e672e53696d706c65526571756573741a1c2e677270632e74657374696e672e53696d706c65526573706f6e7365300112520a1153747265616d696e67426f746857617973121b2e677270632e74657374696e672e53696d706c65526571756573741a1c2e677270632e74657374696e672e53696d706c65526573706f6e736528013001620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
index 2c4fe92..0321b96 100644 (file)
@@ -15,21 +15,8 @@ class CompilerTest
           return;
         }
         $pool->internalAddGeneratedFile(hex2bin(
-            "0aa1030a2a7372632f70726f746f2f677270632f74657374696e672f636f" .
-            "6d70696c65725f746573742e70726f746f120c677270632e74657374696e" .
-            "6722090a0752657175657374220a0a08526573706f6e736532fe010a0853" .
-            "6572766963654112390a084d6574686f64413112152e677270632e746573" .
-            "74696e672e526571756573741a162e677270632e74657374696e672e5265" .
-            "73706f6e7365123b0a084d6574686f64413212152e677270632e74657374" .
-            "696e672e526571756573741a162e677270632e74657374696e672e526573" .
-            "706f6e73652801123b0a084d6574686f64413312152e677270632e746573" .
-            "74696e672e526571756573741a162e677270632e74657374696e672e5265" .
-            "73706f6e73653001123d0a084d6574686f64413412152e677270632e7465" .
-            "7374696e672e526571756573741a162e677270632e74657374696e672e52" .
-            "6573706f6e73652801300132450a08536572766963654212390a084d6574" .
-            "686f64423112152e677270632e74657374696e672e526571756573741a16" .
-            "2e677270632e74657374696e672e526573706f6e7365620670726f746f33"
-        ));
+            "0aa1030a2a7372632f70726f746f2f677270632f74657374696e672f636f6d70696c65725f746573742e70726f746f120c677270632e74657374696e6722090a0752657175657374220a0a08526573706f6e736532fe010a08536572766963654112390a084d6574686f64413112152e677270632e74657374696e672e526571756573741a162e677270632e74657374696e672e526573706f6e7365123b0a084d6574686f64413212152e677270632e74657374696e672e526571756573741a162e677270632e74657374696e672e526573706f6e73652801123b0a084d6574686f64413312152e677270632e74657374696e672e526571756573741a162e677270632e74657374696e672e526573706f6e73653001123d0a084d6574686f64413412152e677270632e74657374696e672e526571756573741a162e677270632e74657374696e672e526573706f6e73652801300132450a08536572766963654212390a084d6574686f64423112152e677270632e74657374696e672e526571756573741a162e677270632e74657374696e672e526573706f6e7365620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
index 2319bcd..0f111cc 100644 (file)
@@ -17,121 +17,8 @@ class Control
         \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce();
         \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
         $pool->internalAddGeneratedFile(hex2bin(
-            "0abc1a0a247372632f70726f746f2f677270632f74657374696e672f636f" .
-            "6e74726f6c2e70726f746f120c677270632e74657374696e671a22737263" .
-            "2f70726f746f2f677270632f74657374696e672f73746174732e70726f74" .
-            "6f22250a0d506f6973736f6e506172616d7312140a0c6f6666657265645f" .
-            "6c6f616418012001280122120a10436c6f7365644c6f6f70506172616d73" .
-            "227b0a0a4c6f6164506172616d7312350a0b636c6f7365645f6c6f6f7018" .
-            "012001280b321e2e677270632e74657374696e672e436c6f7365644c6f6f" .
-            "70506172616d734800122e0a07706f6973736f6e18022001280b321b2e67" .
-            "7270632e74657374696e672e506f6973736f6e506172616d73480042060a" .
-            "046c6f616422560a0e5365637572697479506172616d7312130a0b757365" .
-            "5f746573745f6361180120012808121c0a147365727665725f686f73745f" .
-            "6f7665727269646518022001280912110a09637265645f74797065180320" .
-            "012809224d0a0a4368616e6e656c417267120c0a046e616d651801200128" .
-            "0912130a097374725f76616c7565180220012809480012130a09696e745f" .
-            "76616c7565180320012805480042070a0576616c756522ef040a0c436c69" .
-            "656e74436f6e66696712160a0e7365727665725f74617267657473180120" .
-            "032809122d0a0b636c69656e745f7479706518022001280e32182e677270" .
-            "632e74657374696e672e436c69656e745479706512350a0f736563757269" .
-            "74795f706172616d7318032001280b321c2e677270632e74657374696e67" .
-            "2e5365637572697479506172616d7312240a1c6f75747374616e64696e67" .
-            "5f727063735f7065725f6368616e6e656c18042001280512170a0f636c69" .
-            "656e745f6368616e6e656c73180520012805121c0a146173796e635f636c" .
-            "69656e745f7468726561647318072001280512270a087270635f74797065" .
-            "18082001280e32152e677270632e74657374696e672e5270635479706512" .
-            "2d0a0b6c6f61645f706172616d73180a2001280b32182e677270632e7465" .
-            "7374696e672e4c6f6164506172616d7312330a0e7061796c6f61645f636f" .
-            "6e666967180b2001280b321b2e677270632e74657374696e672e5061796c" .
-            "6f6164436f6e66696712370a10686973746f6772616d5f706172616d7318" .
-            "0c2001280b321d2e677270632e74657374696e672e486973746f6772616d" .
-            "506172616d7312110a09636f72655f6c697374180d2003280512120a0a63" .
-            "6f72655f6c696d6974180e2001280512180a106f746865725f636c69656e" .
-            "745f617069180f20012809122e0a0c6368616e6e656c5f61726773181020" .
-            "03280b32182e677270632e74657374696e672e4368616e6e656c41726712" .
-            "160a0e746872656164735f7065725f6371181120012805121b0a136d6573" .
-            "73616765735f7065725f73747265616d18122001280512180a107573655f" .
-            "636f616c657363655f61706918132001280822380a0c436c69656e745374" .
-            "6174757312280a05737461747318012001280b32192e677270632e746573" .
-            "74696e672e436c69656e74537461747322150a044d61726b120d0a057265" .
-            "73657418012001280822680a0a436c69656e7441726773122b0a05736574" .
-            "757018012001280b321a2e677270632e74657374696e672e436c69656e74" .
-            "436f6e666967480012220a046d61726b18022001280b32122e677270632e" .
-            "74657374696e672e4d61726b480042090a076172677479706522fd020a0c" .
-            "536572766572436f6e666967122d0a0b7365727665725f74797065180120" .
-            "01280e32182e677270632e74657374696e672e5365727665725479706512" .
-            "350a0f73656375726974795f706172616d7318022001280b321c2e677270" .
-            "632e74657374696e672e5365637572697479506172616d73120c0a04706f" .
-            "7274180420012805121c0a146173796e635f7365727665725f7468726561" .
-            "647318072001280512120a0a636f72655f6c696d69741808200128051233" .
-            "0a0e7061796c6f61645f636f6e66696718092001280b321b2e677270632e" .
-            "74657374696e672e5061796c6f6164436f6e66696712110a09636f72655f" .
-            "6c697374180a2003280512180a106f746865725f7365727665725f617069" .
-            "180b2001280912160a0e746872656164735f7065725f6371180c20012805" .
-            "121c0a137265736f757263655f71756f74615f73697a6518e90720012805" .
-            "122f0a0c6368616e6e656c5f6172677318ea072003280b32182e67727063" .
-            "2e74657374696e672e4368616e6e656c41726722680a0a53657276657241" .
-            "726773122b0a05736574757018012001280b321a2e677270632e74657374" .
-            "696e672e536572766572436f6e666967480012220a046d61726b18022001" .
-            "280b32122e677270632e74657374696e672e4d61726b480042090a076172" .
-            "677479706522550a0c53657276657253746174757312280a057374617473" .
-            "18012001280b32192e677270632e74657374696e672e5365727665725374" .
-            "617473120c0a04706f7274180220012805120d0a05636f72657318032001" .
-            "2805220d0a0b436f726552657175657374221d0a0c436f7265526573706f" .
-            "6e7365120d0a05636f72657318012001280522060a04566f696422fd010a" .
-            "085363656e6172696f120c0a046e616d6518012001280912310a0d636c69" .
-            "656e745f636f6e66696718022001280b321a2e677270632e74657374696e" .
-            "672e436c69656e74436f6e66696712130a0b6e756d5f636c69656e747318" .
-            "032001280512310a0d7365727665725f636f6e66696718042001280b321a" .
-            "2e677270632e74657374696e672e536572766572436f6e66696712130a0b" .
-            "6e756d5f7365727665727318052001280512160a0e7761726d75705f7365" .
-            "636f6e647318062001280512190a1162656e63686d61726b5f7365636f6e" .
-            "647318072001280512200a18737061776e5f6c6f63616c5f776f726b6572" .
-            "5f636f756e7418082001280522360a095363656e6172696f7312290a0973" .
-            "63656e6172696f7318012003280b32162e677270632e74657374696e672e" .
-            "5363656e6172696f2284040a155363656e6172696f526573756c7453756d" .
-            "6d617279120b0a03717073180120012801121b0a137170735f7065725f73" .
-            "65727665725f636f7265180220012801121a0a127365727665725f737973" .
-            "74656d5f74696d6518032001280112180a107365727665725f757365725f" .
-            "74696d65180420012801121a0a12636c69656e745f73797374656d5f7469" .
-            "6d6518052001280112180a10636c69656e745f757365725f74696d651806" .
-            "2001280112120a0a6c6174656e63795f353018072001280112120a0a6c61" .
-            "74656e63795f393018082001280112120a0a6c6174656e63795f39351809" .
-            "2001280112120a0a6c6174656e63795f3939180a2001280112130a0b6c61" .
-            "74656e63795f393939180b2001280112180a107365727665725f6370755f" .
-            "7573616765180c2001280112260a1e7375636365737366756c5f72657175" .
-            "657374735f7065725f7365636f6e64180d2001280112220a1a6661696c65" .
-            "645f72657175657374735f7065725f7365636f6e64180e2001280112200a" .
-            "18636c69656e745f706f6c6c735f7065725f72657175657374180f200128" .
-            "0112200a187365727665725f706f6c6c735f7065725f7265717565737418" .
-            "102001280112220a1a7365727665725f717565726965735f7065725f6370" .
-            "755f73656318112001280112220a1a636c69656e745f717565726965735f" .
-            "7065725f6370755f7365631812200128012283030a0e5363656e6172696f" .
-            "526573756c7412280a087363656e6172696f18012001280b32162e677270" .
-            "632e74657374696e672e5363656e6172696f122e0a096c6174656e636965" .
-            "7318022001280b321b2e677270632e74657374696e672e486973746f6772" .
-            "616d44617461122f0a0c636c69656e745f737461747318032003280b3219" .
-            "2e677270632e74657374696e672e436c69656e745374617473122f0a0c73" .
-            "65727665725f737461747318042003280b32192e677270632e7465737469" .
-            "6e672e536572766572537461747312140a0c7365727665725f636f726573" .
-            "18052003280512340a0773756d6d61727918062001280b32232e67727063" .
-            "2e74657374696e672e5363656e6172696f526573756c7453756d6d617279" .
-            "12160a0e636c69656e745f7375636365737318072003280812160a0e7365" .
-            "727665725f7375636365737318082003280812390a0f726571756573745f" .
-            "726573756c747318092003280b32202e677270632e74657374696e672e52" .
-            "657175657374526573756c74436f756e742a410a0a436c69656e74547970" .
-            "65120f0a0b53594e435f434c49454e54100012100a0c4153594e435f434c" .
-            "49454e54100112100a0c4f544845525f434c49454e5410022a5b0a0a5365" .
-            "7276657254797065120f0a0b53594e435f534552564552100012100a0c41" .
-            "53594e435f534552564552100112180a144153594e435f47454e45524943" .
-            "5f534552564552100212100a0c4f544845525f53455256455210032a720a" .
-            "075270635479706512090a05554e4152591000120d0a0953545245414d49" .
-            "4e47100112190a1553545245414d494e475f46524f4d5f434c49454e5410" .
-            "0212190a1553545245414d494e475f46524f4d5f53455256455210031217" .
-            "0a1353545245414d494e475f424f54485f574159531004620670726f746f" .
-            "33"
-        ));
+            "0acd1b0a247372632f70726f746f2f677270632f74657374696e672f636f6e74726f6c2e70726f746f120c677270632e74657374696e671a227372632f70726f746f2f677270632f74657374696e672f73746174732e70726f746f22250a0d506f6973736f6e506172616d7312140a0c6f6666657265645f6c6f616418012001280122120a10436c6f7365644c6f6f70506172616d73227b0a0a4c6f6164506172616d7312350a0b636c6f7365645f6c6f6f7018012001280b321e2e677270632e74657374696e672e436c6f7365644c6f6f70506172616d734800122e0a07706f6973736f6e18022001280b321b2e677270632e74657374696e672e506f6973736f6e506172616d73480042060a046c6f616422560a0e5365637572697479506172616d7312130a0b7573655f746573745f6361180120012808121c0a147365727665725f686f73745f6f7665727269646518022001280912110a09637265645f74797065180320012809224d0a0a4368616e6e656c417267120c0a046e616d6518012001280912130a097374725f76616c7565180220012809480012130a09696e745f76616c7565180320012805480042070a0576616c756522bc050a0c436c69656e74436f6e66696712160a0e7365727665725f74617267657473180120032809122d0a0b636c69656e745f7479706518022001280e32182e677270632e74657374696e672e436c69656e745479706512350a0f73656375726974795f706172616d7318032001280b321c2e677270632e74657374696e672e5365637572697479506172616d7312240a1c6f75747374616e64696e675f727063735f7065725f6368616e6e656c18042001280512170a0f636c69656e745f6368616e6e656c73180520012805121c0a146173796e635f636c69656e745f7468726561647318072001280512270a087270635f7479706518082001280e32152e677270632e74657374696e672e52706354797065122d0a0b6c6f61645f706172616d73180a2001280b32182e677270632e74657374696e672e4c6f6164506172616d7312330a0e7061796c6f61645f636f6e666967180b2001280b321b2e677270632e74657374696e672e5061796c6f6164436f6e66696712370a10686973746f6772616d5f706172616d73180c2001280b321d2e677270632e74657374696e672e486973746f6772616d506172616d7312110a09636f72655f6c697374180d2003280512120a0a636f72655f6c696d6974180e2001280512180a106f746865725f636c69656e745f617069180f20012809122e0a0c6368616e6e656c5f6172677318102003280b32182e677270632e74657374696e672e4368616e6e656c41726712160a0e746872656164735f7065725f6371181120012805121b0a136d657373616765735f7065725f73747265616d18122001280512180a107573655f636f616c657363655f61706918132001280812310a296d656469616e5f6c6174656e63795f636f6c6c656374696f6e5f696e74657276616c5f6d696c6c697318142001280512180a10636c69656e745f70726f63657373657318152001280522380a0c436c69656e7453746174757312280a05737461747318012001280b32192e677270632e74657374696e672e436c69656e74537461747322150a044d61726b120d0a05726573657418012001280822680a0a436c69656e7441726773122b0a05736574757018012001280b321a2e677270632e74657374696e672e436c69656e74436f6e666967480012220a046d61726b18022001280b32122e677270632e74657374696e672e4d61726b480042090a07617267747970652297030a0c536572766572436f6e666967122d0a0b7365727665725f7479706518012001280e32182e677270632e74657374696e672e5365727665725479706512350a0f73656375726974795f706172616d7318022001280b321c2e677270632e74657374696e672e5365637572697479506172616d73120c0a04706f7274180420012805121c0a146173796e635f7365727665725f7468726561647318072001280512120a0a636f72655f6c696d697418082001280512330a0e7061796c6f61645f636f6e66696718092001280b321b2e677270632e74657374696e672e5061796c6f6164436f6e66696712110a09636f72655f6c697374180a2003280512180a106f746865725f7365727665725f617069180b2001280912160a0e746872656164735f7065725f6371180c20012805121c0a137265736f757263655f71756f74615f73697a6518e90720012805122f0a0c6368616e6e656c5f6172677318ea072003280b32182e677270632e74657374696e672e4368616e6e656c41726712180a107365727665725f70726f63657373657318152001280522680a0a53657276657241726773122b0a05736574757018012001280b321a2e677270632e74657374696e672e536572766572436f6e666967480012220a046d61726b18022001280b32122e677270632e74657374696e672e4d61726b480042090a076172677479706522550a0c53657276657253746174757312280a05737461747318012001280b32192e677270632e74657374696e672e5365727665725374617473120c0a04706f7274180220012805120d0a05636f726573180320012805220d0a0b436f726552657175657374221d0a0c436f7265526573706f6e7365120d0a05636f72657318012001280522060a04566f696422fd010a085363656e6172696f120c0a046e616d6518012001280912310a0d636c69656e745f636f6e66696718022001280b321a2e677270632e74657374696e672e436c69656e74436f6e66696712130a0b6e756d5f636c69656e747318032001280512310a0d7365727665725f636f6e66696718042001280b321a2e677270632e74657374696e672e536572766572436f6e66696712130a0b6e756d5f7365727665727318052001280512160a0e7761726d75705f7365636f6e647318062001280512190a1162656e63686d61726b5f7365636f6e647318072001280512200a18737061776e5f6c6f63616c5f776f726b65725f636f756e7418082001280522360a095363656e6172696f7312290a097363656e6172696f7318012003280b32162e677270632e74657374696e672e5363656e6172696f2284040a155363656e6172696f526573756c7453756d6d617279120b0a03717073180120012801121b0a137170735f7065725f7365727665725f636f7265180220012801121a0a127365727665725f73797374656d5f74696d6518032001280112180a107365727665725f757365725f74696d65180420012801121a0a12636c69656e745f73797374656d5f74696d6518052001280112180a10636c69656e745f757365725f74696d6518062001280112120a0a6c6174656e63795f353018072001280112120a0a6c6174656e63795f393018082001280112120a0a6c6174656e63795f393518092001280112120a0a6c6174656e63795f3939180a2001280112130a0b6c6174656e63795f393939180b2001280112180a107365727665725f6370755f7573616765180c2001280112260a1e7375636365737366756c5f72657175657374735f7065725f7365636f6e64180d2001280112220a1a6661696c65645f72657175657374735f7065725f7365636f6e64180e2001280112200a18636c69656e745f706f6c6c735f7065725f72657175657374180f2001280112200a187365727665725f706f6c6c735f7065725f7265717565737418102001280112220a1a7365727665725f717565726965735f7065725f6370755f73656318112001280112220a1a636c69656e745f717565726965735f7065725f6370755f7365631812200128012283030a0e5363656e6172696f526573756c7412280a087363656e6172696f18012001280b32162e677270632e74657374696e672e5363656e6172696f122e0a096c6174656e6369657318022001280b321b2e677270632e74657374696e672e486973746f6772616d44617461122f0a0c636c69656e745f737461747318032003280b32192e677270632e74657374696e672e436c69656e745374617473122f0a0c7365727665725f737461747318042003280b32192e677270632e74657374696e672e536572766572537461747312140a0c7365727665725f636f72657318052003280512340a0773756d6d61727918062001280b32232e677270632e74657374696e672e5363656e6172696f526573756c7453756d6d61727912160a0e636c69656e745f7375636365737318072003280812160a0e7365727665725f7375636365737318082003280812390a0f726571756573745f726573756c747318092003280b32202e677270632e74657374696e672e52657175657374526573756c74436f756e742a560a0a436c69656e7454797065120f0a0b53594e435f434c49454e54100012100a0c4153594e435f434c49454e54100112100a0c4f544845525f434c49454e54100212130a0f43414c4c4241434b5f434c49454e5410032a700a0a53657276657254797065120f0a0b53594e435f534552564552100012100a0c4153594e435f534552564552100112180a144153594e435f47454e455249435f534552564552100212100a0c4f544845525f534552564552100312130a0f43414c4c4241434b5f53455256455210042a720a075270635479706512090a05554e4152591000120d0a0953545245414d494e47100112190a1553545245414d494e475f46524f4d5f434c49454e54100212190a1553545245414d494e475f46524f4d5f534552564552100312170a1353545245414d494e475f424f54485f574159531004620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Echo.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Echo.php
deleted file mode 100644 (file)
index 77c5230..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: src/proto/grpc/testing/echo.proto
-
-namespace GPBMetadata\Src\Proto\Grpc\Testing;
-
-class Echo
-{
-    public static $is_initialized = false;
-
-    public static function initOnce() {
-        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
-
-        if (static::$is_initialized == true) {
-          return;
-        }
-        \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
-        $pool->internalAddGeneratedFile(hex2bin(
-            "0aa6040a217372632f70726f746f2f677270632f74657374696e672f6563" .
-            "686f2e70726f746f120c677270632e74657374696e6732f6020a0f456368" .
-            "6f5465737453657276696365123d0a044563686f12192e677270632e7465" .
-            "7374696e672e4563686f526571756573741a1a2e677270632e7465737469" .
-            "6e672e4563686f526573706f6e736512480a0d5265717565737453747265" .
-            "616d12192e677270632e74657374696e672e4563686f526571756573741a" .
-            "1a2e677270632e74657374696e672e4563686f526573706f6e7365280112" .
-            "490a0e526573706f6e736553747265616d12192e677270632e7465737469" .
-            "6e672e4563686f526571756573741a1a2e677270632e74657374696e672e" .
-            "4563686f526573706f6e7365300112470a0a4269646953747265616d1219" .
-            "2e677270632e74657374696e672e4563686f526571756573741a1a2e6772" .
-            "70632e74657374696e672e4563686f526573706f6e73652801300112460a" .
-            "0d556e696d706c656d656e74656412192e677270632e74657374696e672e" .
-            "4563686f526571756573741a1a2e677270632e74657374696e672e456368" .
-            "6f526573706f6e736532620a18556e696d706c656d656e7465644563686f" .
-            "5365727669636512460a0d556e696d706c656d656e74656412192e677270" .
-            "632e74657374696e672e4563686f526571756573741a1a2e677270632e74" .
-            "657374696e672e4563686f526573706f6e7365320e0a0c4e6f5270635365" .
-            "7276696365620670726f746f33"
-        ));
-
-        static::$is_initialized = true;
-    }
-}
-
index 4bac8a2..efcc9b3 100644 (file)
@@ -15,38 +15,8 @@ class EchoMessages
           return;
         }
         $pool->internalAddGeneratedFile(hex2bin(
-            "0a8f070a2a7372632f70726f746f2f677270632f74657374696e672f6563" .
-            "686f5f6d657373616765732e70726f746f120c677270632e74657374696e" .
-            "6722320a094465627567496e666f12150a0d737461636b5f656e74726965" .
-            "73180120032809120e0a0664657461696c18022001280922500a0b457272" .
-            "6f72537461747573120c0a04636f646518012001280512150a0d6572726f" .
-            "725f6d657373616765180220012809121c0a1462696e6172795f6572726f" .
-            "725f64657461696c7318032001280922e2030a0d52657175657374506172" .
-            "616d7312150a0d6563686f5f646561646c696e65180120012808121e0a16" .
-            "636c69656e745f63616e63656c5f61667465725f7573180220012805121e" .
-            "0a167365727665725f63616e63656c5f61667465725f7573180320012805" .
-            "12150a0d6563686f5f6d65746164617461180420012808121a0a12636865" .
-            "636b5f617574685f636f6e74657874180520012808121f0a17726573706f" .
-            "6e73655f6d6573736167655f6c656e67746818062001280512110a096563" .
-            "686f5f7065657218072001280812200a1865787065637465645f636c6965" .
-            "6e745f6964656e74697479180820012809121c0a14736b69705f63616e63" .
-            "656c6c65645f636865636b18092001280812280a2065787065637465645f" .
-            "7472616e73706f72745f73656375726974795f74797065180a2001280912" .
-            "2b0a0a64656275675f696e666f180b2001280b32172e677270632e746573" .
-            "74696e672e4465627567496e666f12120a0a7365727665725f646965180c" .
-            "20012808121c0a1462696e6172795f6572726f725f64657461696c73180d" .
-            "2001280912310a0e65787065637465645f6572726f72180e2001280b3219" .
-            "2e677270632e74657374696e672e4572726f7253746174757312170a0f73" .
-            "65727665725f736c6565705f7573180f20012805224a0a0b4563686f5265" .
-            "7175657374120f0a076d657373616765180120012809122a0a0570617261" .
-            "6d18022001280b321b2e677270632e74657374696e672e52657175657374" .
-            "506172616d7322460a0e526573706f6e7365506172616d7312180a107265" .
-            "71756573745f646561646c696e65180120012803120c0a04686f73741802" .
-            "20012809120c0a0470656572180320012809224c0a0c4563686f52657370" .
-            "6f6e7365120f0a076d657373616765180120012809122b0a05706172616d" .
-            "18022001280b321c2e677270632e74657374696e672e526573706f6e7365" .
-            "506172616d73620670726f746f33"
-        ));
+            "0afd070a2a7372632f70726f746f2f677270632f74657374696e672f6563686f5f6d657373616765732e70726f746f120c677270632e74657374696e6722320a094465627567496e666f12150a0d737461636b5f656e7472696573180120032809120e0a0664657461696c18022001280922500a0b4572726f72537461747573120c0a04636f646518012001280512150a0d6572726f725f6d657373616765180220012809121c0a1462696e6172795f6572726f725f64657461696c7318032001280922cb040a0d52657175657374506172616d7312150a0d6563686f5f646561646c696e65180120012808121e0a16636c69656e745f63616e63656c5f61667465725f7573180220012805121e0a167365727665725f63616e63656c5f61667465725f757318032001280512150a0d6563686f5f6d65746164617461180420012808121a0a12636865636b5f617574685f636f6e74657874180520012808121f0a17726573706f6e73655f6d6573736167655f6c656e67746818062001280512110a096563686f5f7065657218072001280812200a1865787065637465645f636c69656e745f6964656e74697479180820012809121c0a14736b69705f63616e63656c6c65645f636865636b18092001280812280a2065787065637465645f7472616e73706f72745f73656375726974795f74797065180a20012809122b0a0a64656275675f696e666f180b2001280b32172e677270632e74657374696e672e4465627567496e666f12120a0a7365727665725f646965180c20012808121c0a1462696e6172795f6572726f725f64657461696c73180d2001280912310a0e65787065637465645f6572726f72180e2001280b32192e677270632e74657374696e672e4572726f7253746174757312170a0f7365727665725f736c6565705f7573180f20012805121b0a136261636b656e645f6368616e6e656c5f696478181020012805121f0a176563686f5f6d657461646174615f696e697469616c6c7918112001280812290a217365727665725f6e6f746966795f636c69656e745f7768656e5f73746172746564181220012808224a0a0b4563686f52657175657374120f0a076d657373616765180120012809122a0a05706172616d18022001280b321b2e677270632e74657374696e672e52657175657374506172616d7322460a0e526573706f6e7365506172616d7312180a10726571756573745f646561646c696e65180120012803120c0a04686f7374180220012809120c0a0470656572180320012809224c0a0c4563686f526573706f6e7365120f0a076d657373616765180120012809122b0a05706172616d18022001280b321c2e677270632e74657374696e672e526573706f6e7365506172616d734203f80101620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/EmptyService.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/EmptyService.php
new file mode 100644 (file)
index 0000000..3451b48
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/empty_service.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class EmptyService
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0a520a2a7372632f70726f746f2f677270632f74657374696e672f656d7074795f736572766963652e70726f746f120c677270632e74657374696e67320e0a0c456d70747953657276696365620670726f746f33"
+        ), true);
+
+        static::$is_initialized = true;
+    }
+}
+
index c088002..91a9c7b 100644 (file)
@@ -15,53 +15,8 @@ class Messages
           return;
         }
         $pool->internalAddGeneratedFile(hex2bin(
-            "0ad50a0a257372632f70726f746f2f677270632f74657374696e672f6d65" .
-            "7373616765732e70726f746f120c677270632e74657374696e67221a0a09" .
-            "426f6f6c56616c7565120d0a0576616c756518012001280822400a075061" .
-            "796c6f616412270a047479706518012001280e32192e677270632e746573" .
-            "74696e672e5061796c6f616454797065120c0a04626f647918022001280c" .
-            "222b0a0a4563686f537461747573120c0a04636f6465180120012805120f" .
-            "0a076d65737361676518022001280922ce020a0d53696d706c6552657175" .
-            "65737412300a0d726573706f6e73655f7479706518012001280e32192e67" .
-            "7270632e74657374696e672e5061796c6f61645479706512150a0d726573" .
-            "706f6e73655f73697a6518022001280512260a077061796c6f6164180320" .
-            "01280b32152e677270632e74657374696e672e5061796c6f616412150a0d" .
-            "66696c6c5f757365726e616d6518042001280812180a1066696c6c5f6f61" .
-            "7574685f73636f706518052001280812340a13726573706f6e73655f636f" .
-            "6d7072657373656418062001280b32172e677270632e74657374696e672e" .
-            "426f6f6c56616c756512310a0f726573706f6e73655f7374617475731807" .
-            "2001280b32182e677270632e74657374696e672e4563686f537461747573" .
-            "12320a116578706563745f636f6d7072657373656418082001280b32172e" .
-            "677270632e74657374696e672e426f6f6c56616c7565225f0a0e53696d70" .
-            "6c65526573706f6e736512260a077061796c6f616418012001280b32152e" .
-            "677270632e74657374696e672e5061796c6f616412100a08757365726e61" .
-            "6d6518022001280912130a0b6f617574685f73636f706518032001280922" .
-            "770a1953747265616d696e67496e70757443616c6c526571756573741226" .
-            "0a077061796c6f616418012001280b32152e677270632e74657374696e67" .
-            "2e5061796c6f616412320a116578706563745f636f6d7072657373656418" .
-            "022001280b32172e677270632e74657374696e672e426f6f6c56616c7565" .
-            "223d0a1a53747265616d696e67496e70757443616c6c526573706f6e7365" .
-            "121f0a17616767726567617465645f7061796c6f61645f73697a65180120" .
-            "01280522640a12526573706f6e7365506172616d6574657273120c0a0473" .
-            "697a6518012001280512130a0b696e74657276616c5f7573180220012805" .
-            "122b0a0a636f6d7072657373656418032001280b32172e677270632e7465" .
-            "7374696e672e426f6f6c56616c756522e8010a1a53747265616d696e674f" .
-            "757470757443616c6c5265717565737412300a0d726573706f6e73655f74" .
-            "79706518012001280e32192e677270632e74657374696e672e5061796c6f" .
-            "616454797065123d0a13726573706f6e73655f706172616d657465727318" .
-            "022003280b32202e677270632e74657374696e672e526573706f6e736550" .
-            "6172616d657465727312260a077061796c6f616418032001280b32152e67" .
-            "7270632e74657374696e672e5061796c6f616412310a0f726573706f6e73" .
-            "655f73746174757318072001280b32182e677270632e74657374696e672e" .
-            "4563686f53746174757322450a1b53747265616d696e674f757470757443" .
-            "616c6c526573706f6e736512260a077061796c6f616418012001280b3215" .
-            "2e677270632e74657374696e672e5061796c6f616422330a0f5265636f6e" .
-            "6e656374506172616d7312200a186d61785f7265636f6e6e6563745f6261" .
-            "636b6f66665f6d7318012001280522330a0d5265636f6e6e656374496e66" .
-            "6f120e0a0670617373656418012001280812120a0a6261636b6f66665f6d" .
-            "731802200328052a1f0a0b5061796c6f61645479706512100a0c434f4d50" .
-            "5245535341424c451000620670726f746f33"
-        ));
+            "0ad70e0a257372632f70726f746f2f677270632f74657374696e672f6d657373616765732e70726f746f120c677270632e74657374696e67221a0a09426f6f6c56616c7565120d0a0576616c756518012001280822400a075061796c6f616412270a047479706518012001280e32192e677270632e74657374696e672e5061796c6f616454797065120c0a04626f647918022001280c222b0a0a4563686f537461747573120c0a04636f6465180120012805120f0a076d6573736167651802200128092286030a0d53696d706c655265717565737412300a0d726573706f6e73655f7479706518012001280e32192e677270632e74657374696e672e5061796c6f61645479706512150a0d726573706f6e73655f73697a6518022001280512260a077061796c6f616418032001280b32152e677270632e74657374696e672e5061796c6f616412150a0d66696c6c5f757365726e616d6518042001280812180a1066696c6c5f6f617574685f73636f706518052001280812340a13726573706f6e73655f636f6d7072657373656418062001280b32172e677270632e74657374696e672e426f6f6c56616c756512310a0f726573706f6e73655f73746174757318072001280b32182e677270632e74657374696e672e4563686f53746174757312320a116578706563745f636f6d7072657373656418082001280b32172e677270632e74657374696e672e426f6f6c56616c756512160a0e66696c6c5f7365727665725f6964180920012808121e0a1666696c6c5f677270636c625f726f7574655f74797065180a2001280822be010a0e53696d706c65526573706f6e736512260a077061796c6f616418012001280b32152e677270632e74657374696e672e5061796c6f616412100a08757365726e616d6518022001280912130a0b6f617574685f73636f706518032001280912110a097365727665725f696418042001280912380a11677270636c625f726f7574655f7479706518052001280e321d2e677270632e74657374696e672e477270636c62526f7574655479706512100a08686f73746e616d6518062001280922770a1953747265616d696e67496e70757443616c6c5265717565737412260a077061796c6f616418012001280b32152e677270632e74657374696e672e5061796c6f616412320a116578706563745f636f6d7072657373656418022001280b32172e677270632e74657374696e672e426f6f6c56616c7565223d0a1a53747265616d696e67496e70757443616c6c526573706f6e7365121f0a17616767726567617465645f7061796c6f61645f73697a6518012001280522640a12526573706f6e7365506172616d6574657273120c0a0473697a6518012001280512130a0b696e74657276616c5f7573180220012805122b0a0a636f6d7072657373656418032001280b32172e677270632e74657374696e672e426f6f6c56616c756522e8010a1a53747265616d696e674f757470757443616c6c5265717565737412300a0d726573706f6e73655f7479706518012001280e32192e677270632e74657374696e672e5061796c6f616454797065123d0a13726573706f6e73655f706172616d657465727318022003280b32202e677270632e74657374696e672e526573706f6e7365506172616d657465727312260a077061796c6f616418032001280b32152e677270632e74657374696e672e5061796c6f616412310a0f726573706f6e73655f73746174757318072001280b32182e677270632e74657374696e672e4563686f53746174757322450a1b53747265616d696e674f757470757443616c6c526573706f6e736512260a077061796c6f616418012001280b32152e677270632e74657374696e672e5061796c6f616422330a0f5265636f6e6e656374506172616d7312200a186d61785f7265636f6e6e6563745f6261636b6f66665f6d7318012001280522330a0d5265636f6e6e656374496e666f120e0a0670617373656418012001280812120a0a6261636b6f66665f6d7318022003280522410a184c6f616442616c616e63657253746174735265717565737412100a086e756d5f7270637318012001280512130a0b74696d656f75745f73656318022001280522b3010a194c6f616442616c616e6365725374617473526573706f6e7365124d0a0c727063735f62795f7065657218012003280b32372e677270632e74657374696e672e4c6f616442616c616e6365725374617473526573706f6e73652e52706373427950656572456e74727912140a0c6e756d5f6661696c757265731802200128051a310a0f52706373427950656572456e747279120b0a036b6579180120012809120d0a0576616c75651802200128053a0238012a1f0a0b5061796c6f61645479706512100a0c434f4d505245535341424c4510002a6f0a0f477270636c62526f75746554797065121d0a19475250434c425f524f5554455f545950455f554e4b4e4f574e1000121e0a1a475250434c425f524f5554455f545950455f46414c4c4241434b1001121d0a19475250434c425f524f5554455f545950455f4241434b454e441002620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Metrics.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Metrics.php
deleted file mode 100644 (file)
index 7ac739f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: src/proto/grpc/testing/metrics.proto
-
-namespace GPBMetadata\Src\Proto\Grpc\Testing;
-
-class Metrics
-{
-    public static $is_initialized = false;
-
-    public static function initOnce() {
-        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
-
-        if (static::$is_initialized == true) {
-          return;
-        }
-        $pool->internalAddGeneratedFile(hex2bin(
-            "0afb020a247372632f70726f746f2f677270632f74657374696e672f6d65" .
-            "74726963732e70726f746f120c677270632e74657374696e67226c0a0d47" .
-            "61756765526573706f6e7365120c0a046e616d6518012001280912140a0a" .
-            "6c6f6e675f76616c7565180220012803480012160a0c646f75626c655f76" .
-            "616c7565180320012801480012160a0c737472696e675f76616c75651804" .
-            "20012809480042070a0576616c7565221c0a0c4761756765526571756573" .
-            "74120c0a046e616d65180120012809220e0a0c456d7074794d6573736167" .
-            "6532a0010a0e4d6574726963735365727669636512490a0c476574416c6c" .
-            "476175676573121a2e677270632e74657374696e672e456d7074794d6573" .
-            "736167651a1b2e677270632e74657374696e672e4761756765526573706f" .
-            "6e7365300112430a084765744761756765121a2e677270632e7465737469" .
-            "6e672e4761756765526571756573741a1b2e677270632e74657374696e67" .
-            "2e4761756765526573706f6e7365620670726f746f33"
-        ));
-
-        static::$is_initialized = true;
-    }
-}
-
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/PBEmpty.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/PBEmpty.php
new file mode 100644 (file)
index 0000000..f103e2e
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/empty.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class PBEmpty
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0a4a0a227372632f70726f746f2f677270632f74657374696e672f656d7074792e70726f746f120c677270632e74657374696e67220e0a0c456d7074794d657373616765620670726f746f33"
+        ), true);
+
+        static::$is_initialized = true;
+    }
+}
+
index 279fe00..84ccb0b 100644 (file)
@@ -15,21 +15,8 @@ class Payloads
           return;
         }
         $pool->internalAddGeneratedFile(hex2bin(
-            "0a93030a257372632f70726f746f2f677270632f74657374696e672f7061" .
-            "796c6f6164732e70726f746f120c677270632e74657374696e6722370a10" .
-            "42797465427566666572506172616d7312100a087265715f73697a651801" .
-            "2001280512110a09726573705f73697a6518022001280522380a1153696d" .
-            "706c6550726f746f506172616d7312100a087265715f73697a6518012001" .
-            "280512110a09726573705f73697a6518022001280522140a12436f6d706c" .
-            "657850726f746f506172616d7322ca010a0d5061796c6f6164436f6e6669" .
-            "6712380a0e627974656275665f706172616d7318012001280b321e2e6772" .
-            "70632e74657374696e672e42797465427566666572506172616d73480012" .
-            "380a0d73696d706c655f706172616d7318022001280b321f2e677270632e" .
-            "74657374696e672e53696d706c6550726f746f506172616d734800123a0a" .
-            "0e636f6d706c65785f706172616d7318032001280b32202e677270632e74" .
-            "657374696e672e436f6d706c657850726f746f506172616d73480042090a" .
-            "077061796c6f6164620670726f746f33"
-        ));
+            "0a93030a257372632f70726f746f2f677270632f74657374696e672f7061796c6f6164732e70726f746f120c677270632e74657374696e6722370a1042797465427566666572506172616d7312100a087265715f73697a6518012001280512110a09726573705f73697a6518022001280522380a1153696d706c6550726f746f506172616d7312100a087265715f73697a6518012001280512110a09726573705f73697a6518022001280522140a12436f6d706c657850726f746f506172616d7322ca010a0d5061796c6f6164436f6e66696712380a0e627974656275665f706172616d7318012001280b321e2e677270632e74657374696e672e42797465427566666572506172616d73480012380a0d73696d706c655f706172616d7318022001280b321f2e677270632e74657374696e672e53696d706c6550726f746f506172616d734800123a0a0e636f6d706c65785f706172616d7318032001280b32202e677270632e74657374696e672e436f6d706c657850726f746f506172616d73480042090a077061796c6f6164620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
index e07f736..ef7dae2 100644 (file)
@@ -17,19 +17,8 @@ class ProxyService
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
         \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
         $pool->internalAddGeneratedFile(hex2bin(
-            "0ad6020a2a7372632f70726f746f2f677270632f74657374696e672f7072" .
-            "6f78792d736572766963652e70726f746f120c677270632e74657374696e" .
-            "671a227372632f70726f746f2f677270632f74657374696e672f73746174" .
-            "732e70726f746f221c0a0950726f787953746174120f0a076c6174656e63" .
-            "7918012001280132cf010a1250726f7879436c69656e7453657276696365" .
-            "123b0a09476574436f6e66696712122e677270632e74657374696e672e56" .
-            "6f69641a1a2e677270632e74657374696e672e436c69656e74436f6e6669" .
-            "67123b0a0a5265706f727454696d6512172e677270632e74657374696e67" .
-            "2e50726f7879537461741a122e677270632e74657374696e672e566f6964" .
-            "2801123f0a0a5265706f727448697374121b2e677270632e74657374696e" .
-            "672e486973746f6772616d446174611a122e677270632e74657374696e67" .
-            "2e566f69642801620670726f746f33"
-        ));
+            "0ad6020a2a7372632f70726f746f2f677270632f74657374696e672f70726f78792d736572766963652e70726f746f120c677270632e74657374696e671a227372632f70726f746f2f677270632f74657374696e672f73746174732e70726f746f221c0a0950726f787953746174120f0a076c6174656e637918012001280132cf010a1250726f7879436c69656e7453657276696365123b0a09476574436f6e66696712122e677270632e74657374696e672e566f69641a1a2e677270632e74657374696e672e436c69656e74436f6e666967123b0a0a5265706f727454696d6512172e677270632e74657374696e672e50726f7879537461741a122e677270632e74657374696e672e566f69642801123f0a0a5265706f727448697374121b2e677270632e74657374696e672e486973746f6772616d446174611a122e677270632e74657374696e672e566f69642801620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
index 35a1fb4..f8de870 100644 (file)
@@ -16,13 +16,8 @@ class ReportQpsScenarioService
         }
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
         $pool->internalAddGeneratedFile(hex2bin(
-            "0ab0010a387372632f70726f746f2f677270632f74657374696e672f7265" .
-            "706f72745f7170735f7363656e6172696f5f736572766963652e70726f74" .
-            "6f120c677270632e74657374696e67325e0a185265706f72745170735363" .
-            "656e6172696f5365727669636512420a0e5265706f72745363656e617269" .
-            "6f121c2e677270632e74657374696e672e5363656e6172696f526573756c" .
-            "741a122e677270632e74657374696e672e566f6964620670726f746f33"
-        ));
+            "0ab0010a387372632f70726f746f2f677270632f74657374696e672f7265706f72745f7170735f7363656e6172696f5f736572766963652e70726f746f120c677270632e74657374696e67325e0a185265706f72745170735363656e6172696f5365727669636512420a0e5265706f72745363656e6172696f121c2e677270632e74657374696e672e5363656e6172696f526573756c741a122e677270632e74657374696e672e566f6964620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
index 3d23b75..8cce2f5 100644 (file)
@@ -16,32 +16,8 @@ class Stats
         }
         \GPBMetadata\Src\Proto\Grpc\Core\Stats::initOnce();
         $pool->internalAddGeneratedFile(hex2bin(
-            "0ada050a227372632f70726f746f2f677270632f74657374696e672f7374" .
-            "6174732e70726f746f120c677270632e74657374696e6722b7010a0b5365" .
-            "72766572537461747312140a0c74696d655f656c61707365641801200128" .
-            "0112110a0974696d655f7573657218022001280112130a0b74696d655f73" .
-            "797374656d18032001280112160a0e746f74616c5f6370755f74696d6518" .
-            "042001280412150a0d69646c655f6370755f74696d651805200128041215" .
-            "0a0d63715f706f6c6c5f636f756e7418062001280412240a0a636f72655f" .
-            "737461747318072001280b32102e677270632e636f72652e537461747322" .
-            "3b0a0f486973746f6772616d506172616d7312120a0a7265736f6c757469" .
-            "6f6e18012001280112140a0c6d61785f706f737369626c65180220012801" .
-            "22770a0d486973746f6772616d44617461120e0a066275636b6574180120" .
-            "03280d12100a086d696e5f7365656e18022001280112100a086d61785f73" .
-            "65656e180320012801120b0a0373756d18042001280112160a0e73756d5f" .
-            "6f665f73717561726573180520012801120d0a05636f756e741806200128" .
-            "0122380a1252657175657374526573756c74436f756e7412130a0b737461" .
-            "7475735f636f6465180120012805120d0a05636f756e7418022001280322" .
-            "f3010a0b436c69656e745374617473122e0a096c6174656e636965731801" .
-            "2001280b321b2e677270632e74657374696e672e486973746f6772616d44" .
-            "61746112140a0c74696d655f656c617073656418022001280112110a0974" .
-            "696d655f7573657218032001280112130a0b74696d655f73797374656d18" .
-            "042001280112390a0f726571756573745f726573756c747318052003280b" .
-            "32202e677270632e74657374696e672e52657175657374526573756c7443" .
-            "6f756e7412150a0d63715f706f6c6c5f636f756e7418062001280412240a" .
-            "0a636f72655f737461747318072001280b32102e677270632e636f72652e" .
-            "5374617473620670726f746f33"
-        ));
+            "0ada050a227372632f70726f746f2f677270632f74657374696e672f73746174732e70726f746f120c677270632e74657374696e6722b7010a0b536572766572537461747312140a0c74696d655f656c617073656418012001280112110a0974696d655f7573657218022001280112130a0b74696d655f73797374656d18032001280112160a0e746f74616c5f6370755f74696d6518042001280412150a0d69646c655f6370755f74696d6518052001280412150a0d63715f706f6c6c5f636f756e7418062001280412240a0a636f72655f737461747318072001280b32102e677270632e636f72652e5374617473223b0a0f486973746f6772616d506172616d7312120a0a7265736f6c7574696f6e18012001280112140a0c6d61785f706f737369626c6518022001280122770a0d486973746f6772616d44617461120e0a066275636b657418012003280d12100a086d696e5f7365656e18022001280112100a086d61785f7365656e180320012801120b0a0373756d18042001280112160a0e73756d5f6f665f73717561726573180520012801120d0a05636f756e7418062001280122380a1252657175657374526573756c74436f756e7412130a0b7374617475735f636f6465180120012805120d0a05636f756e7418022001280322f3010a0b436c69656e745374617473122e0a096c6174656e6369657318012001280b321b2e677270632e74657374696e672e486973746f6772616d4461746112140a0c74696d655f656c617073656418022001280112110a0974696d655f7573657218032001280112130a0b74696d655f73797374656d18042001280112390a0f726571756573745f726573756c747318052003280b32202e677270632e74657374696e672e52657175657374526573756c74436f756e7412150a0d63715f706f6c6c5f636f756e7418062001280412240a0a636f72655f737461747318072001280b32102e677270632e636f72652e5374617473620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
index 54628cf..2ae2dad 100644 (file)
@@ -14,45 +14,11 @@ class Test
         if (static::$is_initialized == true) {
           return;
         }
-        \GPBMetadata\Src\Proto\Grpc\Testing\GPBEmpty::initOnce();
+        \GPBMetadata\Src\Proto\Grpc\Testing\PBEmpty::initOnce();
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
         $pool->internalAddGeneratedFile(hex2bin(
-            "0a91080a217372632f70726f746f2f677270632f74657374696e672f7465" .
-            "73742e70726f746f120c677270632e74657374696e671a257372632f7072" .
-            "6f746f2f677270632f74657374696e672f6d657373616765732e70726f74" .
-            "6f32cb050a0b546573745365727669636512350a09456d70747943616c6c" .
-            "12132e677270632e74657374696e672e456d7074791a132e677270632e74" .
-            "657374696e672e456d70747912460a09556e61727943616c6c121b2e6772" .
-            "70632e74657374696e672e53696d706c65526571756573741a1c2e677270" .
-            "632e74657374696e672e53696d706c65526573706f6e7365124f0a124361" .
-            "63686561626c65556e61727943616c6c121b2e677270632e74657374696e" .
-            "672e53696d706c65526571756573741a1c2e677270632e74657374696e67" .
-            "2e53696d706c65526573706f6e7365126c0a1353747265616d696e674f75" .
-            "7470757443616c6c12282e677270632e74657374696e672e53747265616d" .
-            "696e674f757470757443616c6c526571756573741a292e677270632e7465" .
-            "7374696e672e53747265616d696e674f757470757443616c6c526573706f" .
-            "6e7365300112690a1253747265616d696e67496e70757443616c6c12272e" .
-            "677270632e74657374696e672e53747265616d696e67496e70757443616c" .
-            "6c526571756573741a282e677270632e74657374696e672e53747265616d" .
-            "696e67496e70757443616c6c526573706f6e7365280112690a0e46756c6c" .
-            "4475706c657843616c6c12282e677270632e74657374696e672e53747265" .
-            "616d696e674f757470757443616c6c526571756573741a292e677270632e" .
-            "74657374696e672e53747265616d696e674f757470757443616c6c526573" .
-            "706f6e73652801300112690a0e48616c664475706c657843616c6c12282e" .
-            "677270632e74657374696e672e53747265616d696e674f75747075744361" .
-            "6c6c526571756573741a292e677270632e74657374696e672e5374726561" .
-            "6d696e674f757470757443616c6c526573706f6e736528013001123d0a11" .
-            "556e696d706c656d656e74656443616c6c12132e677270632e7465737469" .
-            "6e672e456d7074791a132e677270632e74657374696e672e456d70747932" .
-            "550a14556e696d706c656d656e74656453657276696365123d0a11556e69" .
-            "6d706c656d656e74656443616c6c12132e677270632e74657374696e672e" .
-            "456d7074791a132e677270632e74657374696e672e456d7074793289010a" .
-            "105265636f6e6e65637453657276696365123b0a055374617274121d2e67" .
-            "7270632e74657374696e672e5265636f6e6e656374506172616d731a132e" .
-            "677270632e74657374696e672e456d70747912380a0453746f7012132e67" .
-            "7270632e74657374696e672e456d7074791a1b2e677270632e7465737469" .
-            "6e672e5265636f6e6e656374496e666f620670726f746f33"
-        ));
+            "0aca090a217372632f70726f746f2f677270632f74657374696e672f746573742e70726f746f120c677270632e74657374696e671a257372632f70726f746f2f677270632f74657374696e672f6d657373616765732e70726f746f32e7050a0b546573745365727669636512430a09456d70747943616c6c121a2e677270632e74657374696e672e456d7074794d6573736167651a1a2e677270632e74657374696e672e456d7074794d65737361676512460a09556e61727943616c6c121b2e677270632e74657374696e672e53696d706c65526571756573741a1c2e677270632e74657374696e672e53696d706c65526573706f6e7365124f0a12436163686561626c65556e61727943616c6c121b2e677270632e74657374696e672e53696d706c65526571756573741a1c2e677270632e74657374696e672e53696d706c65526573706f6e7365126c0a1353747265616d696e674f757470757443616c6c12282e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526571756573741a292e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526573706f6e7365300112690a1253747265616d696e67496e70757443616c6c12272e677270632e74657374696e672e53747265616d696e67496e70757443616c6c526571756573741a282e677270632e74657374696e672e53747265616d696e67496e70757443616c6c526573706f6e7365280112690a0e46756c6c4475706c657843616c6c12282e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526571756573741a292e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526573706f6e73652801300112690a0e48616c664475706c657843616c6c12282e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526571756573741a292e677270632e74657374696e672e53747265616d696e674f757470757443616c6c526573706f6e736528013001124b0a11556e696d706c656d656e74656443616c6c121a2e677270632e74657374696e672e456d7074794d6573736167651a1a2e677270632e74657374696e672e456d7074794d65737361676532630a14556e696d706c656d656e74656453657276696365124b0a11556e696d706c656d656e74656443616c6c121a2e677270632e74657374696e672e456d7074794d6573736167651a1a2e677270632e74657374696e672e456d7074794d6573736167653297010a105265636f6e6e6563745365727669636512420a055374617274121d2e677270632e74657374696e672e5265636f6e6e656374506172616d731a1a2e677270632e74657374696e672e456d7074794d657373616765123f0a0453746f70121a2e677270632e74657374696e672e456d7074794d6573736167651a1b2e677270632e74657374696e672e5265636f6e6e656374496e666f327f0a184c6f616442616c616e63657253746174735365727669636512630a0e476574436c69656e74537461747312262e677270632e74657374696e672e4c6f616442616c616e6365725374617473526571756573741a272e677270632e74657374696e672e4c6f616442616c616e6365725374617473526573706f6e73652200620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
index a8a863d..e6b7f87 100644 (file)
@@ -16,19 +16,8 @@ class WorkerService
         }
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
         $pool->internalAddGeneratedFile(hex2bin(
-            "0add020a2b7372632f70726f746f2f677270632f74657374696e672f776f" .
-            "726b65725f736572766963652e70726f746f120c677270632e7465737469" .
-            "6e673297020a0d576f726b65725365727669636512450a0952756e536572" .
-            "76657212182e677270632e74657374696e672e536572766572417267731a" .
-            "1a2e677270632e74657374696e672e536572766572537461747573280130" .
-            "0112450a0952756e436c69656e7412182e677270632e74657374696e672e" .
-            "436c69656e74417267731a1a2e677270632e74657374696e672e436c6965" .
-            "6e745374617475732801300112420a09436f7265436f756e7412192e6772" .
-            "70632e74657374696e672e436f7265526571756573741a1a2e677270632e" .
-            "74657374696e672e436f7265526573706f6e736512340a0a51756974576f" .
-            "726b657212122e677270632e74657374696e672e566f69641a122e677270" .
-            "632e74657374696e672e566f6964620670726f746f33"
-        ));
+            "0add020a2b7372632f70726f746f2f677270632f74657374696e672f776f726b65725f736572766963652e70726f746f120c677270632e74657374696e673297020a0d576f726b65725365727669636512450a0952756e53657276657212182e677270632e74657374696e672e536572766572417267731a1a2e677270632e74657374696e672e5365727665725374617475732801300112450a0952756e436c69656e7412182e677270632e74657374696e672e436c69656e74417267731a1a2e677270632e74657374696e672e436c69656e745374617475732801300112420a09436f7265436f756e7412192e677270632e74657374696e672e436f7265526571756573741a1a2e677270632e74657374696e672e436f7265526573706f6e736512340a0a51756974576f726b657212122e677270632e74657374696e672e566f69641a122e677270632e74657374696e672e566f6964620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }
index 897d627..d974358 100644 (file)
@@ -16,15 +16,25 @@ class Bucket extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>double start = 1;</code>
      */
-    private $start = 0.0;
+    protected $start = 0.0;
     /**
      * Generated from protobuf field <code>uint64 count = 2;</code>
      */
-    private $count = 0;
+    protected $count = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type float $start
+     *     @type int|string $count
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Core\Stats::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 1902be8..a40319b 100644 (file)
@@ -18,9 +18,18 @@ class Histogram extends \Google\Protobuf\Internal\Message
      */
     private $buckets;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Core\Bucket[]|\Google\Protobuf\Internal\RepeatedField $buckets
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Core\Stats::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index c3581b7..d8c1e85 100644 (file)
@@ -16,12 +16,23 @@ class Metric extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>string name = 1;</code>
      */
-    private $name = '';
+    protected $name = '';
     protected $value;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *     @type int|string $count
+     *     @type \Grpc\Core\Histogram $histogram
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Core\Stats::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index e6f3fb0..482776a 100644 (file)
@@ -18,9 +18,18 @@ class Stats extends \Google\Protobuf\Internal\Message
      */
     private $metrics;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Core\Metric[]|\Google\Protobuf\Internal\RepeatedField $metrics
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Core\Stats::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index fa3e147..97819f3 100644 (file)
@@ -39,6 +39,7 @@ class BenchmarkServiceClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\SimpleRequest $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\SimpleResponse
      */
     public function UnaryCall(\Grpc\Testing\SimpleRequest $argument,
       $metadata = [], $options = []) {
@@ -54,6 +55,7 @@ class BenchmarkServiceClient extends \Grpc\BaseStub {
      * The server returns the client payload as-is on each response
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\SimpleResponse
      */
     public function StreamingCall($metadata = [], $options = []) {
         return $this->_bidiRequest('/grpc.testing.BenchmarkService/StreamingCall',
@@ -66,6 +68,7 @@ class BenchmarkServiceClient extends \Grpc\BaseStub {
      * The server returns the client payload as-is once the client does WritesDone
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\SimpleResponse
      */
     public function StreamingFromClient($metadata = [], $options = []) {
         return $this->_clientStreamRequest('/grpc.testing.BenchmarkService/StreamingFromClient',
@@ -79,6 +82,7 @@ class BenchmarkServiceClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\SimpleRequest $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\SimpleResponse
      */
     public function StreamingFromServer(\Grpc\Testing\SimpleRequest $argument,
       $metadata = [], $options = []) {
@@ -93,6 +97,7 @@ class BenchmarkServiceClient extends \Grpc\BaseStub {
      * Both sides send the content of their own choice to the other
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\SimpleResponse
      */
     public function StreamingBothWays($metadata = [], $options = []) {
         return $this->_bidiRequest('/grpc.testing.BenchmarkService/StreamingBothWays',
index 7eb364b..a1fd08d 100644 (file)
@@ -22,11 +22,21 @@ class BoolValue extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>bool value = 1;</code>
      */
-    private $value = false;
+    protected $value = false;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type bool $value
+     *           The bool value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 0511026..2a37cd2 100644 (file)
@@ -16,15 +16,25 @@ class ByteBufferParams extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>int32 req_size = 1;</code>
      */
-    private $req_size = 0;
+    protected $req_size = 0;
     /**
      * Generated from protobuf field <code>int32 resp_size = 2;</code>
      */
-    private $resp_size = 0;
+    protected $resp_size = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $req_size
+     *     @type int $resp_size
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 5c5fb86..72c1b0c 100644 (file)
@@ -16,12 +16,23 @@ class ChannelArg extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>string name = 1;</code>
      */
-    private $name = '';
+    protected $name = '';
     protected $value;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *     @type string $str_value
+     *     @type int $int_value
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index ee3fd46..9964098 100644 (file)
@@ -15,9 +15,19 @@ class ClientArgs extends \Google\Protobuf\Internal\Message
 {
     protected $argtype;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\ClientConfig $setup
+     *     @type \Grpc\Testing\Mark $mark
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 0dd3072..d14257a 100644 (file)
@@ -22,49 +22,49 @@ class ClientConfig extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>.grpc.testing.ClientType client_type = 2;</code>
      */
-    private $client_type = 0;
+    protected $client_type = 0;
     /**
      * Generated from protobuf field <code>.grpc.testing.SecurityParams security_params = 3;</code>
      */
-    private $security_params = null;
+    protected $security_params = null;
     /**
      * How many concurrent RPCs to start for each channel.
      * For synchronous client, use a separate thread for each outstanding RPC.
      *
      * Generated from protobuf field <code>int32 outstanding_rpcs_per_channel = 4;</code>
      */
-    private $outstanding_rpcs_per_channel = 0;
+    protected $outstanding_rpcs_per_channel = 0;
     /**
      * Number of independent client channels to create.
      * i-th channel will connect to server_target[i % server_targets.size()]
      *
      * Generated from protobuf field <code>int32 client_channels = 5;</code>
      */
-    private $client_channels = 0;
+    protected $client_channels = 0;
     /**
      * Only for async client. Number of threads to use to start/manage RPCs.
      *
      * Generated from protobuf field <code>int32 async_client_threads = 7;</code>
      */
-    private $async_client_threads = 0;
+    protected $async_client_threads = 0;
     /**
      * Generated from protobuf field <code>.grpc.testing.RpcType rpc_type = 8;</code>
      */
-    private $rpc_type = 0;
+    protected $rpc_type = 0;
     /**
      * The requested load for the entire client (aggregated over all the threads).
      *
      * Generated from protobuf field <code>.grpc.testing.LoadParams load_params = 10;</code>
      */
-    private $load_params = null;
+    protected $load_params = null;
     /**
      * Generated from protobuf field <code>.grpc.testing.PayloadConfig payload_config = 11;</code>
      */
-    private $payload_config = null;
+    protected $payload_config = null;
     /**
      * Generated from protobuf field <code>.grpc.testing.HistogramParams histogram_params = 12;</code>
      */
-    private $histogram_params = null;
+    protected $histogram_params = null;
     /**
      * Specify the cores we should run the client on, if desired
      *
@@ -74,13 +74,13 @@ class ClientConfig extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>int32 core_limit = 14;</code>
      */
-    private $core_limit = 0;
+    protected $core_limit = 0;
     /**
      * If we use an OTHER_CLIENT client_type, this string gives more detail
      *
      * Generated from protobuf field <code>string other_client_api = 15;</code>
      */
-    private $other_client_api = '';
+    protected $other_client_api = '';
     /**
      * Generated from protobuf field <code>repeated .grpc.testing.ChannelArg channel_args = 16;</code>
      */
@@ -90,23 +90,78 @@ class ClientConfig extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>int32 threads_per_cq = 17;</code>
      */
-    private $threads_per_cq = 0;
+    protected $threads_per_cq = 0;
     /**
      * Number of messages on a stream before it gets finished/restarted
      *
      * Generated from protobuf field <code>int32 messages_per_stream = 18;</code>
      */
-    private $messages_per_stream = 0;
+    protected $messages_per_stream = 0;
     /**
      * Use coalescing API when possible.
      *
      * Generated from protobuf field <code>bool use_coalesce_api = 19;</code>
      */
-    private $use_coalesce_api = false;
+    protected $use_coalesce_api = false;
+    /**
+     * If 0, disabled. Else, specifies the period between gathering latency
+     * medians in milliseconds.
+     *
+     * Generated from protobuf field <code>int32 median_latency_collection_interval_millis = 20;</code>
+     */
+    protected $median_latency_collection_interval_millis = 0;
+    /**
+     * Number of client processes. 0 indicates no restriction.
+     *
+     * Generated from protobuf field <code>int32 client_processes = 21;</code>
+     */
+    protected $client_processes = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string[]|\Google\Protobuf\Internal\RepeatedField $server_targets
+     *           List of targets to connect to. At least one target needs to be specified.
+     *     @type int $client_type
+     *     @type \Grpc\Testing\SecurityParams $security_params
+     *     @type int $outstanding_rpcs_per_channel
+     *           How many concurrent RPCs to start for each channel.
+     *           For synchronous client, use a separate thread for each outstanding RPC.
+     *     @type int $client_channels
+     *           Number of independent client channels to create.
+     *           i-th channel will connect to server_target[i % server_targets.size()]
+     *     @type int $async_client_threads
+     *           Only for async client. Number of threads to use to start/manage RPCs.
+     *     @type int $rpc_type
+     *     @type \Grpc\Testing\LoadParams $load_params
+     *           The requested load for the entire client (aggregated over all the threads).
+     *     @type \Grpc\Testing\PayloadConfig $payload_config
+     *     @type \Grpc\Testing\HistogramParams $histogram_params
+     *     @type int[]|\Google\Protobuf\Internal\RepeatedField $core_list
+     *           Specify the cores we should run the client on, if desired
+     *     @type int $core_limit
+     *     @type string $other_client_api
+     *           If we use an OTHER_CLIENT client_type, this string gives more detail
+     *     @type \Grpc\Testing\ChannelArg[]|\Google\Protobuf\Internal\RepeatedField $channel_args
+     *     @type int $threads_per_cq
+     *           Number of threads that share each completion queue
+     *     @type int $messages_per_stream
+     *           Number of messages on a stream before it gets finished/restarted
+     *     @type bool $use_coalesce_api
+     *           Use coalescing API when possible.
+     *     @type int $median_latency_collection_interval_millis
+     *           If 0, disabled. Else, specifies the period between gathering latency
+     *           medians in milliseconds.
+     *     @type int $client_processes
+     *           Number of client processes. 0 indicates no restriction.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
@@ -527,5 +582,59 @@ class ClientConfig extends \Google\Protobuf\Internal\Message
         return $this;
     }
 
+    /**
+     * If 0, disabled. Else, specifies the period between gathering latency
+     * medians in milliseconds.
+     *
+     * Generated from protobuf field <code>int32 median_latency_collection_interval_millis = 20;</code>
+     * @return int
+     */
+    public function getMedianLatencyCollectionIntervalMillis()
+    {
+        return $this->median_latency_collection_interval_millis;
+    }
+
+    /**
+     * If 0, disabled. Else, specifies the period between gathering latency
+     * medians in milliseconds.
+     *
+     * Generated from protobuf field <code>int32 median_latency_collection_interval_millis = 20;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setMedianLatencyCollectionIntervalMillis($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->median_latency_collection_interval_millis = $var;
+
+        return $this;
+    }
+
+    /**
+     * Number of client processes. 0 indicates no restriction.
+     *
+     * Generated from protobuf field <code>int32 client_processes = 21;</code>
+     * @return int
+     */
+    public function getClientProcesses()
+    {
+        return $this->client_processes;
+    }
+
+    /**
+     * Number of client processes. 0 indicates no restriction.
+     *
+     * Generated from protobuf field <code>int32 client_processes = 21;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setClientProcesses($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->client_processes = $var;
+
+        return $this;
+    }
+
 }
 
index f2a7621..89d241a 100644 (file)
@@ -18,21 +18,21 @@ class ClientStats extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.HistogramData latencies = 1;</code>
      */
-    private $latencies = null;
+    protected $latencies = null;
     /**
      * See ServerStats for details.
      *
      * Generated from protobuf field <code>double time_elapsed = 2;</code>
      */
-    private $time_elapsed = 0.0;
+    protected $time_elapsed = 0.0;
     /**
      * Generated from protobuf field <code>double time_user = 3;</code>
      */
-    private $time_user = 0.0;
+    protected $time_user = 0.0;
     /**
      * Generated from protobuf field <code>double time_system = 4;</code>
      */
-    private $time_system = 0.0;
+    protected $time_system = 0.0;
     /**
      * Number of failed requests (one row per status code seen)
      *
@@ -44,17 +44,37 @@ class ClientStats extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>uint64 cq_poll_count = 6;</code>
      */
-    private $cq_poll_count = 0;
+    protected $cq_poll_count = 0;
     /**
      * Core library stats
      *
      * Generated from protobuf field <code>.grpc.core.Stats core_stats = 7;</code>
      */
-    private $core_stats = null;
+    protected $core_stats = null;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\HistogramData $latencies
+     *           Latency histogram. Data points are in nanoseconds.
+     *     @type float $time_elapsed
+     *           See ServerStats for details.
+     *     @type float $time_user
+     *     @type float $time_system
+     *     @type \Grpc\Testing\RequestResultCount[]|\Google\Protobuf\Internal\RepeatedField $request_results
+     *           Number of failed requests (one row per status code seen)
+     *     @type int|string $cq_poll_count
+     *           Number of polls called inside completion queue
+     *     @type \Grpc\Core\Stats $core_stats
+     *           Core library stats
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 3ea40c4..3f87929 100644 (file)
@@ -16,11 +16,20 @@ class ClientStatus extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>.grpc.testing.ClientStats stats = 1;</code>
      */
-    private $stats = null;
+    protected $stats = null;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\ClientStats $stats
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index d1df4f1..080cb40 100644 (file)
@@ -4,8 +4,10 @@
 
 namespace Grpc\Testing;
 
+use UnexpectedValueException;
+
 /**
- * Protobuf enum <code>Grpc\Testing\ClientType</code>
+ * Protobuf type <code>grpc.testing.ClientType</code>
  */
 class ClientType
 {
@@ -26,5 +28,36 @@ class ClientType
      * Generated from protobuf enum <code>OTHER_CLIENT = 2;</code>
      */
     const OTHER_CLIENT = 2;
+    /**
+     * Generated from protobuf enum <code>CALLBACK_CLIENT = 3;</code>
+     */
+    const CALLBACK_CLIENT = 3;
+
+    private static $valueToName = [
+        self::SYNC_CLIENT => 'SYNC_CLIENT',
+        self::ASYNC_CLIENT => 'ASYNC_CLIENT',
+        self::OTHER_CLIENT => 'OTHER_CLIENT',
+        self::CALLBACK_CLIENT => 'CALLBACK_CLIENT',
+    ];
+
+    public static function name($value)
+    {
+        if (!isset(self::$valueToName[$value])) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no name defined for value %s', __CLASS__, $value));
+        }
+        return self::$valueToName[$value];
+    }
+
+
+    public static function value($name)
+    {
+        $const = __CLASS__ . '::' . strtoupper($name);
+        if (!defined($const)) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no value defined for name %s', __CLASS__, $name));
+        }
+        return constant($const);
+    }
 }
 
index 2772836..59e7cb5 100644 (file)
@@ -17,9 +17,17 @@ use Google\Protobuf\Internal\GPBUtil;
 class ClosedLoopParams extends \Google\Protobuf\Internal\Message
 {
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
 }
index b9013cd..8a6471a 100644 (file)
@@ -17,9 +17,17 @@ use Google\Protobuf\Internal\GPBUtil;
 class ComplexProtoParams extends \Google\Protobuf\Internal\Message
 {
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
 }
index 7772572..8f60530 100644 (file)
@@ -14,9 +14,17 @@ use Google\Protobuf\Internal\GPBUtil;
 class CoreRequest extends \Google\Protobuf\Internal\Message
 {
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
 }
index e0b40ee..4964375 100644 (file)
@@ -18,11 +18,21 @@ class CoreResponse extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>int32 cores = 1;</code>
      */
-    private $cores = 0;
+    protected $cores = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $cores
+     *           Number of cores available on the server
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 805b629..c12e0a0 100644 (file)
@@ -22,11 +22,21 @@ class DebugInfo extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>string detail = 2;</code>
      */
-    private $detail = '';
+    protected $detail = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string[]|\Google\Protobuf\Internal\RepeatedField $stack_entries
+     *     @type string $detail
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 9aadfc5..1ad9469 100644 (file)
@@ -16,15 +16,25 @@ class EchoRequest extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>string message = 1;</code>
      */
-    private $message = '';
+    protected $message = '';
     /**
      * Generated from protobuf field <code>.grpc.testing.RequestParams param = 2;</code>
      */
-    private $param = null;
+    protected $param = null;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $message
+     *     @type \Grpc\Testing\RequestParams $param
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index c4a9db3..47d4d9e 100644 (file)
@@ -16,15 +16,25 @@ class EchoResponse extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>string message = 1;</code>
      */
-    private $message = '';
+    protected $message = '';
     /**
      * Generated from protobuf field <code>.grpc.testing.ResponseParams param = 2;</code>
      */
-    private $param = null;
+    protected $param = null;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $message
+     *     @type \Grpc\Testing\ResponseParams $param
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 6a6623a..31fd6dd 100644 (file)
@@ -19,15 +19,25 @@ class EchoStatus extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>int32 code = 1;</code>
      */
-    private $code = 0;
+    protected $code = 0;
     /**
      * Generated from protobuf field <code>string message = 2;</code>
      */
-    private $message = '';
+    protected $message = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $code
+     *     @type string $message
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 3da163e..66e49ab 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: src/proto/grpc/testing/metrics.proto
+# source: src/proto/grpc/testing/empty.proto
 
 namespace Grpc\Testing;
 
@@ -9,14 +9,29 @@ use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
+ * 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) { };
+ *   };
+ *
  * Generated from protobuf message <code>grpc.testing.EmptyMessage</code>
  */
 class EmptyMessage extends \Google\Protobuf\Internal\Message
 {
 
-    public function __construct() {
-        \GPBMetadata\Src\Proto\Grpc\Testing\Metrics::initOnce();
-        parent::__construct();
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\PBEmpty::initOnce();
+        parent::__construct($data);
     }
 
 }
@@ -2,7 +2,7 @@
 // GENERATED CODE -- DO NOT EDIT!
 
 // Original file comments:
-// Copyright 2015 gRPC authors.
+// Copyright 2018 gRPC authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 namespace Grpc\Testing;
 
 /**
- * A service without any rpc defined to test coverage.
+ * A service that has zero methods.
+ * See https://github.com/grpc/grpc/issues/15574
  */
-class NoRpcServiceClient extends \Grpc\BaseStub {
+class EmptyServiceClient extends \Grpc\BaseStub {
 
     /**
      * @param string $hostname hostname
index cc37875..a9d12bc 100644 (file)
@@ -18,19 +18,30 @@ class ErrorStatus extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>int32 code = 1;</code>
      */
-    private $code = 0;
+    protected $code = 0;
     /**
      * Generated from protobuf field <code>string error_message = 2;</code>
      */
-    private $error_message = '';
+    protected $error_message = '';
     /**
      * Generated from protobuf field <code>string binary_error_details = 3;</code>
      */
-    private $binary_error_details = '';
+    protected $binary_error_details = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $code
+     *     @type string $error_message
+     *     @type string $binary_error_details
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/GaugeRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/GaugeRequest.php
deleted file mode 100644 (file)
index 3c28369..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: src/proto/grpc/testing/metrics.proto
-
-namespace Grpc\Testing;
-
-use Google\Protobuf\Internal\GPBType;
-use Google\Protobuf\Internal\RepeatedField;
-use Google\Protobuf\Internal\GPBUtil;
-
-/**
- * Request message containing the gauge name
- *
- * Generated from protobuf message <code>grpc.testing.GaugeRequest</code>
- */
-class GaugeRequest extends \Google\Protobuf\Internal\Message
-{
-    /**
-     * Generated from protobuf field <code>string name = 1;</code>
-     */
-    private $name = '';
-
-    public function __construct() {
-        \GPBMetadata\Src\Proto\Grpc\Testing\Metrics::initOnce();
-        parent::__construct();
-    }
-
-    /**
-     * Generated from protobuf field <code>string name = 1;</code>
-     * @return string
-     */
-    public function getName()
-    {
-        return $this->name;
-    }
-
-    /**
-     * Generated from protobuf field <code>string name = 1;</code>
-     * @param string $var
-     * @return $this
-     */
-    public function setName($var)
-    {
-        GPBUtil::checkString($var, True);
-        $this->name = $var;
-
-        return $this;
-    }
-
-}
-
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/GaugeResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/GaugeResponse.php
deleted file mode 100644 (file)
index 3969a70..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: src/proto/grpc/testing/metrics.proto
-
-namespace Grpc\Testing;
-
-use Google\Protobuf\Internal\GPBType;
-use Google\Protobuf\Internal\RepeatedField;
-use Google\Protobuf\Internal\GPBUtil;
-
-/**
- * Response message containing the gauge name and value
- *
- * Generated from protobuf message <code>grpc.testing.GaugeResponse</code>
- */
-class GaugeResponse extends \Google\Protobuf\Internal\Message
-{
-    /**
-     * Generated from protobuf field <code>string name = 1;</code>
-     */
-    private $name = '';
-    protected $value;
-
-    public function __construct() {
-        \GPBMetadata\Src\Proto\Grpc\Testing\Metrics::initOnce();
-        parent::__construct();
-    }
-
-    /**
-     * Generated from protobuf field <code>string name = 1;</code>
-     * @return string
-     */
-    public function getName()
-    {
-        return $this->name;
-    }
-
-    /**
-     * Generated from protobuf field <code>string name = 1;</code>
-     * @param string $var
-     * @return $this
-     */
-    public function setName($var)
-    {
-        GPBUtil::checkString($var, True);
-        $this->name = $var;
-
-        return $this;
-    }
-
-    /**
-     * Generated from protobuf field <code>int64 long_value = 2;</code>
-     * @return int|string
-     */
-    public function getLongValue()
-    {
-        return $this->readOneof(2);
-    }
-
-    /**
-     * Generated from protobuf field <code>int64 long_value = 2;</code>
-     * @param int|string $var
-     * @return $this
-     */
-    public function setLongValue($var)
-    {
-        GPBUtil::checkInt64($var);
-        $this->writeOneof(2, $var);
-
-        return $this;
-    }
-
-    /**
-     * Generated from protobuf field <code>double double_value = 3;</code>
-     * @return float
-     */
-    public function getDoubleValue()
-    {
-        return $this->readOneof(3);
-    }
-
-    /**
-     * Generated from protobuf field <code>double double_value = 3;</code>
-     * @param float $var
-     * @return $this
-     */
-    public function setDoubleValue($var)
-    {
-        GPBUtil::checkDouble($var);
-        $this->writeOneof(3, $var);
-
-        return $this;
-    }
-
-    /**
-     * Generated from protobuf field <code>string string_value = 4;</code>
-     * @return string
-     */
-    public function getStringValue()
-    {
-        return $this->readOneof(4);
-    }
-
-    /**
-     * Generated from protobuf field <code>string string_value = 4;</code>
-     * @param string $var
-     * @return $this
-     */
-    public function setStringValue($var)
-    {
-        GPBUtil::checkString($var, True);
-        $this->writeOneof(4, $var);
-
-        return $this;
-    }
-
-    /**
-     * @return string
-     */
-    public function getValue()
-    {
-        return $this->whichOneof("value");
-    }
-
-}
-
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/GrpclbRouteType.php b/src/php/tests/qps/generated_code/Grpc/Testing/GrpclbRouteType.php
new file mode 100644 (file)
index 0000000..f8bff1c
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use UnexpectedValueException;
+
+/**
+ * The type of route that a client took to reach a server w.r.t. gRPCLB.
+ * The server must fill in "fallback" if it detects that the RPC reached
+ * the server via the "gRPCLB fallback" path, and "backend" if it detects
+ * that the RPC reached the server via "gRPCLB backend" path (i.e. if it got
+ * the address of this server from the gRPCLB server BalanceLoad RPC). Exactly
+ * how this detection is done is context and server dependent.
+ *
+ * Protobuf type <code>grpc.testing.GrpclbRouteType</code>
+ */
+class GrpclbRouteType
+{
+    /**
+     * Server didn't detect the route that a client took to reach it.
+     *
+     * Generated from protobuf enum <code>GRPCLB_ROUTE_TYPE_UNKNOWN = 0;</code>
+     */
+    const GRPCLB_ROUTE_TYPE_UNKNOWN = 0;
+    /**
+     * Indicates that a client reached a server via gRPCLB fallback.
+     *
+     * Generated from protobuf enum <code>GRPCLB_ROUTE_TYPE_FALLBACK = 1;</code>
+     */
+    const GRPCLB_ROUTE_TYPE_FALLBACK = 1;
+    /**
+     * Indicates that a client reached a server as a gRPCLB-given backend.
+     *
+     * Generated from protobuf enum <code>GRPCLB_ROUTE_TYPE_BACKEND = 2;</code>
+     */
+    const GRPCLB_ROUTE_TYPE_BACKEND = 2;
+
+    private static $valueToName = [
+        self::GRPCLB_ROUTE_TYPE_UNKNOWN => 'GRPCLB_ROUTE_TYPE_UNKNOWN',
+        self::GRPCLB_ROUTE_TYPE_FALLBACK => 'GRPCLB_ROUTE_TYPE_FALLBACK',
+        self::GRPCLB_ROUTE_TYPE_BACKEND => 'GRPCLB_ROUTE_TYPE_BACKEND',
+    ];
+
+    public static function name($value)
+    {
+        if (!isset(self::$valueToName[$value])) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no name defined for value %s', __CLASS__, $value));
+        }
+        return self::$valueToName[$value];
+    }
+
+
+    public static function value($name)
+    {
+        $const = __CLASS__ . '::' . strtoupper($name);
+        if (!defined($const)) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no value defined for name %s', __CLASS__, $name));
+        }
+        return constant($const);
+    }
+}
+
index 136eac7..705bc83 100644 (file)
@@ -22,27 +22,41 @@ class HistogramData extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>double min_seen = 2;</code>
      */
-    private $min_seen = 0.0;
+    protected $min_seen = 0.0;
     /**
      * Generated from protobuf field <code>double max_seen = 3;</code>
      */
-    private $max_seen = 0.0;
+    protected $max_seen = 0.0;
     /**
      * Generated from protobuf field <code>double sum = 4;</code>
      */
-    private $sum = 0.0;
+    protected $sum = 0.0;
     /**
      * Generated from protobuf field <code>double sum_of_squares = 5;</code>
      */
-    private $sum_of_squares = 0.0;
+    protected $sum_of_squares = 0.0;
     /**
      * Generated from protobuf field <code>double count = 6;</code>
      */
-    private $count = 0.0;
+    protected $count = 0.0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int[]|\Google\Protobuf\Internal\RepeatedField $bucket
+     *     @type float $min_seen
+     *     @type float $max_seen
+     *     @type float $sum
+     *     @type float $sum_of_squares
+     *     @type float $count
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 1a1b484..126b0b9 100644 (file)
@@ -20,17 +20,29 @@ class HistogramParams extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>double resolution = 1;</code>
      */
-    private $resolution = 0.0;
+    protected $resolution = 0.0;
     /**
      * use enough buckets to allow this value
      *
      * Generated from protobuf field <code>double max_possible = 2;</code>
      */
-    private $max_possible = 0.0;
+    protected $max_possible = 0.0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type float $resolution
+     *           first bucket is [0, 1 + resolution)
+     *     @type float $max_possible
+     *           use enough buckets to allow this value
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/LoadBalancerStatsRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/LoadBalancerStatsRequest.php
new file mode 100644 (file)
index 0000000..02a1530
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.LoadBalancerStatsRequest</code>
+ */
+class LoadBalancerStatsRequest extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Request stats for the next num_rpcs sent by client.
+     *
+     * Generated from protobuf field <code>int32 num_rpcs = 1;</code>
+     */
+    protected $num_rpcs = 0;
+    /**
+     * If num_rpcs have not completed within timeout_sec, return partial results.
+     *
+     * Generated from protobuf field <code>int32 timeout_sec = 2;</code>
+     */
+    protected $timeout_sec = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $num_rpcs
+     *           Request stats for the next num_rpcs sent by client.
+     *     @type int $timeout_sec
+     *           If num_rpcs have not completed within timeout_sec, return partial results.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Request stats for the next num_rpcs sent by client.
+     *
+     * Generated from protobuf field <code>int32 num_rpcs = 1;</code>
+     * @return int
+     */
+    public function getNumRpcs()
+    {
+        return $this->num_rpcs;
+    }
+
+    /**
+     * Request stats for the next num_rpcs sent by client.
+     *
+     * Generated from protobuf field <code>int32 num_rpcs = 1;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setNumRpcs($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->num_rpcs = $var;
+
+        return $this;
+    }
+
+    /**
+     * If num_rpcs have not completed within timeout_sec, return partial results.
+     *
+     * Generated from protobuf field <code>int32 timeout_sec = 2;</code>
+     * @return int
+     */
+    public function getTimeoutSec()
+    {
+        return $this->timeout_sec;
+    }
+
+    /**
+     * If num_rpcs have not completed within timeout_sec, return partial results.
+     *
+     * Generated from protobuf field <code>int32 timeout_sec = 2;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setTimeoutSec($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->timeout_sec = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/LoadBalancerStatsResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/LoadBalancerStatsResponse.php
new file mode 100644 (file)
index 0000000..270189e
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.LoadBalancerStatsResponse</code>
+ */
+class LoadBalancerStatsResponse extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * The number of completed RPCs for each peer.
+     *
+     * Generated from protobuf field <code>map<string, int32> rpcs_by_peer = 1;</code>
+     */
+    private $rpcs_by_peer;
+    /**
+     * The number of RPCs that failed to record a remote peer.
+     *
+     * Generated from protobuf field <code>int32 num_failures = 2;</code>
+     */
+    protected $num_failures = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type array|\Google\Protobuf\Internal\MapField $rpcs_by_peer
+     *           The number of completed RPCs for each peer.
+     *     @type int $num_failures
+     *           The number of RPCs that failed to record a remote peer.
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * The number of completed RPCs for each peer.
+     *
+     * Generated from protobuf field <code>map<string, int32> rpcs_by_peer = 1;</code>
+     * @return \Google\Protobuf\Internal\MapField
+     */
+    public function getRpcsByPeer()
+    {
+        return $this->rpcs_by_peer;
+    }
+
+    /**
+     * The number of completed RPCs for each peer.
+     *
+     * Generated from protobuf field <code>map<string, int32> rpcs_by_peer = 1;</code>
+     * @param array|\Google\Protobuf\Internal\MapField $var
+     * @return $this
+     */
+    public function setRpcsByPeer($var)
+    {
+        $arr = GPBUtil::checkMapField($var, \Google\Protobuf\Internal\GPBType::STRING, \Google\Protobuf\Internal\GPBType::INT32);
+        $this->rpcs_by_peer = $arr;
+
+        return $this;
+    }
+
+    /**
+     * The number of RPCs that failed to record a remote peer.
+     *
+     * Generated from protobuf field <code>int32 num_failures = 2;</code>
+     * @return int
+     */
+    public function getNumFailures()
+    {
+        return $this->num_failures;
+    }
+
+    /**
+     * The number of RPCs that failed to record a remote peer.
+     *
+     * Generated from protobuf field <code>int32 num_failures = 2;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setNumFailures($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->num_failures = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/LoadBalancerStatsServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/LoadBalancerStatsServiceClient.php
new file mode 100644 (file)
index 0000000..cfbd0fd
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015-2016 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+//
+namespace Grpc\Testing;
+
+/**
+ * A service used to obtain stats for verifying LB behavior.
+ */
+class LoadBalancerStatsServiceClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * Gets the backend distribution for RPCs sent by a test client.
+     * @param \Grpc\Testing\LoadBalancerStatsRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\Testing\LoadBalancerStatsResponse
+     */
+    public function GetClientStats(\Grpc\Testing\LoadBalancerStatsRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.LoadBalancerStatsService/GetClientStats',
+        $argument,
+        ['\Grpc\Testing\LoadBalancerStatsResponse', 'decode'],
+        $metadata, $options);
+    }
+
+}
index 04c345f..0df1401 100644 (file)
@@ -15,9 +15,19 @@ class LoadParams extends \Google\Protobuf\Internal\Message
 {
     protected $load;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\ClosedLoopParams $closed_loop
+     *     @type \Grpc\Testing\PoissonParams $poisson
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index be058d5..ad97eb9 100644 (file)
@@ -20,11 +20,21 @@ class Mark extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>bool reset = 1;</code>
      */
-    private $reset = false;
+    protected $reset = false;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type bool $reset
+     *           if true, the stats will be reset after taking their snapshot.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 94cb6c1..2215f89 100644 (file)
@@ -14,9 +14,17 @@ use Google\Protobuf\Internal\GPBUtil;
 class PBVoid extends \Google\Protobuf\Internal\Message
 {
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
 }
index ad97890..65a007e 100644 (file)
@@ -16,26 +16,36 @@ use Google\Protobuf\Internal\GPBUtil;
 class Payload extends \Google\Protobuf\Internal\Message
 {
     /**
-     * DEPRECATED, don't use. To be removed shortly.
      * The type of data in body.
      *
      * Generated from protobuf field <code>.grpc.testing.PayloadType type = 1;</code>
      */
-    private $type = 0;
+    protected $type = 0;
     /**
      * Primary contents of payload.
      *
      * Generated from protobuf field <code>bytes body = 2;</code>
      */
-    private $body = '';
+    protected $body = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $type
+     *           The type of data in body.
+     *     @type string $body
+     *           Primary contents of payload.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
-     * DEPRECATED, don't use. To be removed shortly.
      * The type of data in body.
      *
      * Generated from protobuf field <code>.grpc.testing.PayloadType type = 1;</code>
@@ -47,7 +57,6 @@ class Payload extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * DEPRECATED, don't use. To be removed shortly.
      * The type of data in body.
      *
      * Generated from protobuf field <code>.grpc.testing.PayloadType type = 1;</code>
index 748f52d..495d2e1 100644 (file)
@@ -15,9 +15,20 @@ class PayloadConfig extends \Google\Protobuf\Internal\Message
 {
     protected $payload;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\ByteBufferParams $bytebuf_params
+     *     @type \Grpc\Testing\SimpleProtoParams $simple_params
+     *     @type \Grpc\Testing\ComplexProtoParams $complex_params
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index d8df1af..dc246b3 100644 (file)
@@ -4,11 +4,12 @@
 
 namespace Grpc\Testing;
 
+use UnexpectedValueException;
+
 /**
- * DEPRECATED, don't use. To be removed shortly.
  * The type of payload that should be returned.
  *
- * Protobuf enum <code>Grpc\Testing\PayloadType</code>
+ * Protobuf type <code>grpc.testing.PayloadType</code>
  */
 class PayloadType
 {
@@ -18,5 +19,29 @@ class PayloadType
      * Generated from protobuf enum <code>COMPRESSABLE = 0;</code>
      */
     const COMPRESSABLE = 0;
+
+    private static $valueToName = [
+        self::COMPRESSABLE => 'COMPRESSABLE',
+    ];
+
+    public static function name($value)
+    {
+        if (!isset(self::$valueToName[$value])) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no name defined for value %s', __CLASS__, $value));
+        }
+        return self::$valueToName[$value];
+    }
+
+
+    public static function value($name)
+    {
+        $const = __CLASS__ . '::' . strtoupper($name);
+        if (!defined($const)) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no value defined for name %s', __CLASS__, $name));
+        }
+        return constant($const);
+    }
 }
 
index 6a4047f..34a0a66 100644 (file)
@@ -21,11 +21,21 @@ class PoissonParams extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>double offered_load = 1;</code>
      */
-    private $offered_load = 0.0;
+    protected $offered_load = 0.0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type float $offered_load
+     *           The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index c0e3049..5b476ff 100644 (file)
@@ -35,6 +35,7 @@ class ProxyClientServiceClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\PBVoid $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\ClientConfig
      */
     public function GetConfig(\Grpc\Testing\PBVoid $argument,
       $metadata = [], $options = []) {
@@ -47,6 +48,7 @@ class ProxyClientServiceClient extends \Grpc\BaseStub {
     /**
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\PBVoid
      */
     public function ReportTime($metadata = [], $options = []) {
         return $this->_clientStreamRequest('/grpc.testing.ProxyClientService/ReportTime',
@@ -57,6 +59,7 @@ class ProxyClientServiceClient extends \Grpc\BaseStub {
     /**
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\PBVoid
      */
     public function ReportHist($metadata = [], $options = []) {
         return $this->_clientStreamRequest('/grpc.testing.ProxyClientService/ReportHist',
index 6fab611..f952516 100644 (file)
@@ -16,11 +16,20 @@ class ProxyStat extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>double latency = 1;</code>
      */
-    private $latency = 0.0;
+    protected $latency = 0.0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type float $latency
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\ProxyService::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index cd72870..58ac838 100644 (file)
@@ -20,15 +20,25 @@ class ReconnectInfo extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>bool passed = 1;</code>
      */
-    private $passed = false;
+    protected $passed = false;
     /**
      * Generated from protobuf field <code>repeated int32 backoff_ms = 2;</code>
      */
     private $backoff_ms;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type bool $passed
+     *     @type int[]|\Google\Protobuf\Internal\RepeatedField $backoff_ms
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index f91dc41..599b13d 100644 (file)
@@ -19,11 +19,20 @@ class ReconnectParams extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>int32 max_reconnect_backoff_ms = 1;</code>
      */
-    private $max_reconnect_backoff_ms = 0;
+    protected $max_reconnect_backoff_ms = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $max_reconnect_backoff_ms
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index a1802e9..695d83a 100644 (file)
@@ -39,21 +39,23 @@ class ReconnectServiceClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\ReconnectParams $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\EmptyMessage
      */
     public function Start(\Grpc\Testing\ReconnectParams $argument,
       $metadata = [], $options = []) {
         return $this->_simpleRequest('/grpc.testing.ReconnectService/Start',
         $argument,
-        ['\Grpc\Testing\PBEmpty', 'decode'],
+        ['\Grpc\Testing\EmptyMessage', 'decode'],
         $metadata, $options);
     }
 
     /**
-     * @param \Grpc\Testing\PBEmpty $argument input argument
+     * @param \Grpc\Testing\EmptyMessage $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\ReconnectInfo
      */
-    public function Stop(\Grpc\Testing\PBEmpty $argument,
+    public function Stop(\Grpc\Testing\EmptyMessage $argument,
       $metadata = [], $options = []) {
         return $this->_simpleRequest('/grpc.testing.ReconnectService/Stop',
         $argument,
index 3abb5ab..0238798 100644 (file)
@@ -38,6 +38,7 @@ class ReportQpsScenarioServiceClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\ScenarioResult $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\PBVoid
      */
     public function ReportScenario(\Grpc\Testing\ScenarioResult $argument,
       $metadata = [], $options = []) {
index 6a20f6a..d425141 100644 (file)
@@ -14,9 +14,17 @@ use Google\Protobuf\Internal\GPBUtil;
 class Request extends \Google\Protobuf\Internal\Message
 {
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\CompilerTest::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
 }
index f01f50d..d321a80 100644 (file)
@@ -16,73 +16,117 @@ class RequestParams extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>bool echo_deadline = 1;</code>
      */
-    private $echo_deadline = false;
+    protected $echo_deadline = false;
     /**
      * Generated from protobuf field <code>int32 client_cancel_after_us = 2;</code>
      */
-    private $client_cancel_after_us = 0;
+    protected $client_cancel_after_us = 0;
     /**
      * Generated from protobuf field <code>int32 server_cancel_after_us = 3;</code>
      */
-    private $server_cancel_after_us = 0;
+    protected $server_cancel_after_us = 0;
     /**
      * Generated from protobuf field <code>bool echo_metadata = 4;</code>
      */
-    private $echo_metadata = false;
+    protected $echo_metadata = false;
     /**
      * Generated from protobuf field <code>bool check_auth_context = 5;</code>
      */
-    private $check_auth_context = false;
+    protected $check_auth_context = false;
     /**
      * Generated from protobuf field <code>int32 response_message_length = 6;</code>
      */
-    private $response_message_length = 0;
+    protected $response_message_length = 0;
     /**
      * Generated from protobuf field <code>bool echo_peer = 7;</code>
      */
-    private $echo_peer = false;
+    protected $echo_peer = false;
     /**
      * will force check_auth_context.
      *
      * Generated from protobuf field <code>string expected_client_identity = 8;</code>
      */
-    private $expected_client_identity = '';
+    protected $expected_client_identity = '';
     /**
      * Generated from protobuf field <code>bool skip_cancelled_check = 9;</code>
      */
-    private $skip_cancelled_check = false;
+    protected $skip_cancelled_check = false;
     /**
      * Generated from protobuf field <code>string expected_transport_security_type = 10;</code>
      */
-    private $expected_transport_security_type = '';
+    protected $expected_transport_security_type = '';
     /**
      * Generated from protobuf field <code>.grpc.testing.DebugInfo debug_info = 11;</code>
      */
-    private $debug_info = null;
+    protected $debug_info = null;
     /**
      * Server should not see a request with this set.
      *
      * Generated from protobuf field <code>bool server_die = 12;</code>
      */
-    private $server_die = false;
+    protected $server_die = false;
     /**
      * Generated from protobuf field <code>string binary_error_details = 13;</code>
      */
-    private $binary_error_details = '';
+    protected $binary_error_details = '';
     /**
      * Generated from protobuf field <code>.grpc.testing.ErrorStatus expected_error = 14;</code>
      */
-    private $expected_error = null;
+    protected $expected_error = null;
     /**
-     * Amount to sleep when invoking server
+     * sleep when invoking server for deadline tests
      *
      * Generated from protobuf field <code>int32 server_sleep_us = 15;</code>
      */
-    private $server_sleep_us = 0;
+    protected $server_sleep_us = 0;
+    /**
+     * which backend to send request to
+     *
+     * Generated from protobuf field <code>int32 backend_channel_idx = 16;</code>
+     */
+    protected $backend_channel_idx = 0;
+    /**
+     * Generated from protobuf field <code>bool echo_metadata_initially = 17;</code>
+     */
+    protected $echo_metadata_initially = false;
+    /**
+     * Generated from protobuf field <code>bool server_notify_client_when_started = 18;</code>
+     */
+    protected $server_notify_client_when_started = false;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type bool $echo_deadline
+     *     @type int $client_cancel_after_us
+     *     @type int $server_cancel_after_us
+     *     @type bool $echo_metadata
+     *     @type bool $check_auth_context
+     *     @type int $response_message_length
+     *     @type bool $echo_peer
+     *     @type string $expected_client_identity
+     *           will force check_auth_context.
+     *     @type bool $skip_cancelled_check
+     *     @type string $expected_transport_security_type
+     *     @type \Grpc\Testing\DebugInfo $debug_info
+     *     @type bool $server_die
+     *           Server should not see a request with this set.
+     *     @type string $binary_error_details
+     *     @type \Grpc\Testing\ErrorStatus $expected_error
+     *     @type int $server_sleep_us
+     *           sleep when invoking server for deadline tests
+     *     @type int $backend_channel_idx
+     *           which backend to send request to
+     *     @type bool $echo_metadata_initially
+     *     @type bool $server_notify_client_when_started
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
@@ -402,7 +446,7 @@ class RequestParams extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * Amount to sleep when invoking server
+     * sleep when invoking server for deadline tests
      *
      * Generated from protobuf field <code>int32 server_sleep_us = 15;</code>
      * @return int
@@ -413,7 +457,7 @@ class RequestParams extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * Amount to sleep when invoking server
+     * sleep when invoking server for deadline tests
      *
      * Generated from protobuf field <code>int32 server_sleep_us = 15;</code>
      * @param int $var
@@ -427,5 +471,75 @@ class RequestParams extends \Google\Protobuf\Internal\Message
         return $this;
     }
 
+    /**
+     * which backend to send request to
+     *
+     * Generated from protobuf field <code>int32 backend_channel_idx = 16;</code>
+     * @return int
+     */
+    public function getBackendChannelIdx()
+    {
+        return $this->backend_channel_idx;
+    }
+
+    /**
+     * which backend to send request to
+     *
+     * Generated from protobuf field <code>int32 backend_channel_idx = 16;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setBackendChannelIdx($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->backend_channel_idx = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool echo_metadata_initially = 17;</code>
+     * @return bool
+     */
+    public function getEchoMetadataInitially()
+    {
+        return $this->echo_metadata_initially;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool echo_metadata_initially = 17;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setEchoMetadataInitially($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->echo_metadata_initially = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool server_notify_client_when_started = 18;</code>
+     * @return bool
+     */
+    public function getServerNotifyClientWhenStarted()
+    {
+        return $this->server_notify_client_when_started;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool server_notify_client_when_started = 18;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setServerNotifyClientWhenStarted($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->server_notify_client_when_started = $var;
+
+        return $this;
+    }
+
 }
 
index 75fa6ca..5bbe79f 100644 (file)
@@ -16,15 +16,25 @@ class RequestResultCount extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>int32 status_code = 1;</code>
      */
-    private $status_code = 0;
+    protected $status_code = 0;
     /**
      * Generated from protobuf field <code>int64 count = 2;</code>
      */
-    private $count = 0;
+    protected $count = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $status_code
+     *     @type int|string $count
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 7925a7d..84e93b8 100644 (file)
@@ -14,9 +14,17 @@ use Google\Protobuf\Internal\GPBUtil;
 class Response extends \Google\Protobuf\Internal\Message
 {
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\CompilerTest::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
 }
index b2f0a82..4703493 100644 (file)
@@ -20,14 +20,14 @@ class ResponseParameters extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>int32 size = 1;</code>
      */
-    private $size = 0;
+    protected $size = 0;
     /**
      * Desired interval between consecutive responses in the response stream in
      * microseconds.
      *
      * Generated from protobuf field <code>int32 interval_us = 2;</code>
      */
-    private $interval_us = 0;
+    protected $interval_us = 0;
     /**
      * Whether to request the server to compress the response. This field is
      * "nullable" in order to interoperate seamlessly with clients not able to
@@ -36,11 +36,29 @@ class ResponseParameters extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.BoolValue compressed = 3;</code>
      */
-    private $compressed = null;
+    protected $compressed = null;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $size
+     *           Desired payload sizes in responses from the server.
+     *     @type int $interval_us
+     *           Desired interval between consecutive responses in the response stream in
+     *           microseconds.
+     *     @type \Grpc\Testing\BoolValue $compressed
+     *           Whether to request the server to compress the response. This field is
+     *           "nullable" in order to interoperate seamlessly with clients not able to
+     *           implement the full compression tests by introspecting the call to verify
+     *           the response's compression status.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index d20f922..18e99b0 100644 (file)
@@ -16,19 +16,30 @@ class ResponseParams extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>int64 request_deadline = 1;</code>
      */
-    private $request_deadline = 0;
+    protected $request_deadline = 0;
     /**
      * Generated from protobuf field <code>string host = 2;</code>
      */
-    private $host = '';
+    protected $host = '';
     /**
      * Generated from protobuf field <code>string peer = 3;</code>
      */
-    private $peer = '';
+    protected $peer = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $request_deadline
+     *     @type string $host
+     *     @type string $peer
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 73a6649..559d12b 100644 (file)
@@ -4,8 +4,10 @@
 
 namespace Grpc\Testing;
 
+use UnexpectedValueException;
+
 /**
- * Protobuf enum <code>Grpc\Testing\RpcType</code>
+ * Protobuf type <code>grpc.testing.RpcType</code>
  */
 class RpcType
 {
@@ -29,5 +31,33 @@ class RpcType
      * Generated from protobuf enum <code>STREAMING_BOTH_WAYS = 4;</code>
      */
     const STREAMING_BOTH_WAYS = 4;
+
+    private static $valueToName = [
+        self::UNARY => 'UNARY',
+        self::STREAMING => 'STREAMING',
+        self::STREAMING_FROM_CLIENT => 'STREAMING_FROM_CLIENT',
+        self::STREAMING_FROM_SERVER => 'STREAMING_FROM_SERVER',
+        self::STREAMING_BOTH_WAYS => 'STREAMING_BOTH_WAYS',
+    ];
+
+    public static function name($value)
+    {
+        if (!isset(self::$valueToName[$value])) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no name defined for value %s', __CLASS__, $value));
+        }
+        return self::$valueToName[$value];
+    }
+
+
+    public static function value($name)
+    {
+        $const = __CLASS__ . '::' . strtoupper($name);
+        if (!defined($const)) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no value defined for name %s', __CLASS__, $name));
+        }
+        return constant($const);
+    }
 }
 
index 9ec284b..8c1f3fb 100644 (file)
@@ -20,53 +20,77 @@ class Scenario extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>string name = 1;</code>
      */
-    private $name = '';
+    protected $name = '';
     /**
      * Client configuration
      *
      * Generated from protobuf field <code>.grpc.testing.ClientConfig client_config = 2;</code>
      */
-    private $client_config = null;
+    protected $client_config = null;
     /**
      * Number of clients to start for the test
      *
      * Generated from protobuf field <code>int32 num_clients = 3;</code>
      */
-    private $num_clients = 0;
+    protected $num_clients = 0;
     /**
      * Server configuration
      *
      * Generated from protobuf field <code>.grpc.testing.ServerConfig server_config = 4;</code>
      */
-    private $server_config = null;
+    protected $server_config = null;
     /**
      * Number of servers to start for the test
      *
      * Generated from protobuf field <code>int32 num_servers = 5;</code>
      */
-    private $num_servers = 0;
+    protected $num_servers = 0;
     /**
      * Warmup period, in seconds
      *
      * Generated from protobuf field <code>int32 warmup_seconds = 6;</code>
      */
-    private $warmup_seconds = 0;
+    protected $warmup_seconds = 0;
     /**
      * Benchmark time, in seconds
      *
      * Generated from protobuf field <code>int32 benchmark_seconds = 7;</code>
      */
-    private $benchmark_seconds = 0;
+    protected $benchmark_seconds = 0;
     /**
      * Number of workers to spawn locally (usually zero)
      *
      * Generated from protobuf field <code>int32 spawn_local_worker_count = 8;</code>
      */
-    private $spawn_local_worker_count = 0;
+    protected $spawn_local_worker_count = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           Human readable name for this scenario
+     *     @type \Grpc\Testing\ClientConfig $client_config
+     *           Client configuration
+     *     @type int $num_clients
+     *           Number of clients to start for the test
+     *     @type \Grpc\Testing\ServerConfig $server_config
+     *           Server configuration
+     *     @type int $num_servers
+     *           Number of servers to start for the test
+     *     @type int $warmup_seconds
+     *           Warmup period, in seconds
+     *     @type int $benchmark_seconds
+     *           Benchmark time, in seconds
+     *     @type int $spawn_local_worker_count
+     *           Number of workers to spawn locally (usually zero)
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 31d9a39..a15b787 100644 (file)
@@ -20,13 +20,13 @@ class ScenarioResult extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.Scenario scenario = 1;</code>
      */
-    private $scenario = null;
+    protected $scenario = null;
     /**
      * Histograms from all clients merged into one histogram.
      *
      * Generated from protobuf field <code>.grpc.testing.HistogramData latencies = 2;</code>
      */
-    private $latencies = null;
+    protected $latencies = null;
     /**
      * Client stats for each client
      *
@@ -50,7 +50,7 @@ class ScenarioResult extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.ScenarioResultSummary summary = 6;</code>
      */
-    private $summary = null;
+    protected $summary = null;
     /**
      * Information on success or failure of each worker
      *
@@ -68,9 +68,34 @@ class ScenarioResult extends \Google\Protobuf\Internal\Message
      */
     private $request_results;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\Scenario $scenario
+     *           Inputs used to run the scenario.
+     *     @type \Grpc\Testing\HistogramData $latencies
+     *           Histograms from all clients merged into one histogram.
+     *     @type \Grpc\Testing\ClientStats[]|\Google\Protobuf\Internal\RepeatedField $client_stats
+     *           Client stats for each client
+     *     @type \Grpc\Testing\ServerStats[]|\Google\Protobuf\Internal\RepeatedField $server_stats
+     *           Server stats for each server
+     *     @type int[]|\Google\Protobuf\Internal\RepeatedField $server_cores
+     *           Number of cores available to each server
+     *     @type \Grpc\Testing\ScenarioResultSummary $summary
+     *           An after-the-fact computed summary
+     *     @type bool[]|\Google\Protobuf\Internal\RepeatedField $client_success
+     *           Information on success or failure of each worker
+     *     @type bool[]|\Google\Protobuf\Internal\RepeatedField $server_success
+     *     @type \Grpc\Testing\RequestResultCount[]|\Google\Protobuf\Internal\RepeatedField $request_results
+     *           Number of failed requests (one row per status code seen)
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index f7f1c98..2724e9c 100644 (file)
@@ -17,107 +17,156 @@ use Google\Protobuf\Internal\GPBUtil;
 class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
 {
     /**
-     * Total number of operations per second over all clients.
+     * Total number of operations per second over all clients. What is counted as 1 'operation' depends on the benchmark scenarios:
+     * For unary benchmarks, an operation is processing of a single unary RPC. 
+     * For streaming benchmarks, an operation is processing of a single ping pong of request and response. 
      *
      * Generated from protobuf field <code>double qps = 1;</code>
      */
-    private $qps = 0.0;
+    protected $qps = 0.0;
     /**
-     * QPS per one server core.
+     * QPS per server core.
      *
      * Generated from protobuf field <code>double qps_per_server_core = 2;</code>
      */
-    private $qps_per_server_core = 0.0;
+    protected $qps_per_server_core = 0.0;
     /**
-     * server load based on system_time (0.85 => 85%)
+     * The total server cpu load based on system time across all server processes, expressed as percentage of a single cpu core.
+     * For example, 85 implies 85% of a cpu core, 125 implies 125% of a cpu core. Since we are accumulating the cpu load across all the server 
+     * processes, the value could > 100 when there are multiple servers or a single server using multiple threads and cores. 
+     * Same explanation for the total client cpu load below.
      *
      * Generated from protobuf field <code>double server_system_time = 3;</code>
      */
-    private $server_system_time = 0.0;
+    protected $server_system_time = 0.0;
     /**
-     * server load based on user_time (0.85 => 85%)
+     * The total server cpu load based on user time across all server processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
      *
      * Generated from protobuf field <code>double server_user_time = 4;</code>
      */
-    private $server_user_time = 0.0;
+    protected $server_user_time = 0.0;
     /**
-     * client load based on system_time (0.85 => 85%)
+     * The total client cpu load based on system time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
      *
      * Generated from protobuf field <code>double client_system_time = 5;</code>
      */
-    private $client_system_time = 0.0;
+    protected $client_system_time = 0.0;
     /**
-     * client load based on user_time (0.85 => 85%)
+     * The total client cpu load based on user time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
      *
      * Generated from protobuf field <code>double client_user_time = 6;</code>
      */
-    private $client_user_time = 0.0;
+    protected $client_user_time = 0.0;
     /**
      * X% latency percentiles (in nanoseconds)
      *
      * Generated from protobuf field <code>double latency_50 = 7;</code>
      */
-    private $latency_50 = 0.0;
+    protected $latency_50 = 0.0;
     /**
      * Generated from protobuf field <code>double latency_90 = 8;</code>
      */
-    private $latency_90 = 0.0;
+    protected $latency_90 = 0.0;
     /**
      * Generated from protobuf field <code>double latency_95 = 9;</code>
      */
-    private $latency_95 = 0.0;
+    protected $latency_95 = 0.0;
     /**
      * Generated from protobuf field <code>double latency_99 = 10;</code>
      */
-    private $latency_99 = 0.0;
+    protected $latency_99 = 0.0;
     /**
      * Generated from protobuf field <code>double latency_999 = 11;</code>
      */
-    private $latency_999 = 0.0;
+    protected $latency_999 = 0.0;
     /**
      * server cpu usage percentage
      *
      * Generated from protobuf field <code>double server_cpu_usage = 12;</code>
      */
-    private $server_cpu_usage = 0.0;
+    protected $server_cpu_usage = 0.0;
     /**
      * Number of requests that succeeded/failed
      *
      * Generated from protobuf field <code>double successful_requests_per_second = 13;</code>
      */
-    private $successful_requests_per_second = 0.0;
+    protected $successful_requests_per_second = 0.0;
     /**
      * Generated from protobuf field <code>double failed_requests_per_second = 14;</code>
      */
-    private $failed_requests_per_second = 0.0;
+    protected $failed_requests_per_second = 0.0;
     /**
      * Number of polls called inside completion queue per request
      *
      * Generated from protobuf field <code>double client_polls_per_request = 15;</code>
      */
-    private $client_polls_per_request = 0.0;
+    protected $client_polls_per_request = 0.0;
     /**
      * Generated from protobuf field <code>double server_polls_per_request = 16;</code>
      */
-    private $server_polls_per_request = 0.0;
+    protected $server_polls_per_request = 0.0;
     /**
      * Queries per CPU-sec over all servers or clients
      *
      * Generated from protobuf field <code>double server_queries_per_cpu_sec = 17;</code>
      */
-    private $server_queries_per_cpu_sec = 0.0;
+    protected $server_queries_per_cpu_sec = 0.0;
     /**
      * Generated from protobuf field <code>double client_queries_per_cpu_sec = 18;</code>
      */
-    private $client_queries_per_cpu_sec = 0.0;
-
-    public function __construct() {
+    protected $client_queries_per_cpu_sec = 0.0;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type float $qps
+     *           Total number of operations per second over all clients. What is counted as 1 'operation' depends on the benchmark scenarios:
+     *           For unary benchmarks, an operation is processing of a single unary RPC. 
+     *           For streaming benchmarks, an operation is processing of a single ping pong of request and response. 
+     *     @type float $qps_per_server_core
+     *           QPS per server core.
+     *     @type float $server_system_time
+     *           The total server cpu load based on system time across all server processes, expressed as percentage of a single cpu core.
+     *           For example, 85 implies 85% of a cpu core, 125 implies 125% of a cpu core. Since we are accumulating the cpu load across all the server 
+     *           processes, the value could > 100 when there are multiple servers or a single server using multiple threads and cores. 
+     *           Same explanation for the total client cpu load below.
+     *     @type float $server_user_time
+     *           The total server cpu load based on user time across all server processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
+     *     @type float $client_system_time
+     *           The total client cpu load based on system time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
+     *     @type float $client_user_time
+     *           The total client cpu load based on user time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
+     *     @type float $latency_50
+     *           X% latency percentiles (in nanoseconds)
+     *     @type float $latency_90
+     *     @type float $latency_95
+     *     @type float $latency_99
+     *     @type float $latency_999
+     *     @type float $server_cpu_usage
+     *           server cpu usage percentage
+     *     @type float $successful_requests_per_second
+     *           Number of requests that succeeded/failed
+     *     @type float $failed_requests_per_second
+     *     @type float $client_polls_per_request
+     *           Number of polls called inside completion queue per request
+     *     @type float $server_polls_per_request
+     *     @type float $server_queries_per_cpu_sec
+     *           Queries per CPU-sec over all servers or clients
+     *     @type float $client_queries_per_cpu_sec
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
-     * Total number of operations per second over all clients.
+     * Total number of operations per second over all clients. What is counted as 1 'operation' depends on the benchmark scenarios:
+     * For unary benchmarks, an operation is processing of a single unary RPC. 
+     * For streaming benchmarks, an operation is processing of a single ping pong of request and response. 
      *
      * Generated from protobuf field <code>double qps = 1;</code>
      * @return float
@@ -128,7 +177,9 @@ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * Total number of operations per second over all clients.
+     * Total number of operations per second over all clients. What is counted as 1 'operation' depends on the benchmark scenarios:
+     * For unary benchmarks, an operation is processing of a single unary RPC. 
+     * For streaming benchmarks, an operation is processing of a single ping pong of request and response. 
      *
      * Generated from protobuf field <code>double qps = 1;</code>
      * @param float $var
@@ -143,7 +194,7 @@ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * QPS per one server core.
+     * QPS per server core.
      *
      * Generated from protobuf field <code>double qps_per_server_core = 2;</code>
      * @return float
@@ -154,7 +205,7 @@ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * QPS per one server core.
+     * QPS per server core.
      *
      * Generated from protobuf field <code>double qps_per_server_core = 2;</code>
      * @param float $var
@@ -169,7 +220,10 @@ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * server load based on system_time (0.85 => 85%)
+     * The total server cpu load based on system time across all server processes, expressed as percentage of a single cpu core.
+     * For example, 85 implies 85% of a cpu core, 125 implies 125% of a cpu core. Since we are accumulating the cpu load across all the server 
+     * processes, the value could > 100 when there are multiple servers or a single server using multiple threads and cores. 
+     * Same explanation for the total client cpu load below.
      *
      * Generated from protobuf field <code>double server_system_time = 3;</code>
      * @return float
@@ -180,7 +234,10 @@ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * server load based on system_time (0.85 => 85%)
+     * The total server cpu load based on system time across all server processes, expressed as percentage of a single cpu core.
+     * For example, 85 implies 85% of a cpu core, 125 implies 125% of a cpu core. Since we are accumulating the cpu load across all the server 
+     * processes, the value could > 100 when there are multiple servers or a single server using multiple threads and cores. 
+     * Same explanation for the total client cpu load below.
      *
      * Generated from protobuf field <code>double server_system_time = 3;</code>
      * @param float $var
@@ -195,7 +252,7 @@ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * server load based on user_time (0.85 => 85%)
+     * The total server cpu load based on user time across all server processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
      *
      * Generated from protobuf field <code>double server_user_time = 4;</code>
      * @return float
@@ -206,7 +263,7 @@ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * server load based on user_time (0.85 => 85%)
+     * The total server cpu load based on user time across all server processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
      *
      * Generated from protobuf field <code>double server_user_time = 4;</code>
      * @param float $var
@@ -221,7 +278,7 @@ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * client load based on system_time (0.85 => 85%)
+     * The total client cpu load based on system time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
      *
      * Generated from protobuf field <code>double client_system_time = 5;</code>
      * @return float
@@ -232,7 +289,7 @@ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * client load based on system_time (0.85 => 85%)
+     * The total client cpu load based on system time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
      *
      * Generated from protobuf field <code>double client_system_time = 5;</code>
      * @param float $var
@@ -247,7 +304,7 @@ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * client load based on user_time (0.85 => 85%)
+     * The total client cpu load based on user time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
      *
      * Generated from protobuf field <code>double client_user_time = 6;</code>
      * @return float
@@ -258,7 +315,7 @@ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * client load based on user_time (0.85 => 85%)
+     * The total client cpu load based on user time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
      *
      * Generated from protobuf field <code>double client_user_time = 6;</code>
      * @param float $var
index 2146b47..8712524 100644 (file)
@@ -20,9 +20,18 @@ class Scenarios extends \Google\Protobuf\Internal\Message
      */
     private $scenarios;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\Scenario[]|\Google\Protobuf\Internal\RepeatedField $scenarios
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 8ce623a..d54e56b 100644 (file)
@@ -18,19 +18,30 @@ class SecurityParams extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>bool use_test_ca = 1;</code>
      */
-    private $use_test_ca = false;
+    protected $use_test_ca = false;
     /**
      * Generated from protobuf field <code>string server_host_override = 2;</code>
      */
-    private $server_host_override = '';
+    protected $server_host_override = '';
     /**
      * Generated from protobuf field <code>string cred_type = 3;</code>
      */
-    private $cred_type = '';
+    protected $cred_type = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type bool $use_test_ca
+     *     @type string $server_host_override
+     *     @type string $cred_type
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index acf7e18..a6783ed 100644 (file)
@@ -15,9 +15,19 @@ class ServerArgs extends \Google\Protobuf\Internal\Message
 {
     protected $argtype;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\ServerConfig $setup
+     *     @type \Grpc\Testing\Mark $mark
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 8bd4c69..f44fa31 100644 (file)
@@ -16,29 +16,29 @@ class ServerConfig extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>.grpc.testing.ServerType server_type = 1;</code>
      */
-    private $server_type = 0;
+    protected $server_type = 0;
     /**
      * Generated from protobuf field <code>.grpc.testing.SecurityParams security_params = 2;</code>
      */
-    private $security_params = null;
+    protected $security_params = null;
     /**
      * Port on which to listen. Zero means pick unused port.
      *
      * Generated from protobuf field <code>int32 port = 4;</code>
      */
-    private $port = 0;
+    protected $port = 0;
     /**
      * Only for async server. Number of threads used to serve the requests.
      *
      * Generated from protobuf field <code>int32 async_server_threads = 7;</code>
      */
-    private $async_server_threads = 0;
+    protected $async_server_threads = 0;
     /**
      * Specify the number of cores to limit server to, if desired
      *
      * Generated from protobuf field <code>int32 core_limit = 8;</code>
      */
-    private $core_limit = 0;
+    protected $core_limit = 0;
     /**
      * payload config, used in generic server.
      * Note this must NOT be used in proto (non-generic) servers. For proto servers,
@@ -47,7 +47,7 @@ class ServerConfig extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.PayloadConfig payload_config = 9;</code>
      */
-    private $payload_config = null;
+    protected $payload_config = null;
     /**
      * Specify the cores we should run the server on, if desired
      *
@@ -59,27 +59,65 @@ class ServerConfig extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>string other_server_api = 11;</code>
      */
-    private $other_server_api = '';
+    protected $other_server_api = '';
     /**
      * Number of threads that share each completion queue
      *
      * Generated from protobuf field <code>int32 threads_per_cq = 12;</code>
      */
-    private $threads_per_cq = 0;
+    protected $threads_per_cq = 0;
     /**
      * Buffer pool size (no buffer pool specified if unset)
      *
      * Generated from protobuf field <code>int32 resource_quota_size = 1001;</code>
      */
-    private $resource_quota_size = 0;
+    protected $resource_quota_size = 0;
     /**
      * Generated from protobuf field <code>repeated .grpc.testing.ChannelArg channel_args = 1002;</code>
      */
     private $channel_args;
+    /**
+     * Number of server processes. 0 indicates no restriction.
+     *
+     * Generated from protobuf field <code>int32 server_processes = 21;</code>
+     */
+    protected $server_processes = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $server_type
+     *     @type \Grpc\Testing\SecurityParams $security_params
+     *     @type int $port
+     *           Port on which to listen. Zero means pick unused port.
+     *     @type int $async_server_threads
+     *           Only for async server. Number of threads used to serve the requests.
+     *     @type int $core_limit
+     *           Specify the number of cores to limit server to, if desired
+     *     @type \Grpc\Testing\PayloadConfig $payload_config
+     *           payload config, used in generic server.
+     *           Note this must NOT be used in proto (non-generic) servers. For proto servers,
+     *           'response sizes' must be configured from the 'response_size' field of the
+     *           'SimpleRequest' objects in RPC requests.
+     *     @type int[]|\Google\Protobuf\Internal\RepeatedField $core_list
+     *           Specify the cores we should run the server on, if desired
+     *     @type string $other_server_api
+     *           If we use an OTHER_SERVER client_type, this string gives more detail
+     *     @type int $threads_per_cq
+     *           Number of threads that share each completion queue
+     *     @type int $resource_quota_size
+     *           Buffer pool size (no buffer pool specified if unset)
+     *     @type \Grpc\Testing\ChannelArg[]|\Google\Protobuf\Internal\RepeatedField $channel_args
+     *     @type int $server_processes
+     *           Number of server processes. 0 indicates no restriction.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
@@ -362,5 +400,31 @@ class ServerConfig extends \Google\Protobuf\Internal\Message
         return $this;
     }
 
+    /**
+     * Number of server processes. 0 indicates no restriction.
+     *
+     * Generated from protobuf field <code>int32 server_processes = 21;</code>
+     * @return int
+     */
+    public function getServerProcesses()
+    {
+        return $this->server_processes;
+    }
+
+    /**
+     * Number of server processes. 0 indicates no restriction.
+     *
+     * Generated from protobuf field <code>int32 server_processes = 21;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setServerProcesses($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->server_processes = $var;
+
+        return $this;
+    }
+
 }
 
index aea2cb0..c91696d 100644 (file)
@@ -18,48 +18,71 @@ class ServerStats extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>double time_elapsed = 1;</code>
      */
-    private $time_elapsed = 0.0;
+    protected $time_elapsed = 0.0;
     /**
      * change in user time (in seconds) used by the server since last reset
      *
      * Generated from protobuf field <code>double time_user = 2;</code>
      */
-    private $time_user = 0.0;
+    protected $time_user = 0.0;
     /**
      * change in server time (in seconds) used by the server process and all
      * threads since last reset
      *
      * Generated from protobuf field <code>double time_system = 3;</code>
      */
-    private $time_system = 0.0;
+    protected $time_system = 0.0;
     /**
      * change in total cpu time of the server (data from proc/stat)
      *
      * Generated from protobuf field <code>uint64 total_cpu_time = 4;</code>
      */
-    private $total_cpu_time = 0;
+    protected $total_cpu_time = 0;
     /**
      * change in idle time of the server (data from proc/stat)
      *
      * Generated from protobuf field <code>uint64 idle_cpu_time = 5;</code>
      */
-    private $idle_cpu_time = 0;
+    protected $idle_cpu_time = 0;
     /**
      * Number of polls called inside completion queue
      *
      * Generated from protobuf field <code>uint64 cq_poll_count = 6;</code>
      */
-    private $cq_poll_count = 0;
+    protected $cq_poll_count = 0;
     /**
      * Core library stats
      *
      * Generated from protobuf field <code>.grpc.core.Stats core_stats = 7;</code>
      */
-    private $core_stats = null;
+    protected $core_stats = null;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type float $time_elapsed
+     *           wall clock time change in seconds since last reset
+     *     @type float $time_user
+     *           change in user time (in seconds) used by the server since last reset
+     *     @type float $time_system
+     *           change in server time (in seconds) used by the server process and all
+     *           threads since last reset
+     *     @type int|string $total_cpu_time
+     *           change in total cpu time of the server (data from proc/stat)
+     *     @type int|string $idle_cpu_time
+     *           change in idle time of the server (data from proc/stat)
+     *     @type int|string $cq_poll_count
+     *           Number of polls called inside completion queue
+     *     @type \Grpc\Core\Stats $core_stats
+     *           Core library stats
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 04f2ca7..ae96db0 100644 (file)
@@ -16,23 +16,36 @@ class ServerStatus extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>.grpc.testing.ServerStats stats = 1;</code>
      */
-    private $stats = null;
+    protected $stats = null;
     /**
      * the port bound by the server
      *
      * Generated from protobuf field <code>int32 port = 2;</code>
      */
-    private $port = 0;
+    protected $port = 0;
     /**
      * Number of cores available to the server
      *
      * Generated from protobuf field <code>int32 cores = 3;</code>
      */
-    private $cores = 0;
+    protected $cores = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\ServerStats $stats
+     *     @type int $port
+     *           the port bound by the server
+     *     @type int $cores
+     *           Number of cores available to the server
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 4110e91..1c2c041 100644 (file)
@@ -4,8 +4,10 @@
 
 namespace Grpc\Testing;
 
+use UnexpectedValueException;
+
 /**
- * Protobuf enum <code>Grpc\Testing\ServerType</code>
+ * Protobuf type <code>grpc.testing.ServerType</code>
  */
 class ServerType
 {
@@ -27,5 +29,37 @@ class ServerType
      * Generated from protobuf enum <code>OTHER_SERVER = 3;</code>
      */
     const OTHER_SERVER = 3;
+    /**
+     * Generated from protobuf enum <code>CALLBACK_SERVER = 4;</code>
+     */
+    const CALLBACK_SERVER = 4;
+
+    private static $valueToName = [
+        self::SYNC_SERVER => 'SYNC_SERVER',
+        self::ASYNC_SERVER => 'ASYNC_SERVER',
+        self::ASYNC_GENERIC_SERVER => 'ASYNC_GENERIC_SERVER',
+        self::OTHER_SERVER => 'OTHER_SERVER',
+        self::CALLBACK_SERVER => 'CALLBACK_SERVER',
+    ];
+
+    public static function name($value)
+    {
+        if (!isset(self::$valueToName[$value])) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no name defined for value %s', __CLASS__, $value));
+        }
+        return self::$valueToName[$value];
+    }
+
+
+    public static function value($name)
+    {
+        $const = __CLASS__ . '::' . strtoupper($name);
+        if (!defined($const)) {
+            throw new UnexpectedValueException(sprintf(
+                    'Enum %s has no value defined for name %s', __CLASS__, $name));
+        }
+        return constant($const);
+    }
 }
 
index df469cb..d946963 100644 (file)
@@ -46,6 +46,7 @@ class ServiceAClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\Request $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\Response
      */
     public function MethodA1(\Grpc\Testing\Request $argument,
       $metadata = [], $options = []) {
@@ -62,6 +63,7 @@ class ServiceAClient extends \Grpc\BaseStub {
      * Method A2 leading comment 2
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\Response
      */
     public function MethodA2($metadata = [], $options = []) {
         return $this->_clientStreamRequest('/grpc.testing.ServiceA/MethodA2',
@@ -74,6 +76,7 @@ class ServiceAClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\Request $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\Response
      */
     public function MethodA3(\Grpc\Testing\Request $argument,
       $metadata = [], $options = []) {
@@ -87,6 +90,7 @@ class ServiceAClient extends \Grpc\BaseStub {
      * Method A4 leading comment 1
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\Response
      */
     public function MethodA4($metadata = [], $options = []) {
         return $this->_bidiRequest('/grpc.testing.ServiceA/MethodA4',
index 54acf63..5090e0a 100644 (file)
@@ -42,6 +42,7 @@ class ServiceBClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\Request $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\Response
      */
     public function MethodB1(\Grpc\Testing\Request $argument,
       $metadata = [], $options = []) {
index 507db59..1edc368 100644 (file)
@@ -16,15 +16,25 @@ class SimpleProtoParams extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>int32 req_size = 1;</code>
      */
-    private $req_size = 0;
+    protected $req_size = 0;
     /**
      * Generated from protobuf field <code>int32 resp_size = 2;</code>
      */
-    private $resp_size = 0;
+    protected $resp_size = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $req_size
+     *     @type int $resp_size
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index e0c2d2d..9539365 100644 (file)
@@ -16,37 +16,36 @@ use Google\Protobuf\Internal\GPBUtil;
 class SimpleRequest extends \Google\Protobuf\Internal\Message
 {
     /**
-     * DEPRECATED, don't use. To be removed shortly.
      * Desired payload type in the response from the server.
      * If response_type is RANDOM, server randomly chooses one from other formats.
      *
      * Generated from protobuf field <code>.grpc.testing.PayloadType response_type = 1;</code>
      */
-    private $response_type = 0;
+    protected $response_type = 0;
     /**
      * Desired payload size in the response from the server.
      *
      * Generated from protobuf field <code>int32 response_size = 2;</code>
      */
-    private $response_size = 0;
+    protected $response_size = 0;
     /**
      * Optional input payload sent along with the request.
      *
      * Generated from protobuf field <code>.grpc.testing.Payload payload = 3;</code>
      */
-    private $payload = null;
+    protected $payload = null;
     /**
      * Whether SimpleResponse should include username.
      *
      * Generated from protobuf field <code>bool fill_username = 4;</code>
      */
-    private $fill_username = false;
+    protected $fill_username = false;
     /**
      * Whether SimpleResponse should include OAuth scope.
      *
      * Generated from protobuf field <code>bool fill_oauth_scope = 5;</code>
      */
-    private $fill_oauth_scope = false;
+    protected $fill_oauth_scope = false;
     /**
      * Whether to request the server to compress the response. This field is
      * "nullable" in order to interoperate seamlessly with clients not able to
@@ -55,27 +54,70 @@ class SimpleRequest extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.BoolValue response_compressed = 6;</code>
      */
-    private $response_compressed = null;
+    protected $response_compressed = null;
     /**
      * Whether server should return a given status
      *
      * Generated from protobuf field <code>.grpc.testing.EchoStatus response_status = 7;</code>
      */
-    private $response_status = null;
+    protected $response_status = null;
     /**
      * Whether the server should expect this request to be compressed.
      *
      * Generated from protobuf field <code>.grpc.testing.BoolValue expect_compressed = 8;</code>
      */
-    private $expect_compressed = null;
+    protected $expect_compressed = null;
+    /**
+     * Whether SimpleResponse should include server_id.
+     *
+     * Generated from protobuf field <code>bool fill_server_id = 9;</code>
+     */
+    protected $fill_server_id = false;
+    /**
+     * Whether SimpleResponse should include grpclb_route_type.
+     *
+     * Generated from protobuf field <code>bool fill_grpclb_route_type = 10;</code>
+     */
+    protected $fill_grpclb_route_type = false;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $response_type
+     *           Desired payload type in the response from the server.
+     *           If response_type is RANDOM, server randomly chooses one from other formats.
+     *     @type int $response_size
+     *           Desired payload size in the response from the server.
+     *     @type \Grpc\Testing\Payload $payload
+     *           Optional input payload sent along with the request.
+     *     @type bool $fill_username
+     *           Whether SimpleResponse should include username.
+     *     @type bool $fill_oauth_scope
+     *           Whether SimpleResponse should include OAuth scope.
+     *     @type \Grpc\Testing\BoolValue $response_compressed
+     *           Whether to request the server to compress the response. This field is
+     *           "nullable" in order to interoperate seamlessly with clients not able to
+     *           implement the full compression tests by introspecting the call to verify
+     *           the response's compression status.
+     *     @type \Grpc\Testing\EchoStatus $response_status
+     *           Whether server should return a given status
+     *     @type \Grpc\Testing\BoolValue $expect_compressed
+     *           Whether the server should expect this request to be compressed.
+     *     @type bool $fill_server_id
+     *           Whether SimpleResponse should include server_id.
+     *     @type bool $fill_grpclb_route_type
+     *           Whether SimpleResponse should include grpclb_route_type.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
-     * DEPRECATED, don't use. To be removed shortly.
      * Desired payload type in the response from the server.
      * If response_type is RANDOM, server randomly chooses one from other formats.
      *
@@ -88,7 +130,6 @@ class SimpleRequest extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * DEPRECATED, don't use. To be removed shortly.
      * Desired payload type in the response from the server.
      * If response_type is RANDOM, server randomly chooses one from other formats.
      *
@@ -292,5 +333,57 @@ class SimpleRequest extends \Google\Protobuf\Internal\Message
         return $this;
     }
 
+    /**
+     * Whether SimpleResponse should include server_id.
+     *
+     * Generated from protobuf field <code>bool fill_server_id = 9;</code>
+     * @return bool
+     */
+    public function getFillServerId()
+    {
+        return $this->fill_server_id;
+    }
+
+    /**
+     * Whether SimpleResponse should include server_id.
+     *
+     * Generated from protobuf field <code>bool fill_server_id = 9;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setFillServerId($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->fill_server_id = $var;
+
+        return $this;
+    }
+
+    /**
+     * Whether SimpleResponse should include grpclb_route_type.
+     *
+     * Generated from protobuf field <code>bool fill_grpclb_route_type = 10;</code>
+     * @return bool
+     */
+    public function getFillGrpclbRouteType()
+    {
+        return $this->fill_grpclb_route_type;
+    }
+
+    /**
+     * Whether SimpleResponse should include grpclb_route_type.
+     *
+     * Generated from protobuf field <code>bool fill_grpclb_route_type = 10;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setFillGrpclbRouteType($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->fill_grpclb_route_type = $var;
+
+        return $this;
+    }
+
 }
 
index d49f337..7121fc2 100644 (file)
@@ -20,24 +20,65 @@ class SimpleResponse extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
      */
-    private $payload = null;
+    protected $payload = null;
     /**
      * The user the request came from, for verifying authentication was
      * successful when the client expected it.
      *
      * Generated from protobuf field <code>string username = 2;</code>
      */
-    private $username = '';
+    protected $username = '';
     /**
      * OAuth scope.
      *
      * Generated from protobuf field <code>string oauth_scope = 3;</code>
      */
-    private $oauth_scope = '';
+    protected $oauth_scope = '';
+    /**
+     * Server ID. This must be unique among different server instances,
+     * but the same across all RPC's made to a particular server instance.
+     *
+     * Generated from protobuf field <code>string server_id = 4;</code>
+     */
+    protected $server_id = '';
+    /**
+     * gRPCLB Path.
+     *
+     * Generated from protobuf field <code>.grpc.testing.GrpclbRouteType grpclb_route_type = 5;</code>
+     */
+    protected $grpclb_route_type = 0;
+    /**
+     * Server hostname.
+     *
+     * Generated from protobuf field <code>string hostname = 6;</code>
+     */
+    protected $hostname = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\Payload $payload
+     *           Payload to increase message size.
+     *     @type string $username
+     *           The user the request came from, for verifying authentication was
+     *           successful when the client expected it.
+     *     @type string $oauth_scope
+     *           OAuth scope.
+     *     @type string $server_id
+     *           Server ID. This must be unique among different server instances,
+     *           but the same across all RPC's made to a particular server instance.
+     *     @type int $grpclb_route_type
+     *           gRPCLB Path.
+     *     @type string $hostname
+     *           Server hostname.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
@@ -120,5 +161,85 @@ class SimpleResponse extends \Google\Protobuf\Internal\Message
         return $this;
     }
 
+    /**
+     * Server ID. This must be unique among different server instances,
+     * but the same across all RPC's made to a particular server instance.
+     *
+     * Generated from protobuf field <code>string server_id = 4;</code>
+     * @return string
+     */
+    public function getServerId()
+    {
+        return $this->server_id;
+    }
+
+    /**
+     * Server ID. This must be unique among different server instances,
+     * but the same across all RPC's made to a particular server instance.
+     *
+     * Generated from protobuf field <code>string server_id = 4;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setServerId($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->server_id = $var;
+
+        return $this;
+    }
+
+    /**
+     * gRPCLB Path.
+     *
+     * Generated from protobuf field <code>.grpc.testing.GrpclbRouteType grpclb_route_type = 5;</code>
+     * @return int
+     */
+    public function getGrpclbRouteType()
+    {
+        return $this->grpclb_route_type;
+    }
+
+    /**
+     * gRPCLB Path.
+     *
+     * Generated from protobuf field <code>.grpc.testing.GrpclbRouteType grpclb_route_type = 5;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setGrpclbRouteType($var)
+    {
+        GPBUtil::checkEnum($var, \Grpc\Testing\GrpclbRouteType::class);
+        $this->grpclb_route_type = $var;
+
+        return $this;
+    }
+
+    /**
+     * Server hostname.
+     *
+     * Generated from protobuf field <code>string hostname = 6;</code>
+     * @return string
+     */
+    public function getHostname()
+    {
+        return $this->hostname;
+    }
+
+    /**
+     * Server hostname.
+     *
+     * Generated from protobuf field <code>string hostname = 6;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setHostname($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->hostname = $var;
+
+        return $this;
+    }
+
 }
 
index a7460af..00c754b 100644 (file)
@@ -20,7 +20,7 @@ class StreamingInputCallRequest extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
      */
-    private $payload = null;
+    protected $payload = null;
     /**
      * Whether the server should expect this request to be compressed. This field
      * is "nullable" in order to interoperate seamlessly with servers not able to
@@ -29,11 +29,26 @@ class StreamingInputCallRequest extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.BoolValue expect_compressed = 2;</code>
      */
-    private $expect_compressed = null;
+    protected $expect_compressed = null;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\Payload $payload
+     *           Optional input payload sent along with the request.
+     *     @type \Grpc\Testing\BoolValue $expect_compressed
+     *           Whether the server should expect this request to be compressed. This field
+     *           is "nullable" in order to interoperate seamlessly with servers not able to
+     *           implement the full compression tests by introspecting the call to verify
+     *           the request's compression status.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 41f3893..f7ff87c 100644 (file)
@@ -20,11 +20,21 @@ class StreamingInputCallResponse extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>int32 aggregated_payload_size = 1;</code>
      */
-    private $aggregated_payload_size = 0;
+    protected $aggregated_payload_size = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $aggregated_payload_size
+     *           Aggregated size of payloads received from the client.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 69d9cec..552e96d 100644 (file)
@@ -16,7 +16,6 @@ use Google\Protobuf\Internal\GPBUtil;
 class StreamingOutputCallRequest extends \Google\Protobuf\Internal\Message
 {
     /**
-     * DEPRECATED, don't use. To be removed shortly.
      * Desired payload type in the response from the server.
      * If response_type is RANDOM, the payload from each response in the stream
      * might be of different types. This is to simulate a mixed type of payload
@@ -24,7 +23,7 @@ class StreamingOutputCallRequest extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.PayloadType response_type = 1;</code>
      */
-    private $response_type = 0;
+    protected $response_type = 0;
     /**
      * Configuration for each expected response message.
      *
@@ -36,21 +35,39 @@ class StreamingOutputCallRequest extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.Payload payload = 3;</code>
      */
-    private $payload = null;
+    protected $payload = null;
     /**
      * Whether server should return a given status
      *
      * Generated from protobuf field <code>.grpc.testing.EchoStatus response_status = 7;</code>
      */
-    private $response_status = null;
+    protected $response_status = null;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $response_type
+     *           Desired payload type in the response from the server.
+     *           If response_type is RANDOM, the payload from each response in the stream
+     *           might be of different types. This is to simulate a mixed type of payload
+     *           stream.
+     *     @type \Grpc\Testing\ResponseParameters[]|\Google\Protobuf\Internal\RepeatedField $response_parameters
+     *           Configuration for each expected response message.
+     *     @type \Grpc\Testing\Payload $payload
+     *           Optional input payload sent along with the request.
+     *     @type \Grpc\Testing\EchoStatus $response_status
+     *           Whether server should return a given status
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
-     * DEPRECATED, don't use. To be removed shortly.
      * Desired payload type in the response from the server.
      * If response_type is RANDOM, the payload from each response in the stream
      * might be of different types. This is to simulate a mixed type of payload
@@ -65,7 +82,6 @@ class StreamingOutputCallRequest extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * DEPRECATED, don't use. To be removed shortly.
      * Desired payload type in the response from the server.
      * If response_type is RANDOM, the payload from each response in the stream
      * might be of different types. This is to simulate a mixed type of payload
index 52315bb..b28b906 100644 (file)
@@ -20,11 +20,21 @@ class StreamingOutputCallResponse extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>.grpc.testing.Payload payload = 1;</code>
      */
-    private $payload = null;
+    protected $payload = null;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Grpc\Testing\Payload $payload
+     *           Payload to increase response size.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
index 7da9713..770c609 100644 (file)
@@ -38,15 +38,16 @@ class TestServiceClient extends \Grpc\BaseStub {
 
     /**
      * One empty request followed by one empty response.
-     * @param \Grpc\Testing\PBEmpty $argument input argument
+     * @param \Grpc\Testing\EmptyMessage $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\EmptyMessage
      */
-    public function EmptyCall(\Grpc\Testing\PBEmpty $argument,
+    public function EmptyCall(\Grpc\Testing\EmptyMessage $argument,
       $metadata = [], $options = []) {
         return $this->_simpleRequest('/grpc.testing.TestService/EmptyCall',
         $argument,
-        ['\Grpc\Testing\PBEmpty', 'decode'],
+        ['\Grpc\Testing\EmptyMessage', 'decode'],
         $metadata, $options);
     }
 
@@ -55,6 +56,7 @@ class TestServiceClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\SimpleRequest $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\SimpleResponse
      */
     public function UnaryCall(\Grpc\Testing\SimpleRequest $argument,
       $metadata = [], $options = []) {
@@ -71,6 +73,7 @@ class TestServiceClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\SimpleRequest $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\SimpleResponse
      */
     public function CacheableUnaryCall(\Grpc\Testing\SimpleRequest $argument,
       $metadata = [], $options = []) {
@@ -86,6 +89,7 @@ class TestServiceClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\StreamingOutputCallRequest $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\StreamingOutputCallResponse
      */
     public function StreamingOutputCall(\Grpc\Testing\StreamingOutputCallRequest $argument,
       $metadata = [], $options = []) {
@@ -100,6 +104,7 @@ class TestServiceClient extends \Grpc\BaseStub {
      * The server returns the aggregated size of client payload as the result.
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\StreamingInputCallResponse
      */
     public function StreamingInputCall($metadata = [], $options = []) {
         return $this->_clientStreamRequest('/grpc.testing.TestService/StreamingInputCall',
@@ -113,6 +118,7 @@ class TestServiceClient extends \Grpc\BaseStub {
      * demonstrates the idea of full duplexing.
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\StreamingOutputCallResponse
      */
     public function FullDuplexCall($metadata = [], $options = []) {
         return $this->_bidiRequest('/grpc.testing.TestService/FullDuplexCall',
@@ -127,6 +133,7 @@ class TestServiceClient extends \Grpc\BaseStub {
      * first request.
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\StreamingOutputCallResponse
      */
     public function HalfDuplexCall($metadata = [], $options = []) {
         return $this->_bidiRequest('/grpc.testing.TestService/HalfDuplexCall',
@@ -137,15 +144,16 @@ class TestServiceClient extends \Grpc\BaseStub {
     /**
      * The test server will not implement this method. It will be used
      * to test the behavior when clients call unimplemented methods.
-     * @param \Grpc\Testing\PBEmpty $argument input argument
+     * @param \Grpc\Testing\EmptyMessage $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\EmptyMessage
      */
-    public function UnimplementedCall(\Grpc\Testing\PBEmpty $argument,
+    public function UnimplementedCall(\Grpc\Testing\EmptyMessage $argument,
       $metadata = [], $options = []) {
         return $this->_simpleRequest('/grpc.testing.TestService/UnimplementedCall',
         $argument,
-        ['\Grpc\Testing\PBEmpty', 'decode'],
+        ['\Grpc\Testing\EmptyMessage', 'decode'],
         $metadata, $options);
     }
 
index 53b2020..9988a6c 100644 (file)
@@ -38,15 +38,16 @@ class UnimplementedServiceClient extends \Grpc\BaseStub {
 
     /**
      * A call that no server should implement
-     * @param \Grpc\Testing\PBEmpty $argument input argument
+     * @param \Grpc\Testing\EmptyMessage $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\EmptyMessage
      */
-    public function UnimplementedCall(\Grpc\Testing\PBEmpty $argument,
+    public function UnimplementedCall(\Grpc\Testing\EmptyMessage $argument,
       $metadata = [], $options = []) {
         return $this->_simpleRequest('/grpc.testing.UnimplementedService/UnimplementedCall',
         $argument,
-        ['\Grpc\Testing\PBEmpty', 'decode'],
+        ['\Grpc\Testing\EmptyMessage', 'decode'],
         $metadata, $options);
     }
 
index 366e365..a2f28cd 100644 (file)
@@ -42,6 +42,7 @@ class WorkerServiceClient extends \Grpc\BaseStub {
      * this RPC.
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\ServerStatus
      */
     public function RunServer($metadata = [], $options = []) {
         return $this->_bidiRequest('/grpc.testing.WorkerService/RunServer',
@@ -58,6 +59,7 @@ class WorkerServiceClient extends \Grpc\BaseStub {
      * this RPC.
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\ClientStatus
      */
     public function RunClient($metadata = [], $options = []) {
         return $this->_bidiRequest('/grpc.testing.WorkerService/RunClient',
@@ -70,6 +72,7 @@ class WorkerServiceClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\CoreRequest $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\CoreResponse
      */
     public function CoreCount(\Grpc\Testing\CoreRequest $argument,
       $metadata = [], $options = []) {
@@ -84,6 +87,7 @@ class WorkerServiceClient extends \Grpc\BaseStub {
      * @param \Grpc\Testing\PBVoid $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
+     * @return \Grpc\Testing\PBVoid
      */
     public function QuitWorker(\Grpc\Testing\PBVoid $argument,
       $metadata = [], $options = []) {
index 0b198d8..1da43f4 100644 (file)
@@ -84,3 +84,9 @@ service LoadBalancerStatsService {
   rpc GetClientStats(LoadBalancerStatsRequest)
       returns (LoadBalancerStatsResponse) {}
 }
+
+// A service to remotely control health status of an xDS test server.
+service XdsUpdateHealthService {
+  rpc SetServing(grpc.testing.Empty) returns (grpc.testing.Empty);
+  rpc SetNotServing(grpc.testing.Empty) returns (grpc.testing.Empty);
+}
index acf2186..ec2a46b 100644 (file)
@@ -26,6 +26,7 @@ syntax = "proto3";
 package envoy.api.v2;
 
 import "google/protobuf/any.proto";
+import "google/protobuf/wrappers.proto";
 import "src/proto/grpc/testing/xds/cds_for_test.proto";
 
 
@@ -38,6 +39,15 @@ message RouteMatch {
   }
 }
 
+message WeightedCluster {
+  message ClusterWeight {
+    string name = 1;
+    google.protobuf.UInt32Value weight = 2;
+  }
+  repeated ClusterWeight clusters = 1;
+  google.protobuf.UInt32Value  total_weight = 3;
+}
+
 message RouteAction {
   oneof cluster_specifier {
     // Indicates the upstream cluster to which the request should be routed
@@ -54,6 +64,12 @@ message RouteAction {
     //   Internally, Envoy always uses the HTTP/2 *:authority* header to represent the HTTP/1
     //   *Host* header. Thus, if attempting to match on *Host*, match on *:authority* instead.
     string cluster_header = 2;
+    // Multiple upstream clusters can be specified for a given route. The
+    // request is routed to one of the upstream clusters based on weights
+    // assigned to each cluster. See
+    // :ref:`traffic splitting <config_http_conn_man_route_table_traffic_splitting_split>`
+    // for additional documentation.
+    WeightedCluster weighted_clusters = 3;
   }
 }
 
index 9d8ae26..d46d5e2 100644 (file)
@@ -166,8 +166,14 @@ message LoadStatsRequest {
 // [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs.
 message LoadStatsResponse {
   // Clusters to report stats for.
+  // Not populated if *send_all_clusters* is true.
   repeated string clusters = 1;
 
+  // If true, the client should send all clusters it knows about.
+  // Only clients that advertise the "envoy.lrs.supports_send_all_clusters" capability in their
+  // :ref:`client_features<envoy_api_field_core.Node.client_features>` field will honor this field.
+  bool send_all_clusters = 4;
+
   // The minimum interval of time to collect stats over. This is only a minimum for two reasons:
   // 1. There may be some delay from when the timer fires until stats sampling occurs.
   // 2. For clusters that were already feature in the previous *LoadStatsResponse*, any traffic
index 9fde387..fe34ad5 100644 (file)
@@ -12,10 +12,6 @@ Supported Python Versions
 -------------------------
 Python >= 3.5
 
-Deprecated Python Versions
---------------------------
-Python == 2.7. Python 2.7 support will be removed on January 1, 2020.
-
 Installation
 ------------
 
index ff799cd..303d89c 100644 (file)
@@ -414,8 +414,8 @@ class ClientCallDetails(six.with_metaclass(abc.ABCMeta)):
       metadata: Optional :term:`metadata` to be transmitted to
         the service-side of the RPC.
       credentials: An optional CallCredentials for the RPC.
-      wait_for_ready: This is an EXPERIMENTAL argument. An optional flag t
-        enable wait for ready mechanism.
+      wait_for_ready: This is an EXPERIMENTAL argument. An optional
+            flag to enable :term:`wait_for_ready` mechanism.
       compression: An element of grpc.compression, e.g.
         grpc.compression.Gzip. This is an EXPERIMENTAL option.
     """
@@ -690,7 +690,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
@@ -723,7 +723,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
@@ -756,7 +756,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
@@ -792,7 +792,7 @@ class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
@@ -828,7 +828,7 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
@@ -862,7 +862,7 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
@@ -895,7 +895,7 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
@@ -931,7 +931,7 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
@@ -1833,6 +1833,41 @@ def local_server_credentials(local_connect_type=LocalConnectionType.LOCAL_TCP):
         _cygrpc.server_credentials_local(local_connect_type.value))
 
 
+def alts_channel_credentials(service_accounts=None):
+    """Creates a ChannelCredentials for use with an ALTS-enabled Channel.
+
+    This is an EXPERIMENTAL API.
+    ALTS credentials API can only be used in GCP environment as it relies on
+    handshaker service being available. For more info about ALTS see
+    https://cloud.google.com/security/encryption-in-transit/application-layer-transport-security
+
+    Args:
+      service_accounts: A list of server identities accepted by the client.
+        If target service accounts are provided and none of them matches the
+        peer identity of the server, handshake will fail. The arg can be empty
+        if the client does not have any information about trusted server
+        identity.
+    Returns:
+      A ChannelCredentials for use with an ALTS-enabled Channel
+    """
+    return ChannelCredentials(
+        _cygrpc.channel_credentials_alts(service_accounts or []))
+
+
+def alts_server_credentials():
+    """Creates a ServerCredentials for use with an ALTS-enabled connection.
+
+    This is an EXPERIMENTAL API.
+    ALTS credentials API can only be used in GCP environment as it relies on
+    handshaker service being available. For more info about ALTS see
+    https://cloud.google.com/security/encryption-in-transit/application-layer-transport-security
+
+    Returns:
+      A ServerCredentials for use with an ALTS-enabled Server
+    """
+    return ServerCredentials(_cygrpc.server_credentials_alts())
+
+
 def channel_ready_future(channel):
     """Creates a Future that tracks when a Channel is ready.
 
@@ -1857,7 +1892,7 @@ def insecure_channel(target, options=None, compression=None):
 
     Args:
       target: The server address
-      options: An optional list of key-value pairs (channel args
+      options: An optional list of key-value pairs (:term:`channel_arguments`
         in gRPC Core runtime) to configure the channel.
       compression: An optional value indicating the compression method to be
         used over the lifetime of the channel. This is an EXPERIMENTAL option.
@@ -1878,7 +1913,7 @@ def secure_channel(target, credentials, options=None, compression=None):
     Args:
       target: The server address.
       credentials: A ChannelCredentials instance.
-      options: An optional list of key-value pairs (channel args
+      options: An optional list of key-value pairs (:term:`channel_arguments`
         in gRPC Core runtime) to configure the channel.
       compression: An optional value indicating the compression method to be
         used over the lifetime of the channel. This is an EXPERIMENTAL option.
@@ -1942,7 +1977,7 @@ def server(thread_pool,
         and optionally manipulate the incoming RPCs before handing them over to
         handlers. The interceptors are given control in the order they are
         specified. This is an EXPERIMENTAL API.
-      options: An optional list of key-value pairs (channel args in gRPC runtime)
+      options: An optional list of key-value pairs (:term:`channel_arguments` in gRPC runtime)
         to configure the channel.
       maximum_concurrent_rpcs: The maximum number of concurrent RPCs this server
         will service before returning RESOURCE_EXHAUSTED status, or None to
@@ -2036,6 +2071,8 @@ __all__ = (
     'composite_channel_credentials',
     'local_channel_credentials',
     'local_server_credentials',
+    'alts_channel_credentials',
+    'alts_server_credentials',
     'ssl_server_credentials',
     'ssl_server_certificate_configuration',
     'dynamic_ssl_server_credentials',
index f5c6656..8632ead 100644 (file)
@@ -1122,6 +1122,9 @@ class _ChannelCallState(object):
     def reset_postfork_child(self):
         self.managed_calls = 0
 
+    def __del__(self):
+        self.channel.close(cygrpc.StatusCode.cancelled, 'Channel deallocated!')
+
 
 def _run_channel_spin_thread(state):
 
index 6a170ac..27fc80b 100644 (file)
@@ -14,7 +14,6 @@
 """Shared implementation."""
 
 import logging
-
 import time
 import six
 
index 6af2499..1798bef 100644 (file)
@@ -112,3 +112,56 @@ def schedule_coro_threadsafe(object coro, object loop):
             )
         else:
             raise
+
+
+def async_generator_to_generator(object agen, object loop):
+    """Converts an async generator into generator."""
+    try:
+        while True:
+            future = asyncio.run_coroutine_threadsafe(
+                agen.__anext__(),
+                loop
+            )
+            response = future.result()
+            if response is EOF:
+                break
+            else:
+                yield response
+    except StopAsyncIteration:
+        # If StopAsyncIteration is raised, end this generator.
+        pass
+
+
+async def generator_to_async_generator(object gen, object loop, object thread_pool):
+    """Converts a generator into async generator.
+
+    The generator might block, so we need to delegate the iteration to thread
+    pool. Also, we can't simply delegate __next__ to the thread pool, otherwise
+    we will see following error:
+
+        TypeError: StopIteration interacts badly with generators and cannot be
+            raised into a Future
+    """
+    queue = asyncio.Queue(maxsize=1, loop=loop)
+
+    def yield_to_queue():
+        try:
+            for item in gen:
+                asyncio.run_coroutine_threadsafe(queue.put(item), loop).result()
+        finally:
+            asyncio.run_coroutine_threadsafe(queue.put(EOF), loop).result()
+
+    future = loop.run_in_executor(
+        thread_pool,
+        yield_to_queue,
+    )
+
+    while True:
+        response = await queue.get()
+        if response is EOF:
+            break
+        else:
+            yield response
+
+    # Port the exception if there is any
+    await future
index f5b62af..65ec0c8 100644 (file)
@@ -167,8 +167,8 @@ cdef void asyncio_socket_accept(
 
 
 cdef grpc_error* asyncio_resolve(
-        char* host,
-        char* port,
+        const char* host,
+        const char* port,
         grpc_resolved_addresses** res) with gil:
     result = native_socket.getaddrinfo(host, port)
     res[0] = tuples_to_resolvaddr(result)
@@ -176,8 +176,8 @@ cdef grpc_error* asyncio_resolve(
 
 cdef void asyncio_resolve_async(
         grpc_custom_resolver* grpc_resolver,
-        char* host,
-        char* port) with gil:
+        const char* host,
+        const char* port) with gil:
     resolver = _AsyncioResolver.create(grpc_resolver)
     resolver.resolve(host, port)
 
index 35d4e48..51730c1 100644 (file)
@@ -21,4 +21,4 @@ cdef class _AsyncioResolver:
     @staticmethod
     cdef _AsyncioResolver create(grpc_custom_resolver* grpc_resolver)
 
-    cdef void resolve(self, char* host, char* port)
+    cdef void resolve(self, const char* host, const char* port)
index 4983eab..3e66424 100644 (file)
@@ -48,7 +48,7 @@ cdef class _AsyncioResolver:
                 <grpc_error*>0
             )
 
-    cdef void resolve(self, char* host, char* port):
+    cdef void resolve(self, const char* host, const char* port):
         assert not self._task_resolve
 
         self._task_resolve = self._loop.create_task(
index 52f4916..46a47bd 100644 (file)
@@ -48,6 +48,12 @@ cdef class _ServicerContext:
     cdef object _response_serializer  # Callable[[Any], bytes]
 
 
+cdef class _SyncServicerContext:
+    cdef _ServicerContext _context
+    cdef list _callbacks
+    cdef object _loop  # asyncio.AbstractEventLoop
+
+
 cdef class _MessageReceiver:
     cdef _ServicerContext _servicer_context
     cdef object _agen
@@ -71,5 +77,7 @@ cdef class AioServer:
     cdef object _shutdown_completed  # asyncio.Future
     cdef CallbackWrapper _shutdown_callback_wrapper
     cdef object _crash_exception  # Exception
-    cdef set _ongoing_rpc_tasks
     cdef tuple _interceptors
+    cdef object _thread_pool  # concurrent.futures.ThreadPoolExecutor
+
+    cdef thread_pool(self)
index 0e40717..f37769c 100644 (file)
@@ -189,6 +189,9 @@ cdef class _ServicerContext:
 
             raise self._rpc_state.abort_exception
 
+    async def abort_with_status(self, object status):
+        await self.abort(status.code, status.details, status.trailing_metadata)
+
     def set_trailing_metadata(self, tuple metadata):
         self._rpc_state.trailing_metadata = metadata
 
@@ -211,6 +214,53 @@ cdef class _ServicerContext:
         self._rpc_state.disable_next_compression = True
 
 
+cdef class _SyncServicerContext:
+    """Sync servicer context for sync handler compatibility."""
+
+    def __cinit__(self,
+                  _ServicerContext context):
+        self._context = context
+        self._callbacks = []
+        self._loop = context._loop
+
+    def abort(self,
+              object code,
+              str details='',
+              tuple trailing_metadata=_IMMUTABLE_EMPTY_METADATA):
+        future = asyncio.run_coroutine_threadsafe(
+            self._context.abort(code, details, trailing_metadata),
+            self._loop)
+        # Abort should raise an AbortError
+        future.exception()
+
+    def send_initial_metadata(self, tuple metadata):
+        future = asyncio.run_coroutine_threadsafe(
+            self._context.send_initial_metadata(metadata),
+            self._loop)
+        future.result()
+
+    def set_trailing_metadata(self, tuple metadata):
+        self._context.set_trailing_metadata(metadata)
+
+    def invocation_metadata(self):
+        return self._context.invocation_metadata()
+
+    def set_code(self, object code):
+        self._context.set_code(code)
+
+    def set_details(self, str details):
+        self._context.set_details(details)
+
+    def set_compression(self, object compression):
+        self._context.set_compression(compression)
+
+    def disable_next_message_compression(self):
+        self._context.disable_next_message_compression()
+
+    def add_callback(self, object callback):
+        self._callbacks.append(callback)
+
+
 async def _run_interceptor(object interceptors, object query_handler,
                            object handler_call_details):
     interceptor = next(interceptors, None)
@@ -222,6 +272,11 @@ async def _run_interceptor(object interceptors, object query_handler,
         return query_handler(handler_call_details)
 
 
+def _is_async_handler(object handler):
+    """Inspect if a method handler is async or sync."""
+    return inspect.isawaitable(handler) or inspect.iscoroutinefunction(handler) or inspect.isasyncgenfunction(handler)
+
+
 async def _find_method_handler(str method, tuple metadata, list generic_handlers,
                           tuple interceptors):
     def query_handlers(handler_call_details):
@@ -254,11 +309,27 @@ async def _finish_handler_with_unary_response(RPCState rpc_state,
     stream-unary handlers.
     """
     # Executes application logic
-    
-    cdef object response_message = await unary_handler(
-        request,
-        servicer_context,
-    )
+    cdef object response_message
+    cdef _SyncServicerContext sync_servicer_context
+
+    if _is_async_handler(unary_handler):
+        # Run async method handlers in this coroutine
+        response_message = await unary_handler(
+            request,
+            servicer_context,
+        )
+    else:
+        # Run sync method handlers in the thread pool
+        sync_servicer_context = _SyncServicerContext(servicer_context)
+        response_message = await loop.run_in_executor(
+            rpc_state.server.thread_pool(),
+            unary_handler,
+            request,
+            sync_servicer_context,
+        )
+        # Support sync-stack callback
+        for callback in sync_servicer_context._callbacks:
+            callback()
 
     # Raises exception if aborted
     rpc_state.raise_for_termination()
@@ -307,18 +378,31 @@ async def _finish_handler_with_stream_responses(RPCState rpc_state,
     """
     cdef object async_response_generator
     cdef object response_message
+    
     if inspect.iscoroutinefunction(stream_handler):
+        # Case 1: Coroutine async handler - using reader-writer API
         # The handler uses reader / writer API, returns None.
         await stream_handler(
             request,
             servicer_context,
         )
     else:
-        # The handler uses async generator API
-        async_response_generator = stream_handler(
-            request,
-            servicer_context,
-        )
+        if inspect.isasyncgenfunction(stream_handler):
+            # Case 2: Async handler - async generator
+            # The handler uses async generator API
+            async_response_generator = stream_handler(
+                request,
+                servicer_context,
+            )
+        else:
+            # Case 3: Sync handler - normal generator
+            # NOTE(lidiz) Streaming handler in sync stack is either a generator
+            # function or a function returns a generator.
+            sync_servicer_context = _SyncServicerContext(servicer_context)
+            gen = stream_handler(request, sync_servicer_context)
+            async_response_generator = generator_to_async_generator(gen,
+                                                                    loop,
+                                                                    rpc_state.server.thread_pool())
 
         # Consumes messages from the generator
         async for response_message in async_response_generator:
@@ -438,6 +522,9 @@ cdef class _MessageReceiver:
             self._agen = self._async_message_receiver()
         return self._agen
 
+    async def __anext__(self):
+        return await self.__aiter__().__anext__()
+
 
 async def _handle_stream_unary_rpc(object method_handler,
                                    RPCState rpc_state,
@@ -451,13 +538,20 @@ async def _handle_stream_unary_rpc(object method_handler,
     )
 
     # Prepares the request generator
-    cdef object request_async_iterator = _MessageReceiver(servicer_context)
+    cdef object request_iterator
+    if _is_async_handler(method_handler.stream_unary):
+        request_iterator = _MessageReceiver(servicer_context)
+    else:
+        request_iterator = async_generator_to_generator(
+            _MessageReceiver(servicer_context),
+            loop
+        )
 
     # Finishes the application handler
     await _finish_handler_with_unary_response(
         rpc_state,
         method_handler.stream_unary,
-        request_async_iterator,
+        request_iterator,
         servicer_context,
         method_handler.response_serializer,
         loop
@@ -476,13 +570,20 @@ async def _handle_stream_stream_rpc(object method_handler,
     )
 
     # Prepares the request generator
-    cdef object request_async_iterator = _MessageReceiver(servicer_context)
+    cdef object request_iterator
+    if _is_async_handler(method_handler.stream_stream):
+        request_iterator = _MessageReceiver(servicer_context)
+    else:
+        request_iterator = async_generator_to_generator(
+            _MessageReceiver(servicer_context),
+            loop
+        )
 
     # Finishes the application handler
     await _finish_handler_with_stream_responses(
         rpc_state,
         method_handler.stream_stream,
-        request_async_iterator,
+        request_iterator,
         servicer_context,
         loop,
     )
@@ -591,22 +692,22 @@ async def _handle_rpc(list generic_handlers, tuple interceptors,
     # Handles unary-unary case
     if not method_handler.request_streaming and not method_handler.response_streaming:
         await _handle_unary_unary_rpc(method_handler,
-                                        rpc_state,
-                                        loop)
+                                      rpc_state,
+                                      loop)
         return
 
     # Handles unary-stream case
     if not method_handler.request_streaming and method_handler.response_streaming:
         await _handle_unary_stream_rpc(method_handler,
-                                        rpc_state,
-                                        loop)
+                                       rpc_state,
+                                       loop)
         return
 
     # Handles stream-unary case
     if method_handler.request_streaming and not method_handler.response_streaming:
         await _handle_stream_unary_rpc(method_handler,
-                                        rpc_state,
-                                        loop)
+                                       rpc_state,
+                                       loop)
         return
 
     # Handles stream-stream case
@@ -648,7 +749,6 @@ cdef class AioServer:
         self._generic_handlers = []
         self.add_generic_rpc_handlers(generic_handlers)
         self._serving_task = None
-        self._ongoing_rpc_tasks = set()
 
         self._shutdown_lock = asyncio.Lock(loop=self._loop)
         self._shutdown_completed = self._loop.create_future()
@@ -658,17 +758,18 @@ cdef class AioServer:
             SERVER_SHUTDOWN_FAILURE_HANDLER)
         self._crash_exception = None
 
-        self._interceptors = ()
         if interceptors:
             self._interceptors = interceptors
+        else:
+            self._interceptors = ()
+
+        self._thread_pool = thread_pool
+
         if maximum_concurrent_rpcs:
             raise NotImplementedError()
-        if thread_pool:
-            raise NotImplementedError()
 
-    def add_generic_rpc_handlers(self, generic_rpc_handlers):
-        for h in generic_rpc_handlers:
-            self._generic_handlers.append(h)
+    def add_generic_rpc_handlers(self, object generic_rpc_handlers):
+        self._generic_handlers.extend(generic_rpc_handlers)
 
     def add_insecure_port(self, address):
         return self._server.add_http2_port(address)
@@ -846,3 +947,7 @@ cdef class AioServer:
                 self._status
             )
         shutdown_grpc_aio()
+
+    cdef thread_pool(self):
+        """Access the thread pool instance."""
+        return self._thread_pool
index 0631e1c..ddaedb3 100644 (file)
@@ -102,3 +102,9 @@ cdef class ServerCredentials:
 cdef class LocalChannelCredentials(ChannelCredentials):
 
   cdef grpc_local_connect_type _local_connect_type
+
+
+cdef class ALTSChannelCredentials(ChannelCredentials):
+  cdef grpc_alts_credentials_options *c_options
+
+  cdef grpc_channel_credentials *c(self) except *
index 24d1e2a..0ff3706 100644 (file)
@@ -351,3 +351,32 @@ def server_credentials_local(grpc_local_connect_type local_connect_type):
   cdef ServerCredentials credentials = ServerCredentials()
   credentials.c_credentials = grpc_local_server_credentials_create(local_connect_type)
   return credentials
+
+
+cdef class ALTSChannelCredentials(ChannelCredentials):
+
+  def __cinit__(self, list service_accounts):
+    self.c_options = grpc_alts_credentials_client_options_create()
+    cdef str account
+    for account in service_accounts:
+      grpc_alts_credentials_client_options_add_target_service_account(self.c_options, account)
+  def __dealloc__(self):
+    if self.c_options != NULL:
+      grpc_alts_credentials_options_destroy(self.c_options)
+
+  cdef grpc_channel_credentials *c(self) except *:
+    return grpc_alts_credentials_create(self.c_options)
+    
+
+def channel_credentials_alts(list service_accounts):
+  return ALTSChannelCredentials(service_accounts)
+
+
+def server_credentials_alts():
+  cdef ServerCredentials credentials = ServerCredentials()
+  cdef grpc_alts_credentials_options* c_options = grpc_alts_credentials_server_options_create()
+  credentials.c_credentials = grpc_alts_server_credentials_create(c_options)
+  # Options can be destroyed as deep copy was performed.
+  grpc_alts_credentials_options_destroy(c_options)
+  return credentials
index 4a26fdc..98a71f9 100644 (file)
@@ -606,6 +606,21 @@ cdef extern from "grpc/grpc_security.h":
   grpc_server_credentials *grpc_local_server_credentials_create(
     grpc_local_connect_type type)
 
+  ctypedef struct grpc_alts_credentials_options:
+    # We don't care about the internals (and in fact don't know them)
+    pass
+  grpc_channel_credentials *grpc_alts_credentials_create(
+    const grpc_alts_credentials_options *options)
+  grpc_server_credentials *grpc_alts_server_credentials_create(
+    const grpc_alts_credentials_options *options)
+
+  grpc_alts_credentials_options* grpc_alts_credentials_client_options_create()
+  grpc_alts_credentials_options* grpc_alts_credentials_server_options_create()
+  void grpc_alts_credentials_options_destroy(grpc_alts_credentials_options *options)
+  void grpc_alts_credentials_client_options_add_target_service_account(grpc_alts_credentials_options *options, const char *service_account)
+
+
 
 cdef extern from "grpc/compression.h":
 
index 4f5033b..bd1d731 100644 (file)
@@ -37,5 +37,5 @@ cdef class SocketWrapper:
 
 cdef class ResolveWrapper:
   cdef grpc_custom_resolver *c_resolver
-  cdef char* c_host
-  cdef char* c_port
+  cdef const char* c_host
+  cdef const char* c_port
index 05e185d..0f693ec 100644 (file)
@@ -283,14 +283,14 @@ cdef socket_resolve_async_cython(ResolveWrapper resolve_wrapper):
 def socket_resolve_async_python(resolve_wrapper):
   socket_resolve_async_cython(resolve_wrapper)
 
-cdef void socket_resolve_async(grpc_custom_resolver* r, char* host, char* port) with gil:
+cdef void socket_resolve_async(grpc_custom_resolver* r, const char* host, const char* port) with gil:
   rw = ResolveWrapper()
   rw.c_resolver = r
   rw.c_host = host
   rw.c_port = port
   _spawn_greenlet(socket_resolve_async_python, rw)
 
-cdef grpc_error* socket_resolve(char* host, char* port,
+cdef grpc_error* socket_resolve(const char* host, const char* port,
                                 grpc_resolved_addresses** res) with gil:
     try:
       result = gevent_socket.getaddrinfo(host, port)
index 7bf90c3..0c5a4e5 100644 (file)
@@ -13,6 +13,9 @@
 # limitations under the License.
 # distutils: language=c++
 
+from libcpp cimport bool as bool_t
+from libcpp.string cimport string as cppstring
+
 cdef extern from "grpc/impl/codegen/slice.h":
   struct grpc_slice_buffer:
     int count
@@ -46,8 +49,8 @@ cdef extern from "src/core/lib/iomgr/resolve_address_custom.h":
     pass
 
   struct grpc_custom_resolver_vtable:
-    grpc_error* (*resolve)(char* host, char* port, grpc_resolved_addresses** res);
-    void (*resolve_async)(grpc_custom_resolver* resolver, char* host, char* port);
+    grpc_error* (*resolve)(const char* host, const char* port, grpc_resolved_addresses** res);
+    void (*resolve_async)(grpc_custom_resolver* resolver, const char* host, const char* port);
 
   void grpc_custom_resolve_callback(grpc_custom_resolver* resolver,
                                     grpc_resolved_addresses* result,
@@ -118,8 +121,8 @@ cdef extern from "src/core/lib/iomgr/iomgr_custom.h":
 
 cdef extern from "src/core/lib/iomgr/sockaddr_utils.h":
   int grpc_sockaddr_get_port(const grpc_resolved_address *addr);
-  int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *addr,
-                              int normalize);
+  cppstring grpc_sockaddr_to_string(const grpc_resolved_address *addr,
+                                    bool_t normalize);
   void grpc_string_to_sockaddr(grpc_resolved_address *out, char* addr, int port);
   int grpc_sockaddr_set_port(const grpc_resolved_address *resolved_addr,
                              int port)
index 9274f1c..3d6bb24 100644 (file)
@@ -15,6 +15,7 @@
 
 from libc cimport string
 from libc.stdlib cimport malloc
+from libcpp.string cimport string as cppstring
 
 cdef grpc_error* grpc_error_none():
   return <grpc_error*>0
@@ -25,10 +26,10 @@ cdef grpc_error* socket_error(str syscall, str err):
   return grpc_socket_error(error_bytes)
 
 cdef resolved_addr_to_tuple(grpc_resolved_address* address):
-  cdef char* res_str
+  cdef cppstring res_str
   port = grpc_sockaddr_get_port(address)
-  str_len = grpc_sockaddr_to_string(&res_str, address, 0) 
-  byte_str = _decode(<bytes>res_str[:str_len])
+  res_str = grpc_sockaddr_to_string(address, False)
+  byte_str = _decode(res_str)
   if byte_str.endswith(':' + str(port)):
     byte_str = byte_str[:(0 - len(str(port)) - 1)]
   byte_str = byte_str.lstrip('[')
index 79f291c..9da9fe3 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!!
 
-__version__ = """1.29.1"""
+__version__ = """1.30.0"""
index 3953552..202ad12 100644 (file)
@@ -196,7 +196,7 @@ def unary_unary(
         message. Request goes unserialized in case None is passed.
       response_deserializer: Optional :term:`deserializer` for deserializing the response
         message. Response goes undeserialized in case None is passed.
-      options: An optional list of key-value pairs (channel args in gRPC Core
+      options: An optional list of key-value pairs (:term:`channel_arguments` in gRPC Core
         runtime) to configure the channel.
       channel_credentials: A credential applied to the whole channel, e.g. the
         return value of grpc.ssl_channel_credentials() or
@@ -267,7 +267,7 @@ def unary_stream(
         message. Request goes unserialized in case None is passed.
       response_deserializer: Optional :term:`deserializer` for deserializing the response
         message. Response goes undeserialized in case None is passed.
-      options: An optional list of key-value pairs (channel args in gRPC Core
+      options: An optional list of key-value pairs (:term:`channel_arguments` in gRPC Core
         runtime) to configure the channel.
       channel_credentials: A credential applied to the whole channel, e.g. the
         return value of grpc.ssl_channel_credentials().
@@ -337,7 +337,7 @@ def stream_unary(
         message. Request goes unserialized in case None is passed.
       response_deserializer: Optional :term:`deserializer` for deserializing the response
         message. Response goes undeserialized in case None is passed.
-      options: An optional list of key-value pairs (channel args in gRPC Core
+      options: An optional list of key-value pairs (:term:`channel_arguments` in gRPC Core
         runtime) to configure the channel.
       channel_credentials: A credential applied to the whole channel, e.g. the
         return value of grpc.ssl_channel_credentials().
@@ -407,7 +407,7 @@ def stream_stream(
         message. Request goes unserialized in case None is passed.
       response_deserializer: Optional :term:`deserializer` for deserializing the response
         message. Response goes undeserialized in case None is passed.
-      options: An optional list of key-value pairs (channel args in gRPC Core
+      options: An optional list of key-value pairs (:term:`channel_arguments` in gRPC Core
         runtime) to configure the channel.
       channel_credentials: A credential applied to the whole channel, e.g. the
         return value of grpc.ssl_channel_credentials().
index 2c63908..eb64290 100644 (file)
@@ -16,6 +16,7 @@
 These APIs are subject to be removed during any minor version release.
 """
 
+import copy
 import functools
 import sys
 import warnings
@@ -78,11 +79,45 @@ def experimental_api(f):
     return _wrapper
 
 
+def wrap_server_method_handler(wrapper, handler):
+    """Wraps the server method handler function.
+
+    The server implementation requires all server handlers being wrapped as
+    RpcMethodHandler objects. This helper function ease the pain of writing
+    server handler wrappers.
+
+    Args:
+        wrapper: A wrapper function that takes in a method handler behavior
+          (the actual function) and returns a wrapped function.
+        handler: A RpcMethodHandler object to be wrapped.
+
+    Returns:
+        A newly created RpcMethodHandler.
+    """
+    if not handler:
+        return None
+
+    if not handler.request_streaming:
+        if not handler.response_streaming:
+            # NOTE(lidiz) _replace is a public API:
+            #   https://docs.python.org/dev/library/collections.html
+            return handler._replace(unary_unary=wrapper(handler.unary_unary))
+        else:
+            return handler._replace(unary_stream=wrapper(handler.unary_stream))
+    else:
+        if not handler.response_streaming:
+            return handler._replace(stream_unary=wrapper(handler.stream_unary))
+        else:
+            return handler._replace(
+                stream_stream=wrapper(handler.stream_stream))
+
+
 __all__ = (
     'ChannelOptions',
     'ExperimentalApiWarning',
     'UsageError',
     'insecure_channel_credentials',
+    'wrap_server_method_handler',
 )
 
 if sys.version_info[0] == 3 and sys.version_info[1] >= 6:
index 634795e..2933aa5 100644 (file)
@@ -30,8 +30,12 @@ from ._base_channel import (Channel, StreamStreamMultiCallable,
                             StreamUnaryMultiCallable, UnaryStreamMultiCallable,
                             UnaryUnaryMultiCallable)
 from ._call import AioRpcError
-from ._interceptor import (ClientCallDetails, InterceptedUnaryUnaryCall,
-                           UnaryUnaryClientInterceptor, ServerInterceptor)
+from ._interceptor import (ClientCallDetails, ClientInterceptor,
+                           InterceptedUnaryUnaryCall,
+                           UnaryUnaryClientInterceptor,
+                           UnaryStreamClientInterceptor,
+                           StreamUnaryClientInterceptor,
+                           StreamStreamClientInterceptor, ServerInterceptor)
 from ._server import server
 from ._base_server import Server, ServicerContext
 from ._typing import ChannelArgumentType
@@ -56,7 +60,11 @@ __all__ = (
     'StreamUnaryMultiCallable',
     'StreamStreamMultiCallable',
     'ClientCallDetails',
+    'ClientInterceptor',
+    'UnaryStreamClientInterceptor',
     'UnaryUnaryClientInterceptor',
+    'StreamUnaryClientInterceptor',
+    'StreamStreamClientInterceptor',
     'InterceptedUnaryUnaryCall',
     'ServerInterceptor',
     'insecure_channel',
index b6c946a..33efa77 100644 (file)
@@ -49,7 +49,7 @@ class UnaryUnaryMultiCallable(abc.ABC):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
@@ -87,7 +87,7 @@ class UnaryStreamMultiCallable(abc.ABC):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
@@ -125,7 +125,7 @@ class StreamUnaryMultiCallable(abc.ABC):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
@@ -163,7 +163,7 @@ class StreamStreamMultiCallable(abc.ABC):
           credentials: An optional CallCredentials for the RPC. Only valid for
             secure Channel.
           wait_for_ready: This is an EXPERIMENTAL argument. An optional
-            flag to enable wait for ready mechanism
+            flag to enable :term:`wait_for_ready` mechanism.
           compression: An element of grpc.compression, e.g.
             grpc.compression.Gzip. This is an EXPERIMENTAL option.
 
index 3d1d19f..a069392 100644 (file)
@@ -35,6 +35,7 @@ _LOCAL_CANCELLATION_DETAILS = 'Locally cancelled by application!'
 _GC_CANCELLATION_DETAILS = 'Cancelled upon garbage collection!'
 _RPC_ALREADY_FINISHED_DETAILS = 'RPC already finished.'
 _RPC_HALF_CLOSED_DETAILS = 'RPC is half closed after calling "done_writing".'
+_API_STYLE_ERROR = 'The iterator and read/write APIs may not be mixed on a single RPC.'
 
 _OK_CALL_REPRESENTATION = ('<{} of RPC that terminated with:\n'
                            '\tstatus = {}\n'
@@ -302,8 +303,7 @@ class _StreamResponseMixin(Call):
         if self._response_style is _APIStyle.UNKNOWN:
             self._response_style = style
         elif self._response_style is not style:
-            raise cygrpc.UsageError(
-                'Please don\'t mix two styles of API for streaming responses')
+            raise cygrpc.UsageError(_API_STYLE_ERROR)
 
     def cancel(self) -> bool:
         if super().cancel():
@@ -318,6 +318,9 @@ class _StreamResponseMixin(Call):
             yield message
             message = await self._read()
 
+        # If the read operation failed, Core should explain why.
+        await self._raise_for_status()
+
     def __aiter__(self) -> AsyncIterable[ResponseType]:
         self._update_response_style(_APIStyle.ASYNC_GENERATOR)
         if self._message_aiter is None:
@@ -378,8 +381,7 @@ class _StreamRequestMixin(Call):
 
     def _raise_for_different_style(self, style: _APIStyle):
         if self._request_style is not style:
-            raise cygrpc.UsageError(
-                'Please don\'t mix two styles of API for streaming requests')
+            raise cygrpc.UsageError(_API_STYLE_ERROR)
 
     def cancel(self) -> bool:
         if super().cancel():
@@ -396,7 +398,8 @@ class _StreamRequestMixin(Call):
                                         request_iterator: RequestIterableType
                                        ) -> None:
         try:
-            if inspect.isasyncgen(request_iterator):
+            if inspect.isasyncgen(request_iterator) or hasattr(
+                    request_iterator, '__aiter__'):
                 async for request in request_iterator:
                     await self._write(request)
             else:
@@ -423,7 +426,6 @@ class _StreamRequestMixin(Call):
 
         serialized_request = _common.serialize(request,
                                                self._request_serializer)
-
         try:
             await self._cython_call.send_serialized_message(serialized_request)
         except asyncio.CancelledError:
index 5e669e1..7427872 100644 (file)
@@ -15,7 +15,7 @@
 
 import asyncio
 import sys
-from typing import Any, Iterable, Optional, Sequence
+from typing import Any, Iterable, Optional, Sequence, List
 
 import grpc
 from grpc import _common, _compression, _grpcio_metadata
@@ -24,8 +24,11 @@ from grpc._cython import cygrpc
 from . import _base_call, _base_channel
 from ._call import (StreamStreamCall, StreamUnaryCall, UnaryStreamCall,
                     UnaryUnaryCall)
-from ._interceptor import (InterceptedUnaryUnaryCall,
-                           UnaryUnaryClientInterceptor)
+from ._interceptor import (
+    InterceptedUnaryUnaryCall, InterceptedUnaryStreamCall,
+    InterceptedStreamUnaryCall, InterceptedStreamStreamCall, ClientInterceptor,
+    UnaryUnaryClientInterceptor, UnaryStreamClientInterceptor,
+    StreamUnaryClientInterceptor, StreamStreamClientInterceptor)
 from ._typing import (ChannelArgumentType, DeserializingFunction, MetadataType,
                       SerializingFunction, RequestIterableType)
 from ._utils import _timeout_to_deadline
@@ -65,7 +68,7 @@ class _BaseMultiCallable:
     _method: bytes
     _request_serializer: SerializingFunction
     _response_deserializer: DeserializingFunction
-    _interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]]
+    _interceptors: Optional[Sequence[ClientInterceptor]]
     _loop: asyncio.AbstractEventLoop
 
     # pylint: disable=too-many-arguments
@@ -75,7 +78,7 @@ class _BaseMultiCallable:
             method: bytes,
             request_serializer: SerializingFunction,
             response_deserializer: DeserializingFunction,
-            interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]],
+            interceptors: Optional[Sequence[ClientInterceptor]],
             loop: asyncio.AbstractEventLoop,
     ) -> None:
         self._loop = loop
@@ -134,10 +137,17 @@ class UnaryStreamMultiCallable(_BaseMultiCallable,
 
         deadline = _timeout_to_deadline(timeout)
 
-        call = UnaryStreamCall(request, deadline, metadata, credentials,
-                               wait_for_ready, self._channel, self._method,
-                               self._request_serializer,
-                               self._response_deserializer, self._loop)
+        if not self._interceptors:
+            call = UnaryStreamCall(request, deadline, metadata, credentials,
+                                   wait_for_ready, self._channel, self._method,
+                                   self._request_serializer,
+                                   self._response_deserializer, self._loop)
+        else:
+            call = InterceptedUnaryStreamCall(
+                self._interceptors, request, deadline, metadata, credentials,
+                wait_for_ready, self._channel, self._method,
+                self._request_serializer, self._response_deserializer,
+                self._loop)
 
         return call
 
@@ -158,10 +168,17 @@ class StreamUnaryMultiCallable(_BaseMultiCallable,
 
         deadline = _timeout_to_deadline(timeout)
 
-        call = StreamUnaryCall(request_iterator, deadline, metadata,
-                               credentials, wait_for_ready, self._channel,
-                               self._method, self._request_serializer,
-                               self._response_deserializer, self._loop)
+        if not self._interceptors:
+            call = StreamUnaryCall(request_iterator, deadline, metadata,
+                                   credentials, wait_for_ready, self._channel,
+                                   self._method, self._request_serializer,
+                                   self._response_deserializer, self._loop)
+        else:
+            call = InterceptedStreamUnaryCall(
+                self._interceptors, request_iterator, deadline, metadata,
+                credentials, wait_for_ready, self._channel, self._method,
+                self._request_serializer, self._response_deserializer,
+                self._loop)
 
         return call
 
@@ -182,10 +199,17 @@ class StreamStreamMultiCallable(_BaseMultiCallable,
 
         deadline = _timeout_to_deadline(timeout)
 
-        call = StreamStreamCall(request_iterator, deadline, metadata,
-                                credentials, wait_for_ready, self._channel,
-                                self._method, self._request_serializer,
-                                self._response_deserializer, self._loop)
+        if not self._interceptors:
+            call = StreamStreamCall(request_iterator, deadline, metadata,
+                                    credentials, wait_for_ready, self._channel,
+                                    self._method, self._request_serializer,
+                                    self._response_deserializer, self._loop)
+        else:
+            call = InterceptedStreamStreamCall(
+                self._interceptors, request_iterator, deadline, metadata,
+                credentials, wait_for_ready, self._channel, self._method,
+                self._request_serializer, self._response_deserializer,
+                self._loop)
 
         return call
 
@@ -193,12 +217,15 @@ class StreamStreamMultiCallable(_BaseMultiCallable,
 class Channel(_base_channel.Channel):
     _loop: asyncio.AbstractEventLoop
     _channel: cygrpc.AioChannel
-    _unary_unary_interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]]
+    _unary_unary_interceptors: List[UnaryUnaryClientInterceptor]
+    _unary_stream_interceptors: List[UnaryStreamClientInterceptor]
+    _stream_unary_interceptors: List[StreamUnaryClientInterceptor]
+    _stream_stream_interceptors: List[StreamStreamClientInterceptor]
 
     def __init__(self, target: str, options: ChannelArgumentType,
                  credentials: Optional[grpc.ChannelCredentials],
                  compression: Optional[grpc.Compression],
-                 interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]]):
+                 interceptors: Optional[Sequence[ClientInterceptor]]):
         """Constructor.
 
         Args:
@@ -210,23 +237,28 @@ class Channel(_base_channel.Channel):
           interceptors: An optional list of interceptors that would be used for
             intercepting any RPC executed with that channel.
         """
-        if interceptors is None:
-            self._unary_unary_interceptors = None
-        else:
-            self._unary_unary_interceptors = list(
-                filter(
-                    lambda interceptor: isinstance(interceptor,
-                                                   UnaryUnaryClientInterceptor),
-                    interceptors))
-
-            invalid_interceptors = set(interceptors) - set(
-                self._unary_unary_interceptors)
-
-            if invalid_interceptors:
-                raise ValueError(
-                    "Interceptor must be "+\
-                    "UnaryUnaryClientInterceptors, the following are invalid: {}"\
-                    .format(invalid_interceptors))
+        self._unary_unary_interceptors = []
+        self._unary_stream_interceptors = []
+        self._stream_unary_interceptors = []
+        self._stream_stream_interceptors = []
+
+        if interceptors is not None:
+            for interceptor in interceptors:
+                if isinstance(interceptor, UnaryUnaryClientInterceptor):
+                    self._unary_unary_interceptors.append(interceptor)
+                elif isinstance(interceptor, UnaryStreamClientInterceptor):
+                    self._unary_stream_interceptors.append(interceptor)
+                elif isinstance(interceptor, StreamUnaryClientInterceptor):
+                    self._stream_unary_interceptors.append(interceptor)
+                elif isinstance(interceptor, StreamStreamClientInterceptor):
+                    self._stream_stream_interceptors.append(interceptor)
+                else:
+                    raise ValueError(
+                        "Interceptor {} must be ".format(interceptor) +
+                        "{} or ".format(UnaryUnaryClientInterceptor.__name__) +
+                        "{} or ".format(UnaryStreamClientInterceptor.__name__) +
+                        "{} or ".format(StreamUnaryClientInterceptor.__name__) +
+                        "{}. ".format(StreamStreamClientInterceptor.__name__))
 
         self._loop = asyncio.get_event_loop()
         self._channel = cygrpc.AioChannel(
@@ -352,7 +384,9 @@ class Channel(_base_channel.Channel):
     ) -> UnaryStreamMultiCallable:
         return UnaryStreamMultiCallable(self._channel, _common.encode(method),
                                         request_serializer,
-                                        response_deserializer, None, self._loop)
+                                        response_deserializer,
+                                        self._unary_stream_interceptors,
+                                        self._loop)
 
     def stream_unary(
             self,
@@ -362,7 +396,9 @@ class Channel(_base_channel.Channel):
     ) -> StreamUnaryMultiCallable:
         return StreamUnaryMultiCallable(self._channel, _common.encode(method),
                                         request_serializer,
-                                        response_deserializer, None, self._loop)
+                                        response_deserializer,
+                                        self._stream_unary_interceptors,
+                                        self._loop)
 
     def stream_stream(
             self,
@@ -372,7 +408,8 @@ class Channel(_base_channel.Channel):
     ) -> StreamStreamMultiCallable:
         return StreamStreamMultiCallable(self._channel, _common.encode(method),
                                          request_serializer,
-                                         response_deserializer, None,
+                                         response_deserializer,
+                                         self._stream_stream_interceptors,
                                          self._loop)
 
 
@@ -380,12 +417,12 @@ def insecure_channel(
         target: str,
         options: Optional[ChannelArgumentType] = None,
         compression: Optional[grpc.Compression] = None,
-        interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]] = None):
+        interceptors: Optional[Sequence[ClientInterceptor]] = None):
     """Creates an insecure asynchronous Channel to a server.
 
     Args:
       target: The server address
-      options: An optional list of key-value pairs (channel args
+      options: An optional list of key-value pairs (:term:`channel_arguments`
         in gRPC Core runtime) to configure the channel.
       compression: An optional value indicating the compression method to be
         used over the lifetime of the channel. This is an EXPERIMENTAL option.
@@ -399,18 +436,17 @@ def insecure_channel(
                    compression, interceptors)
 
 
-def secure_channel(
-        target: str,
-        credentials: grpc.ChannelCredentials,
-        options: Optional[ChannelArgumentType] = None,
-        compression: Optional[grpc.Compression] = None,
-        interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]] = None):
+def secure_channel(target: str,
+                   credentials: grpc.ChannelCredentials,
+                   options: Optional[ChannelArgumentType] = None,
+                   compression: Optional[grpc.Compression] = None,
+                   interceptors: Optional[Sequence[ClientInterceptor]] = None):
     """Creates a secure asynchronous Channel to a server.
 
     Args:
       target: The server address.
       credentials: A ChannelCredentials instance.
-      options: An optional list of key-value pairs (channel args
+      options: An optional list of key-value pairs (:term:`channel_arguments`
         in gRPC Core runtime) to configure the channel.
       compression: An optional value indicating the compression method to be
         used over the lifetime of the channel. This is an EXPERIMENTAL option.
index d4aca3a..e276ae0 100644 (file)
@@ -16,16 +16,19 @@ import asyncio
 import collections
 import functools
 from abc import ABCMeta, abstractmethod
-from typing import Callable, Optional, Iterator, Sequence, Union, Awaitable
+from typing import Callable, Optional, Iterator, Sequence, Union, Awaitable, AsyncIterable
 
 import grpc
 from grpc._cython import cygrpc
 
 from . import _base_call
-from ._call import UnaryUnaryCall, AioRpcError
+from ._call import UnaryUnaryCall, UnaryStreamCall, StreamUnaryCall, StreamStreamCall, AioRpcError
+from ._call import _RPC_ALREADY_FINISHED_DETAILS, _RPC_HALF_CLOSED_DETAILS
+from ._call import _API_STYLE_ERROR
 from ._utils import _timeout_to_deadline
 from ._typing import (RequestType, SerializingFunction, DeserializingFunction,
-                      MetadataType, ResponseType, DoneCallbackType)
+                      MetadataType, ResponseType, DoneCallbackType,
+                      RequestIterableType, ResponseIterableType)
 
 _LOCAL_CANCELLATION_DETAILS = 'Locally cancelled by application!'
 
@@ -73,8 +76,8 @@ class ClientCallDetails(
         metadata: Optional metadata to be transmitted to the service-side of
           the RPC.
         credentials: An optional CallCredentials for the RPC.
-        wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to
-          enable wait for ready mechanism.
+        wait_for_ready: This is an EXPERIMENTAL argument. An optional
+            flag to enable :term:`wait_for_ready` mechanism.
     """
 
     method: str
@@ -84,7 +87,11 @@ class ClientCallDetails(
     wait_for_ready: Optional[bool]
 
 
-class UnaryUnaryClientInterceptor(metaclass=ABCMeta):
+class ClientInterceptor(metaclass=ABCMeta):
+    """Base class used for all Aio Client Interceptor classes"""
+
+
+class UnaryUnaryClientInterceptor(ClientInterceptor, metaclass=ABCMeta):
     """Affords intercepting unary-unary invocations."""
 
     @abstractmethod
@@ -97,12 +104,12 @@ class UnaryUnaryClientInterceptor(metaclass=ABCMeta):
 
         Args:
           continuation: A coroutine that proceeds with the invocation by
-            executing the next interceptor in chain or invoking the
+            executing the next interceptor in the chain or invoking the
             actual RPC on the underlying Channel. It is the interceptor's
             responsibility to call it if it decides to move the RPC forward.
             The interceptor can use
-            `response_future = await continuation(client_call_details, request)`
-            to continue with the RPC. `continuation` returns the response of the
+            `call = await continuation(client_call_details, request)`
+            to continue with the RPC. `continuation` returns the call to the
             RPC.
           client_call_details: A ClientCallDetails object describing the
             outgoing RPC.
@@ -117,8 +124,131 @@ class UnaryUnaryClientInterceptor(metaclass=ABCMeta):
         """
 
 
-class InterceptedUnaryUnaryCall(_base_call.UnaryUnaryCall):
-    """Used for running a `UnaryUnaryCall` wrapped by interceptors.
+class UnaryStreamClientInterceptor(ClientInterceptor, metaclass=ABCMeta):
+    """Affords intercepting unary-stream invocations."""
+
+    @abstractmethod
+    async def intercept_unary_stream(
+            self, continuation: Callable[[ClientCallDetails, RequestType],
+                                         UnaryStreamCall],
+            client_call_details: ClientCallDetails, request: RequestType
+    ) -> Union[ResponseIterableType, UnaryStreamCall]:
+        """Intercepts a unary-stream invocation asynchronously.
+
+        The function could return the call object or an asynchronous
+        iterator, in case of being an asyncrhonous iterator this will
+        become the source of the reads done by the caller.
+
+        Args:
+          continuation: A coroutine that proceeds with the invocation by
+            executing the next interceptor in the chain or invoking the
+            actual RPC on the underlying Channel. It is the interceptor's
+            responsibility to call it if it decides to move the RPC forward.
+            The interceptor can use
+            `call = await continuation(client_call_details, request)`
+            to continue with the RPC. `continuation` returns the call to the
+            RPC.
+          client_call_details: A ClientCallDetails object describing the
+            outgoing RPC.
+          request: The request value for the RPC.
+
+        Returns:
+          The RPC Call or an asynchronous iterator.
+
+        Raises:
+          AioRpcError: Indicating that the RPC terminated with non-OK status.
+          asyncio.CancelledError: Indicating that the RPC was canceled.
+        """
+
+
+class StreamUnaryClientInterceptor(ClientInterceptor, metaclass=ABCMeta):
+    """Affords intercepting stream-unary invocations."""
+
+    @abstractmethod
+    async def intercept_stream_unary(
+            self,
+            continuation: Callable[[ClientCallDetails, RequestType],
+                                   UnaryStreamCall],
+            client_call_details: ClientCallDetails,
+            request_iterator: RequestIterableType,
+    ) -> StreamUnaryCall:
+        """Intercepts a stream-unary invocation asynchronously.
+
+        Within the interceptor the usage of the call methods like `write` or
+        even awaiting the call should be done carefully, since the caller
+        could be expecting an untouched call, for example for start writing
+        messages to it.
+
+        Args:
+          continuation: A coroutine that proceeds with the invocation by
+            executing the next interceptor in the chain or invoking the
+            actual RPC on the underlying Channel. It is the interceptor's
+            responsibility to call it if it decides to move the RPC forward.
+            The interceptor can use
+            `call = await continuation(client_call_details, request_iterator)`
+            to continue with the RPC. `continuation` returns the call to the
+            RPC.
+          client_call_details: A ClientCallDetails object describing the
+            outgoing RPC.
+          request_iterator: The request iterator that will produce requests
+            for the RPC.
+
+        Returns:
+          The RPC Call.
+
+        Raises:
+          AioRpcError: Indicating that the RPC terminated with non-OK status.
+          asyncio.CancelledError: Indicating that the RPC was canceled.
+        """
+
+
+class StreamStreamClientInterceptor(ClientInterceptor, metaclass=ABCMeta):
+    """Affords intercepting stream-stream invocations."""
+
+    @abstractmethod
+    async def intercept_stream_stream(
+            self,
+            continuation: Callable[[ClientCallDetails, RequestType],
+                                   UnaryStreamCall],
+            client_call_details: ClientCallDetails,
+            request_iterator: RequestIterableType,
+    ) -> Union[ResponseIterableType, StreamStreamCall]:
+        """Intercepts a stream-stream invocation asynchronously.
+
+        Within the interceptor the usage of the call methods like `write` or
+        even awaiting the call should be done carefully, since the caller
+        could be expecting an untouched call, for example for start writing
+        messages to it.
+
+        The function could return the call object or an asynchronous
+        iterator, in case of being an asyncrhonous iterator this will
+        become the source of the reads done by the caller.
+
+        Args:
+          continuation: A coroutine that proceeds with the invocation by
+            executing the next interceptor in the chain or invoking the
+            actual RPC on the underlying Channel. It is the interceptor's
+            responsibility to call it if it decides to move the RPC forward.
+            The interceptor can use
+            `call = await continuation(client_call_details, request_iterator)`
+            to continue with the RPC. `continuation` returns the call to the
+            RPC.
+          client_call_details: A ClientCallDetails object describing the
+            outgoing RPC.
+          request_iterator: The request iterator that will produce requests
+            for the RPC.
+
+        Returns:
+          The RPC Call or an asynchronous iterator.
+
+        Raises:
+          AioRpcError: Indicating that the RPC terminated with non-OK status.
+          asyncio.CancelledError: Indicating that the RPC was canceled.
+        """
+
+
+class InterceptedCall:
+    """Base implementation for all intecepted call arities.
 
     Interceptors might have some work to do before the RPC invocation with
     the capacity of changing the invocation parameters, and some work to do
@@ -133,103 +263,68 @@ class InterceptedUnaryUnaryCall(_base_call.UnaryUnaryCall):
     intercepted call, being at the same time the same call returned to the
     interceptors.
 
-    For most of the methods, like `initial_metadata()` the caller does not need
-    to wait until the interceptors task is finished, once the RPC is done the
-    caller will have the freedom for accessing to the results.
-
-    For the `__await__` method is it is proxied to the intercepted call only when
-    the interceptor task is finished.
+    As a base class for all of the interceptors implements the logic around
+    final status, metadata and cancellation.
     """
 
-    _loop: asyncio.AbstractEventLoop
-    _channel: cygrpc.AioChannel
-    _cancelled_before_rpc: bool
-    _intercepted_call: Optional[_base_call.UnaryUnaryCall]
-    _intercepted_call_created: asyncio.Event
     _interceptors_task: asyncio.Task
     _pending_add_done_callbacks: Sequence[DoneCallbackType]
 
-    # pylint: disable=too-many-arguments
-    def __init__(self, interceptors: Sequence[UnaryUnaryClientInterceptor],
-                 request: RequestType, timeout: Optional[float],
-                 metadata: MetadataType,
-                 credentials: Optional[grpc.CallCredentials],
-                 wait_for_ready: Optional[bool], channel: cygrpc.AioChannel,
-                 method: bytes, request_serializer: SerializingFunction,
-                 response_deserializer: DeserializingFunction,
-                 loop: asyncio.AbstractEventLoop) -> None:
-        self._channel = channel
-        self._loop = loop
-        self._interceptors_task = loop.create_task(
-            self._invoke(interceptors, method, timeout, metadata, credentials,
-                         wait_for_ready, request, request_serializer,
-                         response_deserializer))
+    def __init__(self, interceptors_task: asyncio.Task) -> None:
+        self._interceptors_task = interceptors_task
         self._pending_add_done_callbacks = []
         self._interceptors_task.add_done_callback(
-            self._fire_pending_add_done_callbacks)
+            self._fire_or_add_pending_done_callbacks)
 
     def __del__(self):
         self.cancel()
 
-    # pylint: disable=too-many-arguments
-    async def _invoke(self, interceptors: Sequence[UnaryUnaryClientInterceptor],
-                      method: bytes, timeout: Optional[float],
-                      metadata: Optional[MetadataType],
-                      credentials: Optional[grpc.CallCredentials],
-                      wait_for_ready: Optional[bool], request: RequestType,
-                      request_serializer: SerializingFunction,
-                      response_deserializer: DeserializingFunction
-                     ) -> UnaryUnaryCall:
-        """Run the RPC call wrapped in interceptors"""
-
-        async def _run_interceptor(
-                interceptors: Iterator[UnaryUnaryClientInterceptor],
-                client_call_details: ClientCallDetails,
-                request: RequestType) -> _base_call.UnaryUnaryCall:
-
-            interceptor = next(interceptors, None)
-
-            if interceptor:
-                continuation = functools.partial(_run_interceptor, interceptors)
-
-                call_or_response = await interceptor.intercept_unary_unary(
-                    continuation, client_call_details, request)
+    def _fire_or_add_pending_done_callbacks(self,
+                                            interceptors_task: asyncio.Task
+                                           ) -> None:
 
-                if isinstance(call_or_response, _base_call.UnaryUnaryCall):
-                    return call_or_response
-                else:
-                    return UnaryUnaryCallResponse(call_or_response)
+        if not self._pending_add_done_callbacks:
+            return
 
-            else:
-                return UnaryUnaryCall(
-                    request, _timeout_to_deadline(client_call_details.timeout),
-                    client_call_details.metadata,
-                    client_call_details.credentials,
-                    client_call_details.wait_for_ready, self._channel,
-                    client_call_details.method, request_serializer,
-                    response_deserializer, self._loop)
+        call_completed = False
 
-        client_call_details = ClientCallDetails(method, timeout, metadata,
-                                                credentials, wait_for_ready)
-        return await _run_interceptor(iter(interceptors), client_call_details,
-                                      request)
+        try:
+            call = interceptors_task.result()
+            if call.done():
+                call_completed = True
+        except (AioRpcError, asyncio.CancelledError):
+            call_completed = True
 
-    def _fire_pending_add_done_callbacks(self,
-                                         unused_task: asyncio.Task) -> None:
-        for callback in self._pending_add_done_callbacks:
-            callback(self)
+        if call_completed:
+            for callback in self._pending_add_done_callbacks:
+                callback(self)
+        else:
+            for callback in self._pending_add_done_callbacks:
+                callback = functools.partial(self._wrap_add_done_callback,
+                                             callback)
+                call.add_done_callback(callback)
 
         self._pending_add_done_callbacks = []
 
     def _wrap_add_done_callback(self, callback: DoneCallbackType,
-                                unused_task: asyncio.Task) -> None:
+                                unused_call: _base_call.Call) -> None:
         callback(self)
 
     def cancel(self) -> bool:
-        if self._interceptors_task.done():
+        if not self._interceptors_task.done():
+            # There is no yet the intercepted call available,
+            # Trying to cancel it by using the generic Asyncio
+            # cancellation method.
+            return self._interceptors_task.cancel()
+
+        try:
+            call = self._interceptors_task.result()
+        except AioRpcError:
+            return False
+        except asyncio.CancelledError:
             return False
 
-        return self._interceptors_task.cancel()
+        return call.cancel()
 
     def cancelled(self) -> bool:
         if not self._interceptors_task.done():
@@ -270,7 +365,7 @@ class InterceptedUnaryUnaryCall(_base_call.UnaryUnaryCall):
             callback(self)
         else:
             callback = functools.partial(self._wrap_add_done_callback, callback)
-            call.add_done_callback(self._wrap_add_done_callback)
+            call.add_done_callback(callback)
 
     def time_remaining(self) -> Optional[float]:
         raise NotImplementedError()
@@ -325,14 +420,438 @@ class InterceptedUnaryUnaryCall(_base_call.UnaryUnaryCall):
 
         return await call.debug_error_string()
 
+    async def wait_for_connection(self) -> None:
+        call = await self._interceptors_task
+        return await call.wait_for_connection()
+
+
+class _InterceptedUnaryResponseMixin:
+
     def __await__(self):
         call = yield from self._interceptors_task.__await__()
         response = yield from call.__await__()
         return response
 
-    async def wait_for_connection(self) -> None:
+
+class _InterceptedStreamResponseMixin:
+    _response_aiter: Optional[AsyncIterable[ResponseType]]
+
+    def _init_stream_response_mixin(self) -> None:
+        # Is initalized later, otherwise if the iterator is not finnally
+        # consumed a logging warning is emmited by Asyncio.
+        self._response_aiter = None
+
+    async def _wait_for_interceptor_task_response_iterator(self
+                                                          ) -> ResponseType:
         call = await self._interceptors_task
-        return await call.wait_for_connection()
+        async for response in call:
+            yield response
+
+    def __aiter__(self) -> AsyncIterable[ResponseType]:
+        if self._response_aiter is None:
+            self._response_aiter = self._wait_for_interceptor_task_response_iterator(
+            )
+        return self._response_aiter
+
+    async def read(self) -> ResponseType:
+        if self._response_aiter is None:
+            self._response_aiter = self._wait_for_interceptor_task_response_iterator(
+            )
+        return await self._response_aiter.asend(None)
+
+
+class _InterceptedStreamRequestMixin:
+
+    _write_to_iterator_async_gen: Optional[AsyncIterable[RequestType]]
+    _write_to_iterator_queue: Optional[asyncio.Queue]
+
+    _FINISH_ITERATOR_SENTINEL = object()
+
+    def _init_stream_request_mixin(
+            self, request_iterator: Optional[RequestIterableType]
+    ) -> RequestIterableType:
+
+        if request_iterator is None:
+            # We provide our own request iterator which is a proxy
+            # of the futures writes that will be done by the caller.
+            self._write_to_iterator_queue = asyncio.Queue(maxsize=1)
+            self._write_to_iterator_async_gen = self._proxy_writes_as_request_iterator(
+            )
+            request_iterator = self._write_to_iterator_async_gen
+        else:
+            self._write_to_iterator_queue = None
+
+        return request_iterator
+
+    async def _proxy_writes_as_request_iterator(self):
+        await self._interceptors_task
+
+        while True:
+            value = await self._write_to_iterator_queue.get()
+            if value is _InterceptedStreamRequestMixin._FINISH_ITERATOR_SENTINEL:
+                break
+            yield value
+
+    async def write(self, request: RequestType) -> None:
+        # If no queue was created it means that requests
+        # should be expected through an iterators provided
+        # by the caller.
+        if self._write_to_iterator_queue is None:
+            raise cygrpc.UsageError(_API_STYLE_ERROR)
+
+        try:
+            call = await self._interceptors_task
+        except (asyncio.CancelledError, AioRpcError):
+            raise asyncio.InvalidStateError(_RPC_ALREADY_FINISHED_DETAILS)
+
+        if call.done():
+            raise asyncio.InvalidStateError(_RPC_ALREADY_FINISHED_DETAILS)
+        elif call._done_writing_flag:
+            raise asyncio.InvalidStateError(_RPC_HALF_CLOSED_DETAILS)
+
+        # Write might never end up since the call could abrubtly finish,
+        # we give up on the first awaitable object that finishes.
+        _, _ = await asyncio.wait(
+            (self._write_to_iterator_queue.put(request), call.code()),
+            return_when=asyncio.FIRST_COMPLETED)
+
+        if call.done():
+            raise asyncio.InvalidStateError(_RPC_ALREADY_FINISHED_DETAILS)
+
+    async def done_writing(self) -> None:
+        """Signal peer that client is done writing.
+
+        This method is idempotent.
+        """
+        # If no queue was created it means that requests
+        # should be expected through an iterators provided
+        # by the caller.
+        if self._write_to_iterator_queue is None:
+            raise cygrpc.UsageError(_API_STYLE_ERROR)
+
+        try:
+            call = await self._interceptors_task
+        except asyncio.CancelledError:
+            raise asyncio.InvalidStateError(_RPC_ALREADY_FINISHED_DETAILS)
+
+        # Write might never end up since the call could abrubtly finish,
+        # we give up on the first awaitable object that finishes.
+        _, _ = await asyncio.wait((self._write_to_iterator_queue.put(
+            _InterceptedStreamRequestMixin._FINISH_ITERATOR_SENTINEL),
+                                   call.code()),
+                                  return_when=asyncio.FIRST_COMPLETED)
+
+
+class InterceptedUnaryUnaryCall(_InterceptedUnaryResponseMixin, InterceptedCall,
+                                _base_call.UnaryUnaryCall):
+    """Used for running a `UnaryUnaryCall` wrapped by interceptors.
+
+    For the `__await__` method is it is proxied to the intercepted call only when
+    the interceptor task is finished.
+    """
+
+    _loop: asyncio.AbstractEventLoop
+    _channel: cygrpc.AioChannel
+
+    # pylint: disable=too-many-arguments
+    def __init__(self, interceptors: Sequence[UnaryUnaryClientInterceptor],
+                 request: RequestType, timeout: Optional[float],
+                 metadata: MetadataType,
+                 credentials: Optional[grpc.CallCredentials],
+                 wait_for_ready: Optional[bool], channel: cygrpc.AioChannel,
+                 method: bytes, request_serializer: SerializingFunction,
+                 response_deserializer: DeserializingFunction,
+                 loop: asyncio.AbstractEventLoop) -> None:
+        self._loop = loop
+        self._channel = channel
+        interceptors_task = loop.create_task(
+            self._invoke(interceptors, method, timeout, metadata, credentials,
+                         wait_for_ready, request, request_serializer,
+                         response_deserializer))
+        super().__init__(interceptors_task)
+
+    # pylint: disable=too-many-arguments
+    async def _invoke(self, interceptors: Sequence[UnaryUnaryClientInterceptor],
+                      method: bytes, timeout: Optional[float],
+                      metadata: Optional[MetadataType],
+                      credentials: Optional[grpc.CallCredentials],
+                      wait_for_ready: Optional[bool], request: RequestType,
+                      request_serializer: SerializingFunction,
+                      response_deserializer: DeserializingFunction
+                     ) -> UnaryUnaryCall:
+        """Run the RPC call wrapped in interceptors"""
+
+        async def _run_interceptor(
+                interceptors: Iterator[UnaryUnaryClientInterceptor],
+                client_call_details: ClientCallDetails,
+                request: RequestType) -> _base_call.UnaryUnaryCall:
+
+            interceptor = next(interceptors, None)
+
+            if interceptor:
+                continuation = functools.partial(_run_interceptor, interceptors)
+
+                call_or_response = await interceptor.intercept_unary_unary(
+                    continuation, client_call_details, request)
+
+                if isinstance(call_or_response, _base_call.UnaryUnaryCall):
+                    return call_or_response
+                else:
+                    return UnaryUnaryCallResponse(call_or_response)
+
+            else:
+                return UnaryUnaryCall(
+                    request, _timeout_to_deadline(client_call_details.timeout),
+                    client_call_details.metadata,
+                    client_call_details.credentials,
+                    client_call_details.wait_for_ready, self._channel,
+                    client_call_details.method, request_serializer,
+                    response_deserializer, self._loop)
+
+        client_call_details = ClientCallDetails(method, timeout, metadata,
+                                                credentials, wait_for_ready)
+        return await _run_interceptor(iter(interceptors), client_call_details,
+                                      request)
+
+    def time_remaining(self) -> Optional[float]:
+        raise NotImplementedError()
+
+
+class InterceptedUnaryStreamCall(_InterceptedStreamResponseMixin,
+                                 InterceptedCall, _base_call.UnaryStreamCall):
+    """Used for running a `UnaryStreamCall` wrapped by interceptors."""
+
+    _loop: asyncio.AbstractEventLoop
+    _channel: cygrpc.AioChannel
+    _last_returned_call_from_interceptors = Optional[_base_call.UnaryStreamCall]
+
+    # pylint: disable=too-many-arguments
+    def __init__(self, interceptors: Sequence[UnaryStreamClientInterceptor],
+                 request: RequestType, timeout: Optional[float],
+                 metadata: MetadataType,
+                 credentials: Optional[grpc.CallCredentials],
+                 wait_for_ready: Optional[bool], channel: cygrpc.AioChannel,
+                 method: bytes, request_serializer: SerializingFunction,
+                 response_deserializer: DeserializingFunction,
+                 loop: asyncio.AbstractEventLoop) -> None:
+        self._loop = loop
+        self._channel = channel
+        self._init_stream_response_mixin()
+        self._last_returned_call_from_interceptors = None
+        interceptors_task = loop.create_task(
+            self._invoke(interceptors, method, timeout, metadata, credentials,
+                         wait_for_ready, request, request_serializer,
+                         response_deserializer))
+        super().__init__(interceptors_task)
+
+    # pylint: disable=too-many-arguments
+    async def _invoke(self, interceptors: Sequence[UnaryUnaryClientInterceptor],
+                      method: bytes, timeout: Optional[float],
+                      metadata: Optional[MetadataType],
+                      credentials: Optional[grpc.CallCredentials],
+                      wait_for_ready: Optional[bool], request: RequestType,
+                      request_serializer: SerializingFunction,
+                      response_deserializer: DeserializingFunction
+                     ) -> UnaryStreamCall:
+        """Run the RPC call wrapped in interceptors"""
+
+        async def _run_interceptor(
+                interceptors: Iterator[UnaryStreamClientInterceptor],
+                client_call_details: ClientCallDetails,
+                request: RequestType,
+        ) -> _base_call.UnaryUnaryCall:
+
+            interceptor = next(interceptors, None)
+
+            if interceptor:
+                continuation = functools.partial(_run_interceptor, interceptors)
+
+                call_or_response_iterator = await interceptor.intercept_unary_stream(
+                    continuation, client_call_details, request)
+
+                if isinstance(call_or_response_iterator,
+                              _base_call.UnaryStreamCall):
+                    self._last_returned_call_from_interceptors = call_or_response_iterator
+                else:
+                    self._last_returned_call_from_interceptors = UnaryStreamCallResponseIterator(
+                        self._last_returned_call_from_interceptors,
+                        call_or_response_iterator)
+                return self._last_returned_call_from_interceptors
+            else:
+                self._last_returned_call_from_interceptors = UnaryStreamCall(
+                    request, _timeout_to_deadline(client_call_details.timeout),
+                    client_call_details.metadata,
+                    client_call_details.credentials,
+                    client_call_details.wait_for_ready, self._channel,
+                    client_call_details.method, request_serializer,
+                    response_deserializer, self._loop)
+
+                return self._last_returned_call_from_interceptors
+
+        client_call_details = ClientCallDetails(method, timeout, metadata,
+                                                credentials, wait_for_ready)
+        return await _run_interceptor(iter(interceptors), client_call_details,
+                                      request)
+
+    def time_remaining(self) -> Optional[float]:
+        raise NotImplementedError()
+
+
+class InterceptedStreamUnaryCall(_InterceptedUnaryResponseMixin,
+                                 _InterceptedStreamRequestMixin,
+                                 InterceptedCall, _base_call.StreamUnaryCall):
+    """Used for running a `StreamUnaryCall` wrapped by interceptors.
+
+    For the `__await__` method is it is proxied to the intercepted call only when
+    the interceptor task is finished.
+    """
+
+    _loop: asyncio.AbstractEventLoop
+    _channel: cygrpc.AioChannel
+
+    # pylint: disable=too-many-arguments
+    def __init__(self, interceptors: Sequence[StreamUnaryClientInterceptor],
+                 request_iterator: Optional[RequestIterableType],
+                 timeout: Optional[float], metadata: MetadataType,
+                 credentials: Optional[grpc.CallCredentials],
+                 wait_for_ready: Optional[bool], channel: cygrpc.AioChannel,
+                 method: bytes, request_serializer: SerializingFunction,
+                 response_deserializer: DeserializingFunction,
+                 loop: asyncio.AbstractEventLoop) -> None:
+        self._loop = loop
+        self._channel = channel
+        request_iterator = self._init_stream_request_mixin(request_iterator)
+        interceptors_task = loop.create_task(
+            self._invoke(interceptors, method, timeout, metadata, credentials,
+                         wait_for_ready, request_iterator, request_serializer,
+                         response_deserializer))
+        super().__init__(interceptors_task)
+
+    # pylint: disable=too-many-arguments
+    async def _invoke(
+            self, interceptors: Sequence[StreamUnaryClientInterceptor],
+            method: bytes, timeout: Optional[float],
+            metadata: Optional[MetadataType],
+            credentials: Optional[grpc.CallCredentials],
+            wait_for_ready: Optional[bool],
+            request_iterator: RequestIterableType,
+            request_serializer: SerializingFunction,
+            response_deserializer: DeserializingFunction) -> StreamUnaryCall:
+        """Run the RPC call wrapped in interceptors"""
+
+        async def _run_interceptor(
+                interceptors: Iterator[UnaryUnaryClientInterceptor],
+                client_call_details: ClientCallDetails,
+                request_iterator: RequestIterableType
+        ) -> _base_call.StreamUnaryCall:
+
+            interceptor = next(interceptors, None)
+
+            if interceptor:
+                continuation = functools.partial(_run_interceptor, interceptors)
+
+                return await interceptor.intercept_stream_unary(
+                    continuation, client_call_details, request_iterator)
+            else:
+                return StreamUnaryCall(
+                    request_iterator,
+                    _timeout_to_deadline(client_call_details.timeout),
+                    client_call_details.metadata,
+                    client_call_details.credentials,
+                    client_call_details.wait_for_ready, self._channel,
+                    client_call_details.method, request_serializer,
+                    response_deserializer, self._loop)
+
+        client_call_details = ClientCallDetails(method, timeout, metadata,
+                                                credentials, wait_for_ready)
+        return await _run_interceptor(iter(interceptors), client_call_details,
+                                      request_iterator)
+
+    def time_remaining(self) -> Optional[float]:
+        raise NotImplementedError()
+
+
+class InterceptedStreamStreamCall(_InterceptedStreamResponseMixin,
+                                  _InterceptedStreamRequestMixin,
+                                  InterceptedCall, _base_call.StreamStreamCall):
+    """Used for running a `StreamStreamCall` wrapped by interceptors."""
+
+    _loop: asyncio.AbstractEventLoop
+    _channel: cygrpc.AioChannel
+    _last_returned_call_from_interceptors = Optional[_base_call.UnaryStreamCall]
+
+    # pylint: disable=too-many-arguments
+    def __init__(self, interceptors: Sequence[StreamStreamClientInterceptor],
+                 request_iterator: Optional[RequestIterableType],
+                 timeout: Optional[float], metadata: MetadataType,
+                 credentials: Optional[grpc.CallCredentials],
+                 wait_for_ready: Optional[bool], channel: cygrpc.AioChannel,
+                 method: bytes, request_serializer: SerializingFunction,
+                 response_deserializer: DeserializingFunction,
+                 loop: asyncio.AbstractEventLoop) -> None:
+        self._loop = loop
+        self._channel = channel
+        self._init_stream_response_mixin()
+        request_iterator = self._init_stream_request_mixin(request_iterator)
+        self._last_returned_call_from_interceptors = None
+        interceptors_task = loop.create_task(
+            self._invoke(interceptors, method, timeout, metadata, credentials,
+                         wait_for_ready, request_iterator, request_serializer,
+                         response_deserializer))
+        super().__init__(interceptors_task)
+
+    # pylint: disable=too-many-arguments
+    async def _invoke(
+            self, interceptors: Sequence[StreamStreamClientInterceptor],
+            method: bytes, timeout: Optional[float],
+            metadata: Optional[MetadataType],
+            credentials: Optional[grpc.CallCredentials],
+            wait_for_ready: Optional[bool],
+            request_iterator: RequestIterableType,
+            request_serializer: SerializingFunction,
+            response_deserializer: DeserializingFunction) -> StreamStreamCall:
+        """Run the RPC call wrapped in interceptors"""
+
+        async def _run_interceptor(
+                interceptors: Iterator[StreamStreamClientInterceptor],
+                client_call_details: ClientCallDetails,
+                request_iterator: RequestIterableType
+        ) -> _base_call.StreamStreamCall:
+
+            interceptor = next(interceptors, None)
+
+            if interceptor:
+                continuation = functools.partial(_run_interceptor, interceptors)
+
+                call_or_response_iterator = await interceptor.intercept_stream_stream(
+                    continuation, client_call_details, request_iterator)
+
+                if isinstance(call_or_response_iterator,
+                              _base_call.StreamStreamCall):
+                    self._last_returned_call_from_interceptors = call_or_response_iterator
+                else:
+                    self._last_returned_call_from_interceptors = StreamStreamCallResponseIterator(
+                        self._last_returned_call_from_interceptors,
+                        call_or_response_iterator)
+                return self._last_returned_call_from_interceptors
+            else:
+                self._last_returned_call_from_interceptors = StreamStreamCall(
+                    request_iterator,
+                    _timeout_to_deadline(client_call_details.timeout),
+                    client_call_details.metadata,
+                    client_call_details.credentials,
+                    client_call_details.wait_for_ready, self._channel,
+                    client_call_details.method, request_serializer,
+                    response_deserializer, self._loop)
+                return self._last_returned_call_from_interceptors
+
+        client_call_details = ClientCallDetails(method, timeout, metadata,
+                                                credentials, wait_for_ready)
+        return await _run_interceptor(iter(interceptors), client_call_details,
+                                      request_iterator)
+
+    def time_remaining(self) -> Optional[float]:
+        raise NotImplementedError()
 
 
 class UnaryUnaryCallResponse(_base_call.UnaryUnaryCall):
@@ -381,3 +900,87 @@ class UnaryUnaryCallResponse(_base_call.UnaryUnaryCall):
 
     async def wait_for_connection(self) -> None:
         pass
+
+
+class _StreamCallResponseIterator:
+
+    _call: Union[_base_call.UnaryStreamCall, _base_call.StreamStreamCall]
+    _response_iterator: AsyncIterable[ResponseType]
+
+    def __init__(self, call: Union[_base_call.UnaryStreamCall, _base_call.
+                                   StreamStreamCall],
+                 response_iterator: AsyncIterable[ResponseType]) -> None:
+        self._response_iterator = response_iterator
+        self._call = call
+
+    def cancel(self) -> bool:
+        return self._call.cancel()
+
+    def cancelled(self) -> bool:
+        return self._call.cancelled()
+
+    def done(self) -> bool:
+        return self._call.done()
+
+    def add_done_callback(self, callback) -> None:
+        self._call.add_done_callback(callback)
+
+    def time_remaining(self) -> Optional[float]:
+        return self._call.time_remaining()
+
+    async def initial_metadata(self) -> Optional[MetadataType]:
+        return await self._call.initial_metadata()
+
+    async def trailing_metadata(self) -> Optional[MetadataType]:
+        return await self._call.trailing_metadata()
+
+    async def code(self) -> grpc.StatusCode:
+        return await self._call.code()
+
+    async def details(self) -> str:
+        return await self._call.details()
+
+    async def debug_error_string(self) -> Optional[str]:
+        return await self._call.debug_error_string()
+
+    def __aiter__(self):
+        return self._response_iterator.__aiter__()
+
+    async def wait_for_connection(self) -> None:
+        return await self._call.wait_for_connection()
+
+
+class UnaryStreamCallResponseIterator(_StreamCallResponseIterator,
+                                      _base_call.UnaryStreamCall):
+    """UnaryStreamCall class wich uses an alternative response iterator."""
+
+    async def read(self) -> ResponseType:
+        # Behind the scenes everyting goes through the
+        # async iterator. So this path should not be reached.
+        raise NotImplementedError()
+
+
+class StreamStreamCallResponseIterator(_StreamCallResponseIterator,
+                                       _base_call.StreamStreamCall):
+    """StreamStreamCall class wich uses an alternative response iterator."""
+
+    async def read(self) -> ResponseType:
+        # Behind the scenes everyting goes through the
+        # async iterator. So this path should not be reached.
+        raise NotImplementedError()
+
+    async def write(self, request: RequestType) -> None:
+        # Behind the scenes everyting goes through the
+        # async iterator provided by the InterceptedStreamStreamCall.
+        # So this path should not be reached.
+        raise NotImplementedError()
+
+    async def done_writing(self) -> None:
+        # Behind the scenes everyting goes through the
+        # async iterator provided by the InterceptedStreamStreamCall.
+        # So this path should not be reached.
+        raise NotImplementedError()
+
+    @property
+    def _done_writing_flag(self) -> bool:
+        return self._call._done_writing_flag
index 478049e..8143889 100644 (file)
@@ -187,7 +187,7 @@ def server(migration_thread_pool: Optional[Executor] = None,
         and optionally manipulate the incoming RPCs before handing them over to
         handlers. The interceptors are given control in the order they are
         specified. This is an EXPERIMENTAL API.
-      options: An optional list of key-value pairs (channel args in gRPC runtime)
+      options: An optional list of key-value pairs (:term:`channel_arguments` in gRPC runtime)
         to configure the channel.
       maximum_concurrent_rpcs: The maximum number of concurrent RPCs this server
         will service before returning RESOURCE_EXHAUSTED status, or None to
index 205f6dc..a02ec8f 100644 (file)
@@ -28,3 +28,4 @@ ChannelArgumentType = Sequence[Tuple[str, Any]]
 EOFType = type(EOF)
 DoneCallbackType = Callable[[Any], None]
 RequestIterableType = Union[Iterable[Any], AsyncIterable[Any]]
+ResponseIterableType = AsyncIterable[Any]
index 08a60c0..37bed16 100644 (file)
@@ -70,6 +70,7 @@ CORE_SOURCE_FILES = [
     'src/core/ext/filters/client_channel/retry_throttle.cc',
     'src/core/ext/filters/client_channel/server_address.cc',
     'src/core/ext/filters/client_channel/service_config.cc',
+    'src/core/ext/filters/client_channel/service_config_parser.cc',
     'src/core/ext/filters/client_channel/subchannel.cc',
     'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
     'src/core/ext/filters/client_channel/xds/xds_api.cc',
@@ -127,18 +128,24 @@ CORE_SOURCE_FILES = [
     'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c',
     'src/core/ext/upb-generated/envoy/annotations/resource.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c',
+    'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c',
+    'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c',
+    'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/cds.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c',
+    'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c',
+    'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c',
+    'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/eds.upb.c',
     'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c',
@@ -159,6 +166,7 @@ CORE_SOURCE_FILES = [
     'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c',
     'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c',
     'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c',
+    'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c',
     'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c',
     'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c',
     'src/core/ext/upb-generated/envoy/type/http.upb.c',
@@ -187,6 +195,7 @@ CORE_SOURCE_FILES = [
     'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
     'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c',
     'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c',
+    'src/core/ext/upb-generated/udpa/annotations/status.upb.c',
     'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
     'src/core/ext/upb-generated/validate/validate.upb.c',
     'src/core/lib/avl/avl.cc',
@@ -586,6 +595,7 @@ CORE_SOURCE_FILES = [
     'third_party/boringssl-with-bazel/src/crypto/cpu-intel.c',
     'third_party/boringssl-with-bazel/src/crypto/cpu-ppc64le.c',
     'third_party/boringssl-with-bazel/src/crypto/crypto.c',
+    'third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519.c',
     'third_party/boringssl-with-bazel/src/crypto/curve25519/spake25519.c',
     'third_party/boringssl-with-bazel/src/crypto/dh/check.c',
     'third_party/boringssl-with-bazel/src/crypto/dh/dh.c',
@@ -596,6 +606,7 @@ CORE_SOURCE_FILES = [
     'third_party/boringssl-with-bazel/src/crypto/dsa/dsa_asn1.c',
     'third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_asn1.c',
     'third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_derive.c',
+    'third_party/boringssl-with-bazel/src/crypto/ec_extra/hash_to_curve.c',
     'third_party/boringssl-with-bazel/src/crypto/ecdh_extra/ecdh_extra.c',
     'third_party/boringssl-with-bazel/src/crypto/ecdsa_extra/ecdsa_asn1.c',
     'third_party/boringssl-with-bazel/src/crypto/engine/engine.c',
@@ -660,6 +671,8 @@ CORE_SOURCE_FILES = [
     'third_party/boringssl-with-bazel/src/crypto/thread_none.c',
     'third_party/boringssl-with-bazel/src/crypto/thread_pthread.c',
     'third_party/boringssl-with-bazel/src/crypto/thread_win.c',
+    'third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c',
+    'third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token.c',
     'third_party/boringssl-with-bazel/src/crypto/x509/a_digest.c',
     'third_party/boringssl-with-bazel/src/crypto/x509/a_sign.c',
     'third_party/boringssl-with-bazel/src/crypto/x509/a_strex.c',
@@ -778,7 +791,6 @@ CORE_SOURCE_FILES = [
     'third_party/boringssl-with-bazel/src/ssl/tls13_server.cc',
     'third_party/boringssl-with-bazel/src/ssl/tls_method.cc',
     'third_party/boringssl-with-bazel/src/ssl/tls_record.cc',
-    'third_party/boringssl-with-bazel/src/third_party/fiat/curve25519.c',
     'third_party/cares/cares/ares__close_sockets.c',
     'third_party/cares/cares/ares__get_hostent.c',
     'third_party/cares/cares/ares__read_line.c',
index f65c6f2..a62690c 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
 
-VERSION = '1.29.1'
+VERSION = '1.30.0'
index 942d861..d2393b0 100644 (file)
@@ -16,7 +16,7 @@ py_grpc_library(
 
 py_library(
     name = "grpc_channelz",
-    srcs = ["channelz.py"],
+    srcs = glob(["*.py"]),
     imports = ["../../"],
     deps = [
         ":channelz_py_pb2",
diff --git a/src/python/grpcio_channelz/grpc_channelz/v1/_async.py b/src/python/grpcio_channelz/grpc_channelz/v1/_async.py
new file mode 100644 (file)
index 0000000..50911b0
--- /dev/null
@@ -0,0 +1,66 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""AsyncIO version of Channelz servicer."""
+
+from grpc.experimental import aio
+
+import grpc_channelz.v1.channelz_pb2 as _channelz_pb2
+import grpc_channelz.v1.channelz_pb2_grpc as _channelz_pb2_grpc
+from grpc_channelz.v1._servicer import ChannelzServicer as _SyncChannelzServicer
+
+
+class ChannelzServicer(_channelz_pb2_grpc.ChannelzServicer):
+    """AsyncIO servicer for handling RPCs for service statuses."""
+
+    @staticmethod
+    async def GetTopChannels(request: _channelz_pb2.GetTopChannelsRequest,
+                             context: aio.ServicerContext
+                            ) -> _channelz_pb2.GetTopChannelsResponse:
+        return _SyncChannelzServicer.GetTopChannels(request, context)
+
+    @staticmethod
+    async def GetServers(request: _channelz_pb2.GetServersRequest,
+                         context: aio.ServicerContext
+                        ) -> _channelz_pb2.GetServersResponse:
+        return _SyncChannelzServicer.GetServers(request, context)
+
+    @staticmethod
+    async def GetServer(request: _channelz_pb2.GetServerRequest,
+                        context: aio.ServicerContext
+                       ) -> _channelz_pb2.GetServerResponse:
+        return _SyncChannelzServicer.GetServer(request, context)
+
+    @staticmethod
+    async def GetServerSockets(request: _channelz_pb2.GetServerSocketsRequest,
+                               context: aio.ServicerContext
+                              ) -> _channelz_pb2.GetServerSocketsResponse:
+        return _SyncChannelzServicer.GetServerSockets(request, context)
+
+    @staticmethod
+    async def GetChannel(request: _channelz_pb2.GetChannelRequest,
+                         context: aio.ServicerContext
+                        ) -> _channelz_pb2.GetChannelResponse:
+        return _SyncChannelzServicer.GetChannel(request, context)
+
+    @staticmethod
+    async def GetSubchannel(request: _channelz_pb2.GetSubchannelRequest,
+                            context: aio.ServicerContext
+                           ) -> _channelz_pb2.GetSubchannelResponse:
+        return _SyncChannelzServicer.GetSubchannel(request, context)
+
+    @staticmethod
+    async def GetSocket(request: _channelz_pb2.GetSocketRequest,
+                        context: aio.ServicerContext
+                       ) -> _channelz_pb2.GetSocketResponse:
+        return _SyncChannelzServicer.GetSocket(request, context)
diff --git a/src/python/grpcio_channelz/grpc_channelz/v1/_servicer.py b/src/python/grpcio_channelz/grpc_channelz/v1/_servicer.py
new file mode 100644 (file)
index 0000000..6ba28f5
--- /dev/null
@@ -0,0 +1,120 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Channelz debug service implementation in gRPC Python."""
+
+import grpc
+from grpc._cython import cygrpc
+
+import grpc_channelz.v1.channelz_pb2 as _channelz_pb2
+import grpc_channelz.v1.channelz_pb2_grpc as _channelz_pb2_grpc
+
+from google.protobuf import json_format
+
+
+class ChannelzServicer(_channelz_pb2_grpc.ChannelzServicer):
+    """Servicer handling RPCs for service statuses."""
+
+    @staticmethod
+    def GetTopChannels(request, context):
+        try:
+            return json_format.Parse(
+                cygrpc.channelz_get_top_channels(request.start_channel_id),
+                _channelz_pb2.GetTopChannelsResponse(),
+            )
+        except (ValueError, json_format.ParseError) as e:
+            context.set_code(grpc.StatusCode.INTERNAL)
+            context.set_details(str(e))
+
+    @staticmethod
+    def GetServers(request, context):
+        try:
+            return json_format.Parse(
+                cygrpc.channelz_get_servers(request.start_server_id),
+                _channelz_pb2.GetServersResponse(),
+            )
+        except (ValueError, json_format.ParseError) as e:
+            context.set_code(grpc.StatusCode.INTERNAL)
+            context.set_details(str(e))
+
+    @staticmethod
+    def GetServer(request, context):
+        try:
+            return json_format.Parse(
+                cygrpc.channelz_get_server(request.server_id),
+                _channelz_pb2.GetServerResponse(),
+            )
+        except ValueError as e:
+            context.set_code(grpc.StatusCode.NOT_FOUND)
+            context.set_details(str(e))
+        except json_format.ParseError as e:
+            context.set_code(grpc.StatusCode.INTERNAL)
+            context.set_details(str(e))
+
+    @staticmethod
+    def GetServerSockets(request, context):
+        try:
+            return json_format.Parse(
+                cygrpc.channelz_get_server_sockets(request.server_id,
+                                                   request.start_socket_id,
+                                                   request.max_results),
+                _channelz_pb2.GetServerSocketsResponse(),
+            )
+        except ValueError as e:
+            context.set_code(grpc.StatusCode.NOT_FOUND)
+            context.set_details(str(e))
+        except json_format.ParseError as e:
+            context.set_code(grpc.StatusCode.INTERNAL)
+            context.set_details(str(e))
+
+    @staticmethod
+    def GetChannel(request, context):
+        try:
+            return json_format.Parse(
+                cygrpc.channelz_get_channel(request.channel_id),
+                _channelz_pb2.GetChannelResponse(),
+            )
+        except ValueError as e:
+            context.set_code(grpc.StatusCode.NOT_FOUND)
+            context.set_details(str(e))
+        except json_format.ParseError as e:
+            context.set_code(grpc.StatusCode.INTERNAL)
+            context.set_details(str(e))
+
+    @staticmethod
+    def GetSubchannel(request, context):
+        try:
+            return json_format.Parse(
+                cygrpc.channelz_get_subchannel(request.subchannel_id),
+                _channelz_pb2.GetSubchannelResponse(),
+            )
+        except ValueError as e:
+            context.set_code(grpc.StatusCode.NOT_FOUND)
+            context.set_details(str(e))
+        except json_format.ParseError as e:
+            context.set_code(grpc.StatusCode.INTERNAL)
+            context.set_details(str(e))
+
+    @staticmethod
+    def GetSocket(request, context):
+        try:
+            return json_format.Parse(
+                cygrpc.channelz_get_socket(request.socket_id),
+                _channelz_pb2.GetSocketResponse(),
+            )
+        except ValueError as e:
+            context.set_code(grpc.StatusCode.NOT_FOUND)
+            context.set_details(str(e))
+        except json_format.ParseError as e:
+            context.set_code(grpc.StatusCode.INTERNAL)
+            context.set_details(str(e))
index 00eca31..508fad5 100644 (file)
 # limitations under the License.
 """Channelz debug service implementation in gRPC Python."""
 
+import sys
 import grpc
-from grpc._cython import cygrpc
 
-import grpc_channelz.v1.channelz_pb2 as _channelz_pb2
 import grpc_channelz.v1.channelz_pb2_grpc as _channelz_pb2_grpc
+from grpc_channelz.v1._servicer import ChannelzServicer
 
-from google.protobuf import json_format
-
-
-class ChannelzServicer(_channelz_pb2_grpc.ChannelzServicer):
-    """Servicer handling RPCs for service statuses."""
-
-    @staticmethod
-    def GetTopChannels(request, context):
-        try:
-            return json_format.Parse(
-                cygrpc.channelz_get_top_channels(request.start_channel_id),
-                _channelz_pb2.GetTopChannelsResponse(),
-            )
-        except (ValueError, json_format.ParseError) as e:
-            context.set_code(grpc.StatusCode.INTERNAL)
-            context.set_details(str(e))
-
-    @staticmethod
-    def GetServers(request, context):
-        try:
-            return json_format.Parse(
-                cygrpc.channelz_get_servers(request.start_server_id),
-                _channelz_pb2.GetServersResponse(),
-            )
-        except (ValueError, json_format.ParseError) as e:
-            context.set_code(grpc.StatusCode.INTERNAL)
-            context.set_details(str(e))
-
-    @staticmethod
-    def GetServer(request, context):
-        try:
-            return json_format.Parse(
-                cygrpc.channelz_get_server(request.server_id),
-                _channelz_pb2.GetServerResponse(),
-            )
-        except ValueError as e:
-            context.set_code(grpc.StatusCode.NOT_FOUND)
-            context.set_details(str(e))
-        except json_format.ParseError as e:
-            context.set_code(grpc.StatusCode.INTERNAL)
-            context.set_details(str(e))
-
-    @staticmethod
-    def GetServerSockets(request, context):
-        try:
-            return json_format.Parse(
-                cygrpc.channelz_get_server_sockets(request.server_id,
-                                                   request.start_socket_id,
-                                                   request.max_results),
-                _channelz_pb2.GetServerSocketsResponse(),
-            )
-        except ValueError as e:
-            context.set_code(grpc.StatusCode.NOT_FOUND)
-            context.set_details(str(e))
-        except json_format.ParseError as e:
-            context.set_code(grpc.StatusCode.INTERNAL)
-            context.set_details(str(e))
-
-    @staticmethod
-    def GetChannel(request, context):
-        try:
-            return json_format.Parse(
-                cygrpc.channelz_get_channel(request.channel_id),
-                _channelz_pb2.GetChannelResponse(),
-            )
-        except ValueError as e:
-            context.set_code(grpc.StatusCode.NOT_FOUND)
-            context.set_details(str(e))
-        except json_format.ParseError as e:
-            context.set_code(grpc.StatusCode.INTERNAL)
-            context.set_details(str(e))
-
-    @staticmethod
-    def GetSubchannel(request, context):
-        try:
-            return json_format.Parse(
-                cygrpc.channelz_get_subchannel(request.subchannel_id),
-                _channelz_pb2.GetSubchannelResponse(),
-            )
-        except ValueError as e:
-            context.set_code(grpc.StatusCode.NOT_FOUND)
-            context.set_details(str(e))
-        except json_format.ParseError as e:
-            context.set_code(grpc.StatusCode.INTERNAL)
-            context.set_details(str(e))
-
-    @staticmethod
-    def GetSocket(request, context):
-        try:
-            return json_format.Parse(
-                cygrpc.channelz_get_socket(request.socket_id),
-                _channelz_pb2.GetSocketResponse(),
-            )
-        except ValueError as e:
-            context.set_code(grpc.StatusCode.NOT_FOUND)
-            context.set_details(str(e))
-        except json_format.ParseError as e:
-            context.set_code(grpc.StatusCode.INTERNAL)
-            context.set_details(str(e))
-
-
-def add_channelz_servicer(server):
-    """Add Channelz servicer to a server. Channelz servicer is in charge of
-    pulling information from C-Core for entire process. It will allow the
-    server to response to Channelz queries.
-
-    The Channelz statistic is enabled by default inside C-Core. Whether the
-    statistic is enabled or not is isolated from adding Channelz servicer.
-    That means you can query Channelz info with a Channelz-disabled channel,
-    and you can add Channelz servicer to a Channelz-disabled server.
-
-    The Channelz statistic can be enabled or disabled by channel option
-    'grpc.enable_channelz'. Set to 1 to enable, set to 0 to disable.
-
-    This is an EXPERIMENTAL API.
-
-    Args:
-      server: grpc.Server to which Channelz service will be added.
-    """
-    _channelz_pb2_grpc.add_ChannelzServicer_to_server(ChannelzServicer(),
-                                                      server)
+_add_channelz_servicer_doc = """Add Channelz servicer to a server.
+
+Channelz servicer is in charge of
+pulling information from C-Core for entire process. It will allow the
+server to response to Channelz queries.
+
+The Channelz statistic is enabled by default inside C-Core. Whether the
+statistic is enabled or not is isolated from adding Channelz servicer.
+That means you can query Channelz info with a Channelz-disabled channel,
+and you can add Channelz servicer to a Channelz-disabled server.
+
+The Channelz statistic can be enabled or disabled by channel option
+'grpc.enable_channelz'. Set to 1 to enable, set to 0 to disable.
+
+This is an EXPERIMENTAL API.
+
+Args:
+    server: A gRPC server to which Channelz service will be added.
+"""
+
+if sys.version_info[0] >= 3 and sys.version_info[1] >= 6:
+    from grpc_channelz.v1 import _async as aio
+
+    def add_channelz_servicer(server):
+
+        if isinstance(server, grpc.experimental.aio.Server):
+            _channelz_pb2_grpc.add_ChannelzServicer_to_server(
+                aio.ChannelzServicer(), server)
+        else:
+            _channelz_pb2_grpc.add_ChannelzServicer_to_server(
+                ChannelzServicer(), server)
+
+    add_channelz_servicer.__doc__ = _add_channelz_servicer_doc
+
+    __all__ = [
+        "aio",
+        "add_channelz_servicer",
+        "ChannelzServicer",
+    ]
+
+else:
+
+    def add_channelz_servicer(server):
+        _channelz_pb2_grpc.add_ChannelzServicer_to_server(
+            ChannelzServicer(), server)
+
+    add_channelz_servicer.__doc__ = _add_channelz_servicer_doc
+
+    __all__ = [
+        "add_channelz_servicer",
+        "ChannelzServicer",
+    ]
index 435c333..04e3b8a 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_channelz/grpc_version.py.template`!!!
 
-VERSION = '1.29.1'
+VERSION = '1.30.0'
index 016ab62..e1e27b3 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
 
-VERSION = '1.29.1'
+VERSION = '1.30.0'
index cf30c39..6e3d8e0 100644 (file)
@@ -17,7 +17,7 @@ py_grpc_library(
 
 py_library(
     name = "grpc_reflection",
-    srcs = ["reflection.py"],
+    srcs = glob(["*.py"]),
     imports = ["../../"],
     deps = [
         ":reflection_py_pb2",
diff --git a/src/python/grpcio_reflection/grpc_reflection/v1alpha/_async.py b/src/python/grpcio_reflection/grpc_reflection/v1alpha/_async.py
new file mode 100644 (file)
index 0000000..6e684a4
--- /dev/null
@@ -0,0 +1,57 @@
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""The AsyncIO version of the reflection servicer."""
+
+from typing import AsyncIterable
+
+import grpc
+
+from grpc_reflection.v1alpha import reflection_pb2 as _reflection_pb2
+from grpc_reflection.v1alpha._base import BaseReflectionServicer
+
+
+class ReflectionServicer(BaseReflectionServicer):
+    """Servicer handling RPCs for service statuses."""
+
+    async def ServerReflectionInfo(
+            self, request_iterator: AsyncIterable[
+                _reflection_pb2.ServerReflectionRequest], unused_context
+    ) -> AsyncIterable[_reflection_pb2.ServerReflectionResponse]:
+        async for request in request_iterator:
+            if request.HasField('file_by_filename'):
+                yield self._file_by_filename(request.file_by_filename)
+            elif request.HasField('file_containing_symbol'):
+                yield self._file_containing_symbol(
+                    request.file_containing_symbol)
+            elif request.HasField('file_containing_extension'):
+                yield self._file_containing_extension(
+                    request.file_containing_extension.containing_type,
+                    request.file_containing_extension.extension_number)
+            elif request.HasField('all_extension_numbers_of_type'):
+                yield self._all_extension_numbers_of_type(
+                    request.all_extension_numbers_of_type)
+            elif request.HasField('list_services'):
+                yield self._list_services()
+            else:
+                yield _reflection_pb2.ServerReflectionResponse(
+                    error_response=_reflection_pb2.ErrorResponse(
+                        error_code=grpc.StatusCode.INVALID_ARGUMENT.value[0],
+                        error_message=grpc.StatusCode.INVALID_ARGUMENT.value[1].
+                        encode(),
+                    ))
+
+
+__all__ = [
+    "ReflectionServicer",
+]
diff --git a/src/python/grpcio_reflection/grpc_reflection/v1alpha/_base.py b/src/python/grpcio_reflection/grpc_reflection/v1alpha/_base.py
new file mode 100644 (file)
index 0000000..2c9e79c
--- /dev/null
@@ -0,0 +1,110 @@
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Base implementation of reflection servicer."""
+
+import grpc
+from google.protobuf import descriptor_pb2
+from google.protobuf import descriptor_pool
+
+from grpc_reflection.v1alpha import reflection_pb2 as _reflection_pb2
+from grpc_reflection.v1alpha import reflection_pb2_grpc as _reflection_pb2_grpc
+
+_POOL = descriptor_pool.Default()
+
+
+def _not_found_error():
+    return _reflection_pb2.ServerReflectionResponse(
+        error_response=_reflection_pb2.ErrorResponse(
+            error_code=grpc.StatusCode.NOT_FOUND.value[0],
+            error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(),
+        ))
+
+
+def _file_descriptor_response(descriptor):
+    proto = descriptor_pb2.FileDescriptorProto()
+    descriptor.CopyToProto(proto)
+    serialized_proto = proto.SerializeToString()
+    return _reflection_pb2.ServerReflectionResponse(
+        file_descriptor_response=_reflection_pb2.FileDescriptorResponse(
+            file_descriptor_proto=(serialized_proto,)),)
+
+
+class BaseReflectionServicer(_reflection_pb2_grpc.ServerReflectionServicer):
+    """Base class for reflection servicer."""
+
+    def __init__(self, service_names, pool=None):
+        """Constructor.
+
+        Args:
+            service_names: Iterable of fully-qualified service names available.
+            pool: An optional DescriptorPool instance.
+        """
+        self._service_names = tuple(sorted(service_names))
+        self._pool = _POOL if pool is None else pool
+
+    def _file_by_filename(self, filename):
+        try:
+            descriptor = self._pool.FindFileByName(filename)
+        except KeyError:
+            return _not_found_error()
+        else:
+            return _file_descriptor_response(descriptor)
+
+    def _file_containing_symbol(self, fully_qualified_name):
+        try:
+            descriptor = self._pool.FindFileContainingSymbol(
+                fully_qualified_name)
+        except KeyError:
+            return _not_found_error()
+        else:
+            return _file_descriptor_response(descriptor)
+
+    def _file_containing_extension(self, containing_type, extension_number):
+        try:
+            message_descriptor = self._pool.FindMessageTypeByName(
+                containing_type)
+            extension_descriptor = self._pool.FindExtensionByNumber(
+                message_descriptor, extension_number)
+            descriptor = self._pool.FindFileContainingSymbol(
+                extension_descriptor.full_name)
+        except KeyError:
+            return _not_found_error()
+        else:
+            return _file_descriptor_response(descriptor)
+
+    def _all_extension_numbers_of_type(self, containing_type):
+        try:
+            message_descriptor = self._pool.FindMessageTypeByName(
+                containing_type)
+            extension_numbers = tuple(
+                sorted(extension.number for extension in
+                       self._pool.FindAllExtensions(message_descriptor)))
+        except KeyError:
+            return _not_found_error()
+        else:
+            return _reflection_pb2.ServerReflectionResponse(
+                all_extension_numbers_response=_reflection_pb2.
+                ExtensionNumberResponse(
+                    base_type_name=message_descriptor.full_name,
+                    extension_number=extension_numbers))
+
+    def _list_services(self):
+        return _reflection_pb2.ServerReflectionResponse(
+            list_services_response=_reflection_pb2.ListServiceResponse(service=[
+                _reflection_pb2.ServiceResponse(name=service_name)
+                for service_name in self._service_names
+            ]))
+
+
+__all__ = ['BaseReflectionServicer']
index dde291f..219f10a 100644 (file)
 # limitations under the License.
 """Reference implementation for reflection in gRPC Python."""
 
+import sys
 import grpc
-from google.protobuf import descriptor_pb2
-from google.protobuf import descriptor_pool
 
 from grpc_reflection.v1alpha import reflection_pb2 as _reflection_pb2
 from grpc_reflection.v1alpha import reflection_pb2_grpc as _reflection_pb2_grpc
 
-_POOL = descriptor_pool.Default()
+from grpc_reflection.v1alpha._base import BaseReflectionServicer
+
 SERVICE_NAME = _reflection_pb2.DESCRIPTOR.services_by_name[
     'ServerReflection'].full_name
 
 
-def _not_found_error():
-    return _reflection_pb2.ServerReflectionResponse(
-        error_response=_reflection_pb2.ErrorResponse(
-            error_code=grpc.StatusCode.NOT_FOUND.value[0],
-            error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(),
-        ))
-
-
-def _file_descriptor_response(descriptor):
-    proto = descriptor_pb2.FileDescriptorProto()
-    descriptor.CopyToProto(proto)
-    serialized_proto = proto.SerializeToString()
-    return _reflection_pb2.ServerReflectionResponse(
-        file_descriptor_response=_reflection_pb2.FileDescriptorResponse(
-            file_descriptor_proto=(serialized_proto,)),)
-
-
-class ReflectionServicer(_reflection_pb2_grpc.ServerReflectionServicer):
+class ReflectionServicer(BaseReflectionServicer):
     """Servicer handling RPCs for service statuses."""
 
-    def __init__(self, service_names, pool=None):
-        """Constructor.
-
-    Args:
-      service_names: Iterable of fully-qualified service names available.
-    """
-        self._service_names = tuple(sorted(service_names))
-        self._pool = _POOL if pool is None else pool
-
-    def _file_by_filename(self, filename):
-        try:
-            descriptor = self._pool.FindFileByName(filename)
-        except KeyError:
-            return _not_found_error()
-        else:
-            return _file_descriptor_response(descriptor)
-
-    def _file_containing_symbol(self, fully_qualified_name):
-        try:
-            descriptor = self._pool.FindFileContainingSymbol(
-                fully_qualified_name)
-        except KeyError:
-            return _not_found_error()
-        else:
-            return _file_descriptor_response(descriptor)
-
-    def _file_containing_extension(self, containing_type, extension_number):
-        try:
-            message_descriptor = self._pool.FindMessageTypeByName(
-                containing_type)
-            extension_descriptor = self._pool.FindExtensionByNumber(
-                message_descriptor, extension_number)
-            descriptor = self._pool.FindFileContainingSymbol(
-                extension_descriptor.full_name)
-        except KeyError:
-            return _not_found_error()
-        else:
-            return _file_descriptor_response(descriptor)
-
-    def _all_extension_numbers_of_type(self, containing_type):
-        try:
-            message_descriptor = self._pool.FindMessageTypeByName(
-                containing_type)
-            extension_numbers = tuple(
-                sorted(extension.number for extension in
-                       self._pool.FindAllExtensions(message_descriptor)))
-        except KeyError:
-            return _not_found_error()
-        else:
-            return _reflection_pb2.ServerReflectionResponse(
-                all_extension_numbers_response=_reflection_pb2.
-                ExtensionNumberResponse(
-                    base_type_name=message_descriptor.full_name,
-                    extension_number=extension_numbers))
-
-    def _list_services(self):
-        return _reflection_pb2.ServerReflectionResponse(
-            list_services_response=_reflection_pb2.ListServiceResponse(service=[
-                _reflection_pb2.ServiceResponse(name=service_name)
-                for service_name in self._service_names
-            ]))
-
     def ServerReflectionInfo(self, request_iterator, context):
         # pylint: disable=unused-argument
         for request in request_iterator:
@@ -133,13 +54,45 @@ class ReflectionServicer(_reflection_pb2_grpc.ServerReflectionServicer):
                     ))
 
 
-def enable_server_reflection(service_names, server, pool=None):
-    """Enables server reflection on a server.
+_enable_server_reflection_doc = """Enables server reflection on a server.
 
-    Args:
-      service_names: Iterable of fully-qualified service names available.
-      server: grpc.Server to which reflection service will be added.
-      pool: DescriptorPool object to use (descriptor_pool.Default() if None).
-    """
-    _reflection_pb2_grpc.add_ServerReflectionServicer_to_server(
-        ReflectionServicer(service_names, pool=pool), server)
+Args:
+    service_names: Iterable of fully-qualified service names available.
+    server: grpc.Server to which reflection service will be added.
+    pool: DescriptorPool object to use (descriptor_pool.Default() if None).
+"""
+
+if sys.version_info[0] >= 3 and sys.version_info[1] >= 6:
+    # Exposes AsyncReflectionServicer as public API.
+    from . import _async as aio
+    from grpc.experimental import aio as grpc_aio  # pylint: disable=ungrouped-imports
+
+    def enable_server_reflection(service_names, server, pool=None):
+        if isinstance(server, grpc_aio.Server):
+            _reflection_pb2_grpc.add_ServerReflectionServicer_to_server(
+                aio.ReflectionServicer(service_names, pool=pool), server)
+        else:
+            _reflection_pb2_grpc.add_ServerReflectionServicer_to_server(
+                ReflectionServicer(service_names, pool=pool), server)
+
+    enable_server_reflection.__doc__ = _enable_server_reflection_doc
+
+    __all__ = [
+        "SERVICE_NAME",
+        "ReflectionServicer",
+        "enable_server_reflection",
+        "aio",
+    ]
+else:
+
+    def enable_server_reflection(service_names, server, pool=None):
+        _reflection_pb2_grpc.add_ServerReflectionServicer_to_server(
+            ReflectionServicer(service_names, pool=pool), server)
+
+    enable_server_reflection.__doc__ = _enable_server_reflection_doc
+
+    __all__ = [
+        "SERVICE_NAME",
+        "ReflectionServicer",
+        "enable_server_reflection",
+    ]
index beba57e..3ac565f 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
 
-VERSION = '1.29.1'
+VERSION = '1.30.0'
index 122a94f..a6abdd3 100644 (file)
@@ -4,7 +4,7 @@ package(default_visibility = ["//visibility:public"])
 
 py_library(
     name = "grpc_status",
-    srcs = ["rpc_status.py"],
+    srcs = glob(["*.py"]),
     imports = ["../"],
     deps = [
         "//src/python/grpcio/grpc:grpcio",
diff --git a/src/python/grpcio_status/grpc_status/_async.py b/src/python/grpcio_status/grpc_status/_async.py
new file mode 100644 (file)
index 0000000..a6a6f7e
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Reference implementation for status mapping in gRPC Python."""
+
+from grpc.experimental import aio
+
+from google.rpc import status_pb2
+
+from ._common import code_to_grpc_status_code, GRPC_DETAILS_METADATA_KEY
+
+
+async def from_call(call: aio.Call):
+    """Returns a google.rpc.status.Status message from a given grpc.aio.Call.
+
+    This is an EXPERIMENTAL API.
+
+    Args:
+      call: An grpc.aio.Call instance.
+
+    Returns:
+      A google.rpc.status.Status message representing the status of the RPC.
+    """
+    code = await call.code()
+    details = await call.details()
+    trailing_metadata = await call.trailing_metadata()
+    if trailing_metadata is None:
+        return None
+    for key, value in trailing_metadata:
+        if key == GRPC_DETAILS_METADATA_KEY:
+            rich_status = status_pb2.Status.FromString(value)
+            if code.value[0] != rich_status.code:
+                raise ValueError(
+                    'Code in Status proto (%s) doesn\'t match status code (%s)'
+                    % (code_to_grpc_status_code(rich_status.code), code))
+            if details != rich_status.message:
+                raise ValueError(
+                    'Message in Status proto (%s) doesn\'t match status details (%s)'
+                    % (rich_status.message, details))
+            return rich_status
+    return None
+
+
+__all__ = [
+    'from_call',
+]
diff --git a/src/python/grpcio_status/grpc_status/_common.py b/src/python/grpcio_status/grpc_status/_common.py
new file mode 100644 (file)
index 0000000..4bec0ba
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Reference implementation for status mapping in gRPC Python."""
+
+import grpc
+
+_CODE_TO_GRPC_CODE_MAPPING = {x.value[0]: x for x in grpc.StatusCode}
+
+GRPC_DETAILS_METADATA_KEY = 'grpc-status-details-bin'
+
+
+def code_to_grpc_status_code(code):
+    try:
+        return _CODE_TO_GRPC_CODE_MAPPING[code]
+    except KeyError:
+        raise ValueError('Invalid status code %s' % code)
index ec78c47..d0ec08e 100644 (file)
 """Reference implementation for status mapping in gRPC Python."""
 
 import collections
+import sys
 
 import grpc
 
 from google.rpc import status_pb2
-
-_CODE_TO_GRPC_CODE_MAPPING = {x.value[0]: x for x in grpc.StatusCode}
-
-_GRPC_DETAILS_METADATA_KEY = 'grpc-status-details-bin'
+from ._common import code_to_grpc_status_code, GRPC_DETAILS_METADATA_KEY
 
 
 class _Status(
@@ -31,13 +29,6 @@ class _Status(
     pass
 
 
-def _code_to_grpc_status_code(code):
-    try:
-        return _CODE_TO_GRPC_CODE_MAPPING[code]
-    except KeyError:
-        raise ValueError('Invalid status code %s' % code)
-
-
 def from_call(call):
     """Returns a google.rpc.status.Status message corresponding to a given grpc.Call.
 
@@ -56,13 +47,12 @@ def from_call(call):
     if call.trailing_metadata() is None:
         return None
     for key, value in call.trailing_metadata():
-        if key == _GRPC_DETAILS_METADATA_KEY:
+        if key == GRPC_DETAILS_METADATA_KEY:
             rich_status = status_pb2.Status.FromString(value)
             if call.code().value[0] != rich_status.code:
                 raise ValueError(
                     'Code in Status proto (%s) doesn\'t match status code (%s)'
-                    %
-                    (_code_to_grpc_status_code(rich_status.code), call.code()))
+                    % (code_to_grpc_status_code(rich_status.code), call.code()))
             if call.details() != rich_status.message:
                 raise ValueError(
                     'Message in Status proto (%s) doesn\'t match status details (%s)'
@@ -83,7 +73,17 @@ def to_status(status):
     Returns:
       A grpc.Status instance representing the input google.rpc.status.Status message.
     """
-    return _Status(code=_code_to_grpc_status_code(status.code),
+    return _Status(code=code_to_grpc_status_code(status.code),
                    details=status.message,
-                   trailing_metadata=((_GRPC_DETAILS_METADATA_KEY,
+                   trailing_metadata=((GRPC_DETAILS_METADATA_KEY,
                                        status.SerializeToString()),))
+
+
+__all__ = [
+    'from_call',
+    'to_status',
+]
+
+if sys.version_info[0] >= 3 and sys.version_info[1] >= 6:
+    from . import _async as aio  # pylint: disable=unused-import
+    __all__.append('aio')
index b74fa95..a5de312 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_status/grpc_version.py.template`!!!
 
-VERSION = '1.29.1'
+VERSION = '1.30.0'
index fdc618e..a1eda0e 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!!
 
-VERSION = '1.29.1'
+VERSION = '1.30.0'
index a13dd66..f1b79ab 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!!
 
-VERSION = '1.29.1'
+VERSION = '1.30.0'
index 671f065..6c1ed2f 100644 (file)
@@ -43,8 +43,8 @@ INSTALL_REQUIRES = (
     'grpcio-status>={version}'.format(version=grpc_version.VERSION),
     'grpcio-tools>={version}'.format(version=grpc_version.VERSION),
     'grpcio-health-checking>={version}'.format(version=grpc_version.VERSION),
-    'oauth2client>=1.4.7', 'protobuf>=3.6.0', 'six>=1.10', 'google-auth>=1.0.0',
-    'requests>=2.14.2')
+    'oauth2client>=1.4.7', 'protobuf>=3.6.0', 'six>=1.10',
+    'google-auth>=1.17.2', 'requests>=2.14.2')
 
 if not PY3:
     INSTALL_REQUIRES += ('futures>=2.2.0',)
index 71b2fec..04b82c0 100644 (file)
@@ -43,6 +43,10 @@ def parse_interop_client_args():
                         default=False,
                         type=resources.parse_bool,
                         help='require a secure connection')
+    parser.add_argument('--use_alts',
+                        default=False,
+                        type=resources.parse_bool,
+                        help='require an ALTS secure connection')
     parser.add_argument('--use_test_ca',
                         default=False,
                         type=resources.parse_bool,
@@ -85,22 +89,25 @@ def _create_call_credentials(args):
 def get_secure_channel_parameters(args):
     call_credentials = _create_call_credentials(args)
 
-    if args.use_test_ca:
-        root_certificates = resources.test_root_certificates()
-    else:
-        root_certificates = None  # will load default roots.
-
-    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_opts = None
-    if args.server_host_override:
-        channel_opts = ((
-            'grpc.ssl_target_name_override',
-            args.server_host_override,
-        ),)
+    if args.use_tls:
+        if args.use_test_ca:
+            root_certificates = resources.test_root_certificates()
+        else:
+            root_certificates = None  # will load default roots.
+
+        channel_credentials = grpc.ssl_channel_credentials(root_certificates)
+        if call_credentials is not None:
+            channel_credentials = grpc.composite_channel_credentials(
+                channel_credentials, call_credentials)
+
+        if args.server_host_override:
+            channel_opts = ((
+                'grpc.ssl_target_name_override',
+                args.server_host_override,
+            ),)
+    elif args.use_alts:
+        channel_credentials = grpc.alts_channel_credentials()
 
     return channel_credentials, channel_opts
 
@@ -108,7 +115,7 @@ def get_secure_channel_parameters(args):
 def _create_channel(args):
     target = '{}:{}'.format(args.server_host, args.server_port)
 
-    if args.use_tls:
+    if args.use_tls or args.use_alts:
         channel_credentials, options = get_secure_channel_parameters(args)
         return grpc.secure_channel(target, channel_credentials, options)
     else:
index 0a0061f..c85adb0 100644 (file)
@@ -38,13 +38,20 @@ def parse_interop_server_arguments():
                         default=False,
                         type=resources.parse_bool,
                         help='require a secure connection')
+    parser.add_argument('--use_alts',
+                        default=False,
+                        type=resources.parse_bool,
+                        help='require an ALTS connection')
     return parser.parse_args()
 
 
-def get_server_credentials():
-    private_key = resources.private_key()
-    certificate_chain = resources.certificate_chain()
-    return grpc.ssl_server_credentials(((private_key, certificate_chain),))
+def get_server_credentials(use_tls):
+    if use_tls:
+        private_key = resources.private_key()
+        certificate_chain = resources.certificate_chain()
+        return grpc.ssl_server_credentials(((private_key, certificate_chain),))
+    else:
+        return grpc.alts_server_credentials()
 
 
 def serve():
@@ -53,8 +60,8 @@ def serve():
     server = test_common.test_server()
     test_pb2_grpc.add_TestServiceServicer_to_server(service.TestService(),
                                                     server)
-    if args.use_tls:
-        credentials = get_server_credentials()
+    if args.use_tls or args.use_alts:
+        credentials = get_server_credentials(args.use_tls)
         server.add_secure_port('[::]:{}'.format(args.port), credentials)
     else:
         server.add_insecure_port('[::]:{}'.format(args.port))
index cc0daba..a37ac3e 100644 (file)
@@ -63,6 +63,8 @@ class AllTest(unittest.TestCase):
             'LocalConnectionType',
             'local_channel_credentials',
             'local_server_credentials',
+            'alts_channel_credentials',
+            'alts_server_credentials',
             'unary_unary_rpc_method_handler',
             'unary_stream_rpc_method_handler',
             'stream_unary_rpc_method_handler',
index 3f3db2e..2f2eea6 100644 (file)
@@ -11,7 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-"""Tests of Channel Args on client/server side."""
+"""Tests of channel arguments on client/server side."""
 
 from concurrent import futures
 import unittest
index de9ded2..e2b36b1 100644 (file)
@@ -17,6 +17,7 @@ import time
 import weakref
 import unittest
 import threading
+import logging
 import socket
 from six.moves import queue
 
@@ -25,7 +26,7 @@ import grpc
 from tests.unit import test_common
 from tests.unit.framework.common import test_constants
 import tests.unit.framework.common
-from tests.unit.framework.common import bound_socket
+from tests.unit.framework.common import get_socket
 
 _UNARY_UNARY = '/test/UnaryUnary'
 _UNARY_STREAM = '/test/UnaryStream'
@@ -101,8 +102,9 @@ class _GenericHandler(grpc.GenericRpcHandler):
 
 def create_dummy_channel():
     """Creating dummy channels is a workaround for retries"""
-    with bound_socket() as (host, port):
-        return grpc.insecure_channel('{}:{}'.format(host, port))
+    host, port, sock = get_socket(sock_options=(socket.SO_REUSEADDR,))
+    sock.close()
+    return grpc.insecure_channel('{}:{}'.format(host, port))
 
 
 def perform_unary_unary_call(channel, wait_for_ready=None):
@@ -203,51 +205,56 @@ class MetadataFlagsTest(unittest.TestCase):
         #   main thread. So, it need another method to store the
         #   exceptions and raise them again in main thread.
         unhandled_exceptions = queue.Queue()
-        with bound_socket(listen=False) as (host, port):
-            addr = '{}:{}'.format(host, port)
-            wg = test_common.WaitGroup(len(_ALL_CALL_CASES))
 
-            def wait_for_transient_failure(channel_connectivity):
-                if channel_connectivity == grpc.ChannelConnectivity.TRANSIENT_FAILURE:
+        # We just need an unused TCP port
+        host, port, sock = get_socket(sock_options=(socket.SO_REUSEADDR,))
+        sock.close()
+
+        addr = '{}:{}'.format(host, port)
+        wg = test_common.WaitGroup(len(_ALL_CALL_CASES))
+
+        def wait_for_transient_failure(channel_connectivity):
+            if channel_connectivity == grpc.ChannelConnectivity.TRANSIENT_FAILURE:
+                wg.done()
+
+        def test_call(perform_call):
+            with grpc.insecure_channel(addr) as channel:
+                try:
+                    channel.subscribe(wait_for_transient_failure)
+                    perform_call(channel, wait_for_ready=True)
+                except BaseException as e:  # pylint: disable=broad-except
+                    # If the call failed, the thread would be destroyed. The
+                    # channel object can be collected before calling the
+                    # callback, which will result in a deadlock.
                     wg.done()
+                    unhandled_exceptions.put(e, True)
 
-            def test_call(perform_call):
-                with grpc.insecure_channel(addr) as channel:
-                    try:
-                        channel.subscribe(wait_for_transient_failure)
-                        perform_call(channel, wait_for_ready=True)
-                    except BaseException as e:  # pylint: disable=broad-except
-                        # If the call failed, the thread would be destroyed. The
-                        # channel object can be collected before calling the
-                        # callback, which will result in a deadlock.
-                        wg.done()
-                        unhandled_exceptions.put(e, True)
-
-            test_threads = []
-            for perform_call in _ALL_CALL_CASES:
-                test_thread = threading.Thread(target=test_call,
-                                               args=(perform_call,))
-                test_thread.exception = None
-                test_thread.start()
-                test_threads.append(test_thread)
-
-            # Start the server after the connections are waiting
-            wg.wait()
-            server = test_common.test_server(reuse_port=True)
-            server.add_generic_rpc_handlers(
-                (_GenericHandler(weakref.proxy(self)),))
-            server.add_insecure_port(addr)
-            server.start()
-
-            for test_thread in test_threads:
-                test_thread.join()
-
-            # Stop the server to make test end properly
-            server.stop(0)
-
-            if not unhandled_exceptions.empty():
-                raise unhandled_exceptions.get(True)
+        test_threads = []
+        for perform_call in _ALL_CALL_CASES:
+            test_thread = threading.Thread(target=test_call,
+                                           args=(perform_call,))
+            test_thread.daemon = True
+            test_thread.exception = None
+            test_thread.start()
+            test_threads.append(test_thread)
+
+        # Start the server after the connections are waiting
+        wg.wait()
+        server = test_common.test_server(reuse_port=True)
+        server.add_generic_rpc_handlers((_GenericHandler(weakref.proxy(self)),))
+        server.add_insecure_port(addr)
+        server.start()
+
+        for test_thread in test_threads:
+            test_thread.join()
+
+        # Stop the server to make test end properly
+        server.stop(0)
+
+        if not unhandled_exceptions.empty():
+            raise unhandled_exceptions.get(True)
 
 
 if __name__ == '__main__':
+    logging.basicConfig(level=logging.DEBUG)
     unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests_aio/channelz/BUILD.bazel b/src/python/grpcio_tests/tests_aio/channelz/BUILD.bazel
new file mode 100644 (file)
index 0000000..2ead714
--- /dev/null
@@ -0,0 +1,29 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+package(default_visibility = ["//visibility:public"])
+
+py_test(
+    name = "channelz_servicer_test",
+    size = "small",
+    srcs = ["channelz_servicer_test.py"],
+    imports = ["../../"],
+    python_version = "PY3",
+    deps = [
+        "//src/python/grpcio/grpc:grpcio",
+        "//src/python/grpcio_channelz/grpc_channelz/v1:grpc_channelz",
+        "//src/python/grpcio_tests/tests/unit/framework/common",
+        "//src/python/grpcio_tests/tests_aio/unit:_test_base",
+    ],
+)
diff --git a/src/python/grpcio_tests/tests_aio/channelz/__init__.py b/src/python/grpcio_tests/tests_aio/channelz/__init__.py
new file mode 100644 (file)
index 0000000..1517f71
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/src/python/grpcio_tests/tests_aio/channelz/channelz_servicer_test.py b/src/python/grpcio_tests/tests_aio/channelz/channelz_servicer_test.py
new file mode 100644 (file)
index 0000000..d6e9fd4
--- /dev/null
@@ -0,0 +1,474 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests of grpc_channelz.v1.channelz."""
+
+import unittest
+import logging
+import asyncio
+
+import grpc
+from grpc.experimental import aio
+
+from grpc_channelz.v1 import channelz
+from grpc_channelz.v1 import channelz_pb2
+from grpc_channelz.v1 import channelz_pb2_grpc
+
+from tests.unit.framework.common import test_constants
+from tests_aio.unit._test_base import AioTestBase
+
+_SUCCESSFUL_UNARY_UNARY = '/test/SuccessfulUnaryUnary'
+_FAILED_UNARY_UNARY = '/test/FailedUnaryUnary'
+_SUCCESSFUL_STREAM_STREAM = '/test/SuccessfulStreamStream'
+
+_REQUEST = b'\x00\x00\x00'
+_RESPONSE = b'\x01\x01\x01'
+
+_DISABLE_REUSE_PORT = (('grpc.so_reuseport', 0),)
+_ENABLE_CHANNELZ = (('grpc.enable_channelz', 1),)
+_DISABLE_CHANNELZ = (('grpc.enable_channelz', 0),)
+
+_LARGE_UNASSIGNED_ID = 10000
+
+
+async def _successful_unary_unary(request, servicer_context):
+    return _RESPONSE
+
+
+async def _failed_unary_unary(request, servicer_context):
+    servicer_context.set_code(grpc.StatusCode.INTERNAL)
+    servicer_context.set_details("Channelz Test Intended Failure")
+
+
+async def _successful_stream_stream(request_iterator, servicer_context):
+    async for _ in request_iterator:
+        yield _RESPONSE
+
+
+class _GenericHandler(grpc.GenericRpcHandler):
+
+    def service(self, handler_call_details):
+        if handler_call_details.method == _SUCCESSFUL_UNARY_UNARY:
+            return grpc.unary_unary_rpc_method_handler(_successful_unary_unary)
+        elif handler_call_details.method == _FAILED_UNARY_UNARY:
+            return grpc.unary_unary_rpc_method_handler(_failed_unary_unary)
+        elif handler_call_details.method == _SUCCESSFUL_STREAM_STREAM:
+            return grpc.stream_stream_rpc_method_handler(
+                _successful_stream_stream)
+        else:
+            return None
+
+
+class _ChannelServerPair:
+
+    def __init__(self):
+        self.address = ''
+        self.server = None
+        self.channel = None
+        self.server_ref_id = None
+        self.channel_ref_id = None
+
+    async def start(self):
+        # Server will enable channelz service
+        self.server = aio.server(options=_DISABLE_REUSE_PORT + _ENABLE_CHANNELZ)
+        port = self.server.add_insecure_port('[::]:0')
+        self.address = 'localhost:%d' % port
+        self.server.add_generic_rpc_handlers((_GenericHandler(),))
+        await self.server.start()
+
+        # Channel will enable channelz service...
+        self.channel = aio.insecure_channel(self.address,
+                                            options=_ENABLE_CHANNELZ)
+
+    async def bind_channelz(self, channelz_stub):
+        resp = await channelz_stub.GetTopChannels(
+            channelz_pb2.GetTopChannelsRequest(start_channel_id=0))
+        for channel in resp.channel:
+            if channel.data.target == self.address:
+                self.channel_ref_id = channel.ref.channel_id
+
+        resp = await channelz_stub.GetServers(
+            channelz_pb2.GetServersRequest(start_server_id=0))
+        self.server_ref_id = resp.server[-1].ref.server_id
+
+    async def stop(self):
+        await self.channel.close()
+        await self.server.stop(None)
+
+
+async def _create_channel_server_pairs(n, channelz_stub=None):
+    """Create channel-server pairs."""
+    pairs = [_ChannelServerPair() for i in range(n)]
+    for pair in pairs:
+        await pair.start()
+        if channelz_stub:
+            await pair.bind_channelz(channelz_stub)
+    return pairs
+
+
+async def _destroy_channel_server_pairs(pairs):
+    for pair in pairs:
+        await pair.stop()
+
+
+class ChannelzServicerTest(AioTestBase):
+
+    async def setUp(self):
+        # This server is for Channelz info fetching only
+        # It self should not enable Channelz
+        self._server = aio.server(options=_DISABLE_REUSE_PORT +
+                                  _DISABLE_CHANNELZ)
+        port = self._server.add_insecure_port('[::]:0')
+        channelz.add_channelz_servicer(self._server)
+        await self._server.start()
+
+        # This channel is used to fetch Channelz info only
+        # Channelz should not be enabled
+        self._channel = aio.insecure_channel('localhost:%d' % port,
+                                             options=_DISABLE_CHANNELZ)
+        self._channelz_stub = channelz_pb2_grpc.ChannelzStub(self._channel)
+
+    async def tearDown(self):
+        await self._channel.close()
+        await self._server.stop(None)
+
+    async def _get_server_by_ref_id(self, ref_id):
+        """Server id may not be consecutive"""
+        resp = await self._channelz_stub.GetServers(
+            channelz_pb2.GetServersRequest(start_server_id=ref_id))
+        self.assertEqual(ref_id, resp.server[0].ref.server_id)
+        return resp.server[0]
+
+    async def _send_successful_unary_unary(self, pair):
+        call = pair.channel.unary_unary(_SUCCESSFUL_UNARY_UNARY)(_REQUEST)
+        self.assertEqual(grpc.StatusCode.OK, await call.code())
+
+    async def _send_failed_unary_unary(self, pair):
+        try:
+            await pair.channel.unary_unary(_FAILED_UNARY_UNARY)(_REQUEST)
+        except grpc.RpcError:
+            return
+        else:
+            self.fail("This call supposed to fail")
+
+    async def _send_successful_stream_stream(self, pair):
+        call = pair.channel.stream_stream(_SUCCESSFUL_STREAM_STREAM)(iter(
+            [_REQUEST] * test_constants.STREAM_LENGTH))
+        cnt = 0
+        async for _ in call:
+            cnt += 1
+        self.assertEqual(cnt, test_constants.STREAM_LENGTH)
+
+    async def test_get_top_channels_high_start_id(self):
+        pairs = await _create_channel_server_pairs(1)
+
+        resp = await self._channelz_stub.GetTopChannels(
+            channelz_pb2.GetTopChannelsRequest(
+                start_channel_id=_LARGE_UNASSIGNED_ID))
+        self.assertEqual(len(resp.channel), 0)
+        self.assertEqual(resp.end, True)
+
+        await _destroy_channel_server_pairs(pairs)
+
+    async def test_successful_request(self):
+        pairs = await _create_channel_server_pairs(1, self._channelz_stub)
+
+        await self._send_successful_unary_unary(pairs[0])
+        resp = await self._channelz_stub.GetChannel(
+            channelz_pb2.GetChannelRequest(channel_id=pairs[0].channel_ref_id))
+
+        self.assertEqual(resp.channel.data.calls_started, 1)
+        self.assertEqual(resp.channel.data.calls_succeeded, 1)
+        self.assertEqual(resp.channel.data.calls_failed, 0)
+
+        await _destroy_channel_server_pairs(pairs)
+
+    async def test_failed_request(self):
+        pairs = await _create_channel_server_pairs(1, self._channelz_stub)
+
+        await self._send_failed_unary_unary(pairs[0])
+        resp = await self._channelz_stub.GetChannel(
+            channelz_pb2.GetChannelRequest(channel_id=pairs[0].channel_ref_id))
+        self.assertEqual(resp.channel.data.calls_started, 1)
+        self.assertEqual(resp.channel.data.calls_succeeded, 0)
+        self.assertEqual(resp.channel.data.calls_failed, 1)
+
+        await _destroy_channel_server_pairs(pairs)
+
+    async def test_many_requests(self):
+        pairs = await _create_channel_server_pairs(1, self._channelz_stub)
+
+        k_success = 7
+        k_failed = 9
+        for i in range(k_success):
+            await self._send_successful_unary_unary(pairs[0])
+        for i in range(k_failed):
+            await self._send_failed_unary_unary(pairs[0])
+        resp = await self._channelz_stub.GetChannel(
+            channelz_pb2.GetChannelRequest(channel_id=pairs[0].channel_ref_id))
+        self.assertEqual(resp.channel.data.calls_started, k_success + k_failed)
+        self.assertEqual(resp.channel.data.calls_succeeded, k_success)
+        self.assertEqual(resp.channel.data.calls_failed, k_failed)
+
+        await _destroy_channel_server_pairs(pairs)
+
+    async def test_many_requests_many_channel(self):
+        k_channels = 4
+        pairs = await _create_channel_server_pairs(k_channels,
+                                                   self._channelz_stub)
+        k_success = 11
+        k_failed = 13
+        for i in range(k_success):
+            await self._send_successful_unary_unary(pairs[0])
+            await self._send_successful_unary_unary(pairs[2])
+        for i in range(k_failed):
+            await self._send_failed_unary_unary(pairs[1])
+            await self._send_failed_unary_unary(pairs[2])
+
+        # The first channel saw only successes
+        resp = await self._channelz_stub.GetChannel(
+            channelz_pb2.GetChannelRequest(channel_id=pairs[0].channel_ref_id))
+        self.assertEqual(resp.channel.data.calls_started, k_success)
+        self.assertEqual(resp.channel.data.calls_succeeded, k_success)
+        self.assertEqual(resp.channel.data.calls_failed, 0)
+
+        # The second channel saw only failures
+        resp = await self._channelz_stub.GetChannel(
+            channelz_pb2.GetChannelRequest(channel_id=pairs[1].channel_ref_id))
+        self.assertEqual(resp.channel.data.calls_started, k_failed)
+        self.assertEqual(resp.channel.data.calls_succeeded, 0)
+        self.assertEqual(resp.channel.data.calls_failed, k_failed)
+
+        # The third channel saw both successes and failures
+        resp = await self._channelz_stub.GetChannel(
+            channelz_pb2.GetChannelRequest(channel_id=pairs[2].channel_ref_id))
+        self.assertEqual(resp.channel.data.calls_started, k_success + k_failed)
+        self.assertEqual(resp.channel.data.calls_succeeded, k_success)
+        self.assertEqual(resp.channel.data.calls_failed, k_failed)
+
+        # The fourth channel saw nothing
+        resp = await self._channelz_stub.GetChannel(
+            channelz_pb2.GetChannelRequest(channel_id=pairs[3].channel_ref_id))
+        self.assertEqual(resp.channel.data.calls_started, 0)
+        self.assertEqual(resp.channel.data.calls_succeeded, 0)
+        self.assertEqual(resp.channel.data.calls_failed, 0)
+
+        await _destroy_channel_server_pairs(pairs)
+
+    async def test_many_subchannels(self):
+        k_channels = 4
+        pairs = await _create_channel_server_pairs(k_channels,
+                                                   self._channelz_stub)
+        k_success = 17
+        k_failed = 19
+        for i in range(k_success):
+            await self._send_successful_unary_unary(pairs[0])
+            await self._send_successful_unary_unary(pairs[2])
+        for i in range(k_failed):
+            await self._send_failed_unary_unary(pairs[1])
+            await self._send_failed_unary_unary(pairs[2])
+
+        for i in range(k_channels):
+            gc_resp = await self._channelz_stub.GetChannel(
+                channelz_pb2.GetChannelRequest(
+                    channel_id=pairs[i].channel_ref_id))
+            # If no call performed in the channel, there shouldn't be any subchannel
+            if gc_resp.channel.data.calls_started == 0:
+                self.assertEqual(len(gc_resp.channel.subchannel_ref), 0)
+                continue
+
+            # Otherwise, the subchannel should exist
+            self.assertGreater(len(gc_resp.channel.subchannel_ref), 0)
+            gsc_resp = await self._channelz_stub.GetSubchannel(
+                channelz_pb2.GetSubchannelRequest(
+                    subchannel_id=gc_resp.channel.subchannel_ref[0].
+                    subchannel_id))
+            self.assertEqual(gc_resp.channel.data.calls_started,
+                             gsc_resp.subchannel.data.calls_started)
+            self.assertEqual(gc_resp.channel.data.calls_succeeded,
+                             gsc_resp.subchannel.data.calls_succeeded)
+            self.assertEqual(gc_resp.channel.data.calls_failed,
+                             gsc_resp.subchannel.data.calls_failed)
+
+        await _destroy_channel_server_pairs(pairs)
+
+    async def test_server_call(self):
+        pairs = await _create_channel_server_pairs(1, self._channelz_stub)
+
+        k_success = 23
+        k_failed = 29
+        for i in range(k_success):
+            await self._send_successful_unary_unary(pairs[0])
+        for i in range(k_failed):
+            await self._send_failed_unary_unary(pairs[0])
+
+        resp = await self._get_server_by_ref_id(pairs[0].server_ref_id)
+        self.assertEqual(resp.data.calls_started, k_success + k_failed)
+        self.assertEqual(resp.data.calls_succeeded, k_success)
+        self.assertEqual(resp.data.calls_failed, k_failed)
+
+        await _destroy_channel_server_pairs(pairs)
+
+    async def test_many_subchannels_and_sockets(self):
+        k_channels = 4
+        pairs = await _create_channel_server_pairs(k_channels,
+                                                   self._channelz_stub)
+        k_success = 3
+        k_failed = 5
+        for i in range(k_success):
+            await self._send_successful_unary_unary(pairs[0])
+            await self._send_successful_unary_unary(pairs[2])
+        for i in range(k_failed):
+            await self._send_failed_unary_unary(pairs[1])
+            await self._send_failed_unary_unary(pairs[2])
+
+        for i in range(k_channels):
+            gc_resp = await self._channelz_stub.GetChannel(
+                channelz_pb2.GetChannelRequest(
+                    channel_id=pairs[i].channel_ref_id))
+
+            # If no call performed in the channel, there shouldn't be any subchannel
+            if gc_resp.channel.data.calls_started == 0:
+                self.assertEqual(len(gc_resp.channel.subchannel_ref), 0)
+                continue
+
+            # Otherwise, the subchannel should exist
+            self.assertGreater(len(gc_resp.channel.subchannel_ref), 0)
+            gsc_resp = await self._channelz_stub.GetSubchannel(
+                channelz_pb2.GetSubchannelRequest(
+                    subchannel_id=gc_resp.channel.subchannel_ref[0].
+                    subchannel_id))
+            self.assertEqual(len(gsc_resp.subchannel.socket_ref), 1)
+
+            gs_resp = await self._channelz_stub.GetSocket(
+                channelz_pb2.GetSocketRequest(
+                    socket_id=gsc_resp.subchannel.socket_ref[0].socket_id))
+            self.assertEqual(gsc_resp.subchannel.data.calls_started,
+                             gs_resp.socket.data.streams_started)
+            self.assertEqual(0, gs_resp.socket.data.streams_failed)
+            # Calls started == messages sent, only valid for unary calls
+            self.assertEqual(gsc_resp.subchannel.data.calls_started,
+                             gs_resp.socket.data.messages_sent)
+
+        await _destroy_channel_server_pairs(pairs)
+
+    async def test_streaming_rpc(self):
+        pairs = await _create_channel_server_pairs(1, self._channelz_stub)
+        # In C++, the argument for _send_successful_stream_stream is message length.
+        # Here the argument is still channel idx, to be consistent with the other two.
+        await self._send_successful_stream_stream(pairs[0])
+
+        gc_resp = await self._channelz_stub.GetChannel(
+            channelz_pb2.GetChannelRequest(channel_id=pairs[0].channel_ref_id))
+        self.assertEqual(gc_resp.channel.data.calls_started, 1)
+        self.assertEqual(gc_resp.channel.data.calls_succeeded, 1)
+        self.assertEqual(gc_resp.channel.data.calls_failed, 0)
+        # Subchannel exists
+        self.assertGreater(len(gc_resp.channel.subchannel_ref), 0)
+
+        gsc_resp = await self._channelz_stub.GetSubchannel(
+            channelz_pb2.GetSubchannelRequest(
+                subchannel_id=gc_resp.channel.subchannel_ref[0].subchannel_id))
+        self.assertEqual(gsc_resp.subchannel.data.calls_started, 1)
+        self.assertEqual(gsc_resp.subchannel.data.calls_succeeded, 1)
+        self.assertEqual(gsc_resp.subchannel.data.calls_failed, 0)
+        # Socket exists
+        self.assertEqual(len(gsc_resp.subchannel.socket_ref), 1)
+
+        gs_resp = await self._channelz_stub.GetSocket(
+            channelz_pb2.GetSocketRequest(
+                socket_id=gsc_resp.subchannel.socket_ref[0].socket_id))
+        self.assertEqual(gs_resp.socket.data.streams_started, 1)
+        self.assertEqual(gs_resp.socket.data.streams_succeeded, 1)
+        self.assertEqual(gs_resp.socket.data.streams_failed, 0)
+        self.assertEqual(gs_resp.socket.data.messages_sent,
+                         test_constants.STREAM_LENGTH)
+        self.assertEqual(gs_resp.socket.data.messages_received,
+                         test_constants.STREAM_LENGTH)
+
+        await _destroy_channel_server_pairs(pairs)
+
+    async def test_server_sockets(self):
+        pairs = await _create_channel_server_pairs(1, self._channelz_stub)
+
+        await self._send_successful_unary_unary(pairs[0])
+        await self._send_failed_unary_unary(pairs[0])
+
+        resp = await self._get_server_by_ref_id(pairs[0].server_ref_id)
+        self.assertEqual(resp.data.calls_started, 2)
+        self.assertEqual(resp.data.calls_succeeded, 1)
+        self.assertEqual(resp.data.calls_failed, 1)
+
+        gss_resp = await self._channelz_stub.GetServerSockets(
+            channelz_pb2.GetServerSocketsRequest(server_id=resp.ref.server_id,
+                                                 start_socket_id=0))
+        # If the RPC call failed, it will raise a grpc.RpcError
+        # So, if there is no exception raised, considered pass
+        await _destroy_channel_server_pairs(pairs)
+
+    async def test_server_listen_sockets(self):
+        pairs = await _create_channel_server_pairs(1, self._channelz_stub)
+
+        resp = await self._get_server_by_ref_id(pairs[0].server_ref_id)
+        self.assertEqual(len(resp.listen_socket), 1)
+
+        gs_resp = await self._channelz_stub.GetSocket(
+            channelz_pb2.GetSocketRequest(
+                socket_id=resp.listen_socket[0].socket_id))
+        # If the RPC call failed, it will raise a grpc.RpcError
+        # So, if there is no exception raised, considered pass
+        await _destroy_channel_server_pairs(pairs)
+
+    async def test_invalid_query_get_server(self):
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await self._channelz_stub.GetServer(
+                channelz_pb2.GetServerRequest(server_id=_LARGE_UNASSIGNED_ID))
+        self.assertEqual(grpc.StatusCode.NOT_FOUND,
+                         exception_context.exception.code())
+
+    async def test_invalid_query_get_channel(self):
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await self._channelz_stub.GetChannel(
+                channelz_pb2.GetChannelRequest(channel_id=_LARGE_UNASSIGNED_ID))
+        self.assertEqual(grpc.StatusCode.NOT_FOUND,
+                         exception_context.exception.code())
+
+    async def test_invalid_query_get_subchannel(self):
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await self._channelz_stub.GetSubchannel(
+                channelz_pb2.GetSubchannelRequest(
+                    subchannel_id=_LARGE_UNASSIGNED_ID))
+        self.assertEqual(grpc.StatusCode.NOT_FOUND,
+                         exception_context.exception.code())
+
+    async def test_invalid_query_get_socket(self):
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await self._channelz_stub.GetSocket(
+                channelz_pb2.GetSocketRequest(socket_id=_LARGE_UNASSIGNED_ID))
+        self.assertEqual(grpc.StatusCode.NOT_FOUND,
+                         exception_context.exception.code())
+
+    async def test_invalid_query_get_server_sockets(self):
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await self._channelz_stub.GetServerSockets(
+                channelz_pb2.GetServerSocketsRequest(
+                    server_id=_LARGE_UNASSIGNED_ID,
+                    start_socket_id=0,
+                ))
+        self.assertEqual(grpc.StatusCode.NOT_FOUND,
+                         exception_context.exception.code())
+
+
+if __name__ == '__main__':
+    logging.basicConfig(level=logging.DEBUG)
+    unittest.main(verbosity=2)
index ac6c84b..a539dbf 100644 (file)
@@ -108,7 +108,10 @@ class HealthServicerTest(AioTestBase):
                          (await queue.get()).status)
 
         call.cancel()
-        await task
+
+        with self.assertRaises(asyncio.CancelledError):
+            await task
+
         self.assertTrue(queue.empty())
 
     async def test_watch_new_service(self):
@@ -131,7 +134,10 @@ class HealthServicerTest(AioTestBase):
                          (await queue.get()).status)
 
         call.cancel()
-        await task
+
+        with self.assertRaises(asyncio.CancelledError):
+            await task
+
         self.assertTrue(queue.empty())
 
     async def test_watch_service_isolation(self):
@@ -151,7 +157,10 @@ class HealthServicerTest(AioTestBase):
             await asyncio.wait_for(queue.get(), test_constants.SHORT_TIMEOUT)
 
         call.cancel()
-        await task
+
+        with self.assertRaises(asyncio.CancelledError):
+            await task
+
         self.assertTrue(queue.empty())
 
     async def test_two_watchers(self):
@@ -177,8 +186,13 @@ class HealthServicerTest(AioTestBase):
 
         call1.cancel()
         call2.cancel()
-        await task1
-        await task2
+
+        with self.assertRaises(asyncio.CancelledError):
+            await task1
+
+        with self.assertRaises(asyncio.CancelledError):
+            await task2
+
         self.assertTrue(queue1.empty())
         self.assertTrue(queue2.empty())
 
@@ -194,7 +208,9 @@ class HealthServicerTest(AioTestBase):
         call.cancel()
         await self._servicer.set(_WATCH_SERVICE,
                                  health_pb2.HealthCheckResponse.SERVING)
-        await task
+
+        with self.assertRaises(asyncio.CancelledError):
+            await task
 
         # Wait for the serving coroutine to process client cancellation.
         timeout = time.monotonic() + test_constants.TIME_ALLOWANCE
@@ -226,7 +242,10 @@ class HealthServicerTest(AioTestBase):
                          resp.status)
 
         call.cancel()
-        await task
+
+        with self.assertRaises(asyncio.CancelledError):
+            await task
+
         self.assertTrue(queue.empty())
 
     async def test_no_duplicate_status(self):
@@ -251,7 +270,10 @@ class HealthServicerTest(AioTestBase):
             last_status = status
 
         call.cancel()
-        await task
+
+        with self.assertRaises(asyncio.CancelledError):
+            await task
+
         self.assertTrue(queue.empty())
 
 
index 89793f9..7731f3b 100644 (file)
@@ -30,7 +30,7 @@ _LOGGER.setLevel(logging.DEBUG)
 def _create_channel(args):
     target = f'{args.server_host}:{args.server_port}'
 
-    if args.use_tls:
+    if args.use_tls or args.use_alts:
         channel_credentials, options = interop_client_lib.get_secure_channel_parameters(
             args)
         return aio.secure_channel(target, channel_credentials, options)
index 06a6c51..509abdf 100644 (file)
@@ -30,9 +30,8 @@ _LOGGER.setLevel(logging.DEBUG)
 async def serve():
     args = interop_server_lib.parse_interop_server_arguments()
 
-    if args.use_tls:
-        credentials = interop_server_lib.get_server_credentials()
-
+    if args.use_tls or args.use_alts:
+        credentials = interop_server_lib.get_server_credentials(args.use_tls)
         address, server = await _test_server.start_test_server(
             port=args.port, secure=True, server_credentials=credentials)
     else:
diff --git a/src/python/grpcio_tests/tests_aio/reflection/BUILD.bazel b/src/python/grpcio_tests/tests_aio/reflection/BUILD.bazel
new file mode 100644 (file)
index 0000000..88bf8cc
--- /dev/null
@@ -0,0 +1,30 @@
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+package(default_testonly = 1)
+
+py_test(
+    name = "reflection_servicer_test",
+    srcs = ["reflection_servicer_test.py"],
+    imports = ["../../"],
+    python_version = "PY3",
+    deps = [
+        "//src/proto/grpc/testing:empty_py_pb2",
+        "//src/proto/grpc/testing/proto2:empty2_extensions_proto",
+        "//src/proto/grpc/testing/proto2:empty2_proto",
+        "//src/python/grpcio/grpc:grpcio",
+        "//src/python/grpcio_reflection/grpc_reflection/v1alpha:grpc_reflection",
+        "//src/python/grpcio_tests/tests_aio/unit:_test_base",
+    ],
+)
diff --git a/src/python/grpcio_tests/tests_aio/reflection/__init__.py b/src/python/grpcio_tests/tests_aio/reflection/__init__.py
new file mode 100644 (file)
index 0000000..5772620
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2016 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/src/python/grpcio_tests/tests_aio/reflection/reflection_servicer_test.py b/src/python/grpcio_tests/tests_aio/reflection/reflection_servicer_test.py
new file mode 100644 (file)
index 0000000..edd2d79
--- /dev/null
@@ -0,0 +1,193 @@
+# Copyright 2016 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests of grpc_reflection.v1alpha.reflection."""
+
+import logging
+import unittest
+
+import grpc
+from google.protobuf import descriptor_pb2
+from grpc.experimental import aio
+
+from grpc_reflection.v1alpha import (reflection, reflection_pb2,
+                                     reflection_pb2_grpc)
+from src.proto.grpc.testing import empty_pb2
+from src.proto.grpc.testing.proto2 import empty2_extensions_pb2
+from tests_aio.unit._test_base import AioTestBase
+
+_EMPTY_PROTO_FILE_NAME = 'src/proto/grpc/testing/empty.proto'
+_EMPTY_PROTO_SYMBOL_NAME = 'grpc.testing.Empty'
+_SERVICE_NAMES = ('Angstrom', 'Bohr', 'Curie', 'Dyson', 'Einstein', 'Feynman',
+                  'Galilei')
+_EMPTY_EXTENSIONS_SYMBOL_NAME = 'grpc.testing.proto2.EmptyWithExtensions'
+_EMPTY_EXTENSIONS_NUMBERS = (
+    124,
+    125,
+    126,
+    127,
+    128,
+)
+
+
+def _file_descriptor_to_proto(descriptor):
+    proto = descriptor_pb2.FileDescriptorProto()
+    descriptor.CopyToProto(proto)
+    return proto.SerializeToString()
+
+
+class ReflectionServicerTest(AioTestBase):
+
+    async def setUp(self):
+        self._server = aio.server()
+        reflection.enable_server_reflection(_SERVICE_NAMES, self._server)
+        port = self._server.add_insecure_port('[::]:0')
+        await self._server.start()
+
+        self._channel = aio.insecure_channel('localhost:%d' % port)
+        self._stub = reflection_pb2_grpc.ServerReflectionStub(self._channel)
+
+    async def tearDown(self):
+        await self._server.stop(None)
+        await self._channel.close()
+
+    async def test_file_by_name(self):
+        requests = (
+            reflection_pb2.ServerReflectionRequest(
+                file_by_filename=_EMPTY_PROTO_FILE_NAME),
+            reflection_pb2.ServerReflectionRequest(
+                file_by_filename='i-donut-exist'),
+        )
+        responses = []
+        async for response in self._stub.ServerReflectionInfo(iter(requests)):
+            responses.append(response)
+        expected_responses = (
+            reflection_pb2.ServerReflectionResponse(
+                valid_host='',
+                file_descriptor_response=reflection_pb2.FileDescriptorResponse(
+                    file_descriptor_proto=(
+                        _file_descriptor_to_proto(empty_pb2.DESCRIPTOR),))),
+            reflection_pb2.ServerReflectionResponse(
+                valid_host='',
+                error_response=reflection_pb2.ErrorResponse(
+                    error_code=grpc.StatusCode.NOT_FOUND.value[0],
+                    error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(),
+                )),
+        )
+        self.assertSequenceEqual(expected_responses, responses)
+
+    async def test_file_by_symbol(self):
+        requests = (
+            reflection_pb2.ServerReflectionRequest(
+                file_containing_symbol=_EMPTY_PROTO_SYMBOL_NAME),
+            reflection_pb2.ServerReflectionRequest(
+                file_containing_symbol='i.donut.exist.co.uk.org.net.me.name.foo'
+            ),
+        )
+        responses = []
+        async for response in self._stub.ServerReflectionInfo(iter(requests)):
+            responses.append(response)
+        expected_responses = (
+            reflection_pb2.ServerReflectionResponse(
+                valid_host='',
+                file_descriptor_response=reflection_pb2.FileDescriptorResponse(
+                    file_descriptor_proto=(
+                        _file_descriptor_to_proto(empty_pb2.DESCRIPTOR),))),
+            reflection_pb2.ServerReflectionResponse(
+                valid_host='',
+                error_response=reflection_pb2.ErrorResponse(
+                    error_code=grpc.StatusCode.NOT_FOUND.value[0],
+                    error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(),
+                )),
+        )
+        self.assertSequenceEqual(expected_responses, responses)
+
+    async def test_file_containing_extension(self):
+        requests = (
+            reflection_pb2.ServerReflectionRequest(
+                file_containing_extension=reflection_pb2.ExtensionRequest(
+                    containing_type=_EMPTY_EXTENSIONS_SYMBOL_NAME,
+                    extension_number=125,
+                ),),
+            reflection_pb2.ServerReflectionRequest(
+                file_containing_extension=reflection_pb2.ExtensionRequest(
+                    containing_type='i.donut.exist.co.uk.org.net.me.name.foo',
+                    extension_number=55,
+                ),),
+        )
+        responses = []
+        async for response in self._stub.ServerReflectionInfo(iter(requests)):
+            responses.append(response)
+        expected_responses = (
+            reflection_pb2.ServerReflectionResponse(
+                valid_host='',
+                file_descriptor_response=reflection_pb2.FileDescriptorResponse(
+                    file_descriptor_proto=(_file_descriptor_to_proto(
+                        empty2_extensions_pb2.DESCRIPTOR),))),
+            reflection_pb2.ServerReflectionResponse(
+                valid_host='',
+                error_response=reflection_pb2.ErrorResponse(
+                    error_code=grpc.StatusCode.NOT_FOUND.value[0],
+                    error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(),
+                )),
+        )
+        self.assertSequenceEqual(expected_responses, responses)
+
+    async def test_extension_numbers_of_type(self):
+        requests = (
+            reflection_pb2.ServerReflectionRequest(
+                all_extension_numbers_of_type=_EMPTY_EXTENSIONS_SYMBOL_NAME),
+            reflection_pb2.ServerReflectionRequest(
+                all_extension_numbers_of_type='i.donut.exist.co.uk.net.name.foo'
+            ),
+        )
+        responses = []
+        async for response in self._stub.ServerReflectionInfo(iter(requests)):
+            responses.append(response)
+        expected_responses = (
+            reflection_pb2.ServerReflectionResponse(
+                valid_host='',
+                all_extension_numbers_response=reflection_pb2.
+                ExtensionNumberResponse(
+                    base_type_name=_EMPTY_EXTENSIONS_SYMBOL_NAME,
+                    extension_number=_EMPTY_EXTENSIONS_NUMBERS)),
+            reflection_pb2.ServerReflectionResponse(
+                valid_host='',
+                error_response=reflection_pb2.ErrorResponse(
+                    error_code=grpc.StatusCode.NOT_FOUND.value[0],
+                    error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(),
+                )),
+        )
+        self.assertSequenceEqual(expected_responses, responses)
+
+    async def test_list_services(self):
+        requests = (reflection_pb2.ServerReflectionRequest(list_services='',),)
+        responses = []
+        async for response in self._stub.ServerReflectionInfo(iter(requests)):
+            responses.append(response)
+        expected_responses = (reflection_pb2.ServerReflectionResponse(
+            valid_host='',
+            list_services_response=reflection_pb2.ListServiceResponse(
+                service=tuple(
+                    reflection_pb2.ServiceResponse(name=name)
+                    for name in _SERVICE_NAMES))),)
+        self.assertSequenceEqual(expected_responses, responses)
+
+    def test_reflection_service_name(self):
+        self.assertEqual(reflection.SERVICE_NAME,
+                         'grpc.reflection.v1alpha.ServerReflection')
+
+
+if __name__ == '__main__':
+    logging.basicConfig(level=logging.DEBUG)
+    unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests_aio/status/BUILD.bazel b/src/python/grpcio_tests/tests_aio/status/BUILD.bazel
new file mode 100644 (file)
index 0000000..2fd82f2
--- /dev/null
@@ -0,0 +1,30 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("@grpc_python_dependencies//:requirements.bzl", "requirement")
+
+py_test(
+    name = "grpc_status_test",
+    size = "small",
+    srcs = ["grpc_status_test.py"],
+    imports = ["../../"],
+    python_version = "PY3",
+    deps = [
+        "//src/python/grpcio/grpc:grpcio",
+        "//src/python/grpcio_status/grpc_status",
+        "//src/python/grpcio_tests/tests_aio/unit:_test_base",
+        requirement("protobuf"),
+        requirement("googleapis-common-protos"),
+    ],
+)
diff --git a/src/python/grpcio_tests/tests_aio/status/__init__.py b/src/python/grpcio_tests/tests_aio/status/__init__.py
new file mode 100644 (file)
index 0000000..1517f71
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/src/python/grpcio_tests/tests_aio/status/grpc_status_test.py b/src/python/grpcio_tests/tests_aio/status/grpc_status_test.py
new file mode 100644 (file)
index 0000000..980cf5a
--- /dev/null
@@ -0,0 +1,175 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests of grpc_status with gRPC AsyncIO stack."""
+
+import logging
+import traceback
+import unittest
+
+import grpc
+from google.protobuf import any_pb2
+from google.rpc import code_pb2, error_details_pb2, status_pb2
+from grpc.experimental import aio
+
+from grpc_status import rpc_status
+from tests_aio.unit._test_base import AioTestBase
+
+_STATUS_OK = '/test/StatusOK'
+_STATUS_NOT_OK = '/test/StatusNotOk'
+_ERROR_DETAILS = '/test/ErrorDetails'
+_INCONSISTENT = '/test/Inconsistent'
+_INVALID_CODE = '/test/InvalidCode'
+
+_REQUEST = b'\x00\x00\x00'
+_RESPONSE = b'\x01\x01\x01'
+
+_GRPC_DETAILS_METADATA_KEY = 'grpc-status-details-bin'
+
+_STATUS_DETAILS = 'This is an error detail'
+_STATUS_DETAILS_ANOTHER = 'This is another error detail'
+
+
+async def _ok_unary_unary(request, servicer_context):
+    return _RESPONSE
+
+
+async def _not_ok_unary_unary(request, servicer_context):
+    await servicer_context.abort(grpc.StatusCode.INTERNAL, _STATUS_DETAILS)
+
+
+async def _error_details_unary_unary(request, servicer_context):
+    details = any_pb2.Any()
+    details.Pack(
+        error_details_pb2.DebugInfo(stack_entries=traceback.format_stack(),
+                                    detail='Intentionally invoked'))
+    rich_status = status_pb2.Status(
+        code=code_pb2.INTERNAL,
+        message=_STATUS_DETAILS,
+        details=[details],
+    )
+    await servicer_context.abort_with_status(rpc_status.to_status(rich_status))
+
+
+async def _inconsistent_unary_unary(request, servicer_context):
+    rich_status = status_pb2.Status(
+        code=code_pb2.INTERNAL,
+        message=_STATUS_DETAILS,
+    )
+    servicer_context.set_code(grpc.StatusCode.NOT_FOUND)
+    servicer_context.set_details(_STATUS_DETAILS_ANOTHER)
+    # User put inconsistent status information in trailing metadata
+    servicer_context.set_trailing_metadata(
+        ((_GRPC_DETAILS_METADATA_KEY, rich_status.SerializeToString()),))
+
+
+async def _invalid_code_unary_unary(request, servicer_context):
+    rich_status = status_pb2.Status(
+        code=42,
+        message='Invalid code',
+    )
+    await servicer_context.abort_with_status(rpc_status.to_status(rich_status))
+
+
+class _GenericHandler(grpc.GenericRpcHandler):
+
+    def service(self, handler_call_details):
+        if handler_call_details.method == _STATUS_OK:
+            return grpc.unary_unary_rpc_method_handler(_ok_unary_unary)
+        elif handler_call_details.method == _STATUS_NOT_OK:
+            return grpc.unary_unary_rpc_method_handler(_not_ok_unary_unary)
+        elif handler_call_details.method == _ERROR_DETAILS:
+            return grpc.unary_unary_rpc_method_handler(
+                _error_details_unary_unary)
+        elif handler_call_details.method == _INCONSISTENT:
+            return grpc.unary_unary_rpc_method_handler(
+                _inconsistent_unary_unary)
+        elif handler_call_details.method == _INVALID_CODE:
+            return grpc.unary_unary_rpc_method_handler(
+                _invalid_code_unary_unary)
+        else:
+            return None
+
+
+class StatusTest(AioTestBase):
+
+    async def setUp(self):
+        self._server = aio.server()
+        self._server.add_generic_rpc_handlers((_GenericHandler(),))
+        port = self._server.add_insecure_port('[::]:0')
+        await self._server.start()
+
+        self._channel = aio.insecure_channel('localhost:%d' % port)
+
+    async def tearDown(self):
+        await self._server.stop(None)
+        await self._channel.close()
+
+    async def test_status_ok(self):
+        call = self._channel.unary_unary(_STATUS_OK)(_REQUEST)
+
+        # Succeed RPC doesn't have status
+        status = await rpc_status.aio.from_call(call)
+        self.assertIs(status, None)
+
+    async def test_status_not_ok(self):
+        call = self._channel.unary_unary(_STATUS_NOT_OK)(_REQUEST)
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await call
+        rpc_error = exception_context.exception
+
+        self.assertEqual(rpc_error.code(), grpc.StatusCode.INTERNAL)
+        # Failed RPC doesn't automatically generate status
+        status = await rpc_status.aio.from_call(call)
+        self.assertIs(status, None)
+
+    async def test_error_details(self):
+        call = self._channel.unary_unary(_ERROR_DETAILS)(_REQUEST)
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await call
+        rpc_error = exception_context.exception
+
+        status = await rpc_status.aio.from_call(call)
+        self.assertEqual(rpc_error.code(), grpc.StatusCode.INTERNAL)
+        self.assertEqual(status.code, code_pb2.Code.Value('INTERNAL'))
+
+        # Check if the underlying proto message is intact
+        self.assertTrue(status.details[0].Is(
+            error_details_pb2.DebugInfo.DESCRIPTOR))
+        info = error_details_pb2.DebugInfo()
+        status.details[0].Unpack(info)
+        self.assertIn('_error_details_unary_unary', info.stack_entries[-1])
+
+    async def test_code_message_validation(self):
+        call = self._channel.unary_unary(_INCONSISTENT)(_REQUEST)
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await call
+        rpc_error = exception_context.exception
+        self.assertEqual(rpc_error.code(), grpc.StatusCode.NOT_FOUND)
+
+        # Code/Message validation failed
+        with self.assertRaises(ValueError):
+            await rpc_status.aio.from_call(call)
+
+    async def test_invalid_code(self):
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await self._channel.unary_unary(_INVALID_CODE)(_REQUEST)
+        rpc_error = exception_context.exception
+        self.assertEqual(rpc_error.code(), grpc.StatusCode.UNKNOWN)
+        # Invalid status code exception raised during coversion
+        self.assertIn('Invalid status code', rpc_error.details())
+
+
+if __name__ == '__main__':
+    logging.basicConfig()
+    unittest.main(verbosity=2)
index 71f8733..f01d7d0 100644 (file)
@@ -1,8 +1,11 @@
 [
   "_sanity._sanity_test.AioSanityTest",
+  "channelz.channelz_servicer_test.ChannelzServicerTest",
   "health_check.health_servicer_test.HealthServicerTest",
   "interop.local_interop_test.InsecureLocalInteropTest",
   "interop.local_interop_test.SecureLocalInteropTest",
+  "reflection.reflection_servicer_test.ReflectionServicerTest",
+  "status.grpc_status_test.StatusTest",
   "unit._metadata_test.TestTypeMetadata",
   "unit.abort_test.TestAbort",
   "unit.aio_rpc_error_test.TestAioRpcError",
   "unit.channel_argument_test.TestChannelArgument",
   "unit.channel_ready_test.TestChannelReady",
   "unit.channel_test.TestChannel",
-  "unit.client_interceptor_test.TestInterceptedUnaryUnaryCall",
-  "unit.client_interceptor_test.TestUnaryUnaryClientInterceptor",
+  "unit.client_stream_stream_interceptor_test.TestStreamStreamClientInterceptor",
+  "unit.client_stream_unary_interceptor_test.TestStreamUnaryClientInterceptor",
+  "unit.client_unary_stream_interceptor_test.TestUnaryStreamClientInterceptor",
+  "unit.client_unary_unary_interceptor_test.TestInterceptedUnaryUnaryCall",
+  "unit.client_unary_unary_interceptor_test.TestUnaryUnaryClientInterceptor",
   "unit.close_channel_test.TestCloseChannel",
   "unit.compatibility_test.TestCompatibility",
   "unit.compression_test.TestCompression",
index 1b5a4d9..dab9454 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import asyncio
 import grpc
+from typing import AsyncIterable
 from grpc.experimental import aio
 from grpc.experimental.aio._typing import MetadataType, MetadatumType
 
+from tests.unit.framework.common import test_constants
+
 
 def seen_metadata(expected: MetadataType, actual: MetadataType):
     return not bool(set(expected) - set(actual))
@@ -32,3 +36,62 @@ async def block_until_certain_state(channel: aio.Channel,
     while state != expected_state:
         await channel.wait_for_state_change(state)
         state = channel.get_state()
+
+
+def inject_callbacks(call: aio.Call):
+    first_callback_ran = asyncio.Event()
+
+    def first_callback(call):
+        # Validate that all resopnses have been received
+        # and the call is an end state.
+        assert call.done()
+        first_callback_ran.set()
+
+    second_callback_ran = asyncio.Event()
+
+    def second_callback(call):
+        # Validate that all resopnses have been received
+        # and the call is an end state.
+        assert call.done()
+        second_callback_ran.set()
+
+    call.add_done_callback(first_callback)
+    call.add_done_callback(second_callback)
+
+    async def validation():
+        await asyncio.wait_for(
+            asyncio.gather(first_callback_ran.wait(),
+                           second_callback_ran.wait()),
+            test_constants.SHORT_TIMEOUT)
+
+    return validation()
+
+
+class CountingRequestIterator:
+
+    def __init__(self, request_iterator):
+        self.request_cnt = 0
+        self._request_iterator = request_iterator
+
+    async def _forward_requests(self):
+        async for request in self._request_iterator:
+            self.request_cnt += 1
+            yield request
+
+    def __aiter__(self):
+        return self._forward_requests()
+
+
+class CountingResponseIterator:
+
+    def __init__(self, response_iterator):
+        self.response_cnt = 0
+        self._response_iterator = response_iterator
+
+    async def _forward_responses(self):
+        async for response in self._response_iterator:
+            self.response_cnt += 1
+            yield response
+
+    def __aiter__(self):
+        return self._forward_responses()
index 2396608..5e5081a 100644 (file)
@@ -47,7 +47,7 @@ async def _maybe_echo_status(request: messages_pb2.SimpleRequest,
                                      request.response_status.message)
 
 
-class _TestServiceServicer(test_pb2_grpc.TestServiceServicer):
+class TestServiceServicer(test_pb2_grpc.TestServiceServicer):
 
     async def UnaryCall(self, request, context):
         await _maybe_echo_metadata(context)
@@ -102,7 +102,7 @@ class _TestServiceServicer(test_pb2_grpc.TestServiceServicer):
                                                  response_parameters.size))
 
 
-def _create_extra_generic_handler(servicer: _TestServiceServicer):
+def _create_extra_generic_handler(servicer: TestServiceServicer):
     # Add programatically extra methods not provided by the proto file
     # that are used during the tests
     rpc_method_handlers = {
@@ -123,7 +123,7 @@ async def start_test_server(port=0,
                             interceptors=None):
     server = aio.server(options=(('grpc.so_reuseport', 0),),
                         interceptors=interceptors)
-    servicer = _TestServiceServicer()
+    servicer = TestServiceServicer()
     test_pb2_grpc.add_TestServiceServicer_to_server(servicer, server)
 
     server.add_generic_rpc_handlers((_create_extra_generic_handler(servicer),))
index 2548e77..3ce2a2f 100644 (file)
@@ -217,6 +217,23 @@ class TestUnaryUnaryCall(_MulticallableTestMixin, AioTestBase):
 
 class TestUnaryStreamCall(_MulticallableTestMixin, AioTestBase):
 
+    async def test_call_rpc_error(self):
+        channel = aio.insecure_channel(UNREACHABLE_TARGET)
+        request = messages_pb2.StreamingOutputCallRequest()
+        stub = test_pb2_grpc.TestServiceStub(channel)
+        call = stub.StreamingOutputCall(request)
+
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            async for response in call:
+                pass
+
+        self.assertEqual(grpc.StatusCode.UNAVAILABLE,
+                         exception_context.exception.code())
+
+        self.assertTrue(call.done())
+        self.assertEqual(grpc.StatusCode.UNAVAILABLE, await call.code())
+        await channel.close()
+
     async def test_cancel_unary_stream(self):
         # Prepares the request
         request = messages_pb2.StreamingOutputCallRequest()
@@ -550,7 +567,6 @@ class TestStreamUnaryCall(_MulticallableTestMixin, AioTestBase):
 
         cancel_later_task = self.loop.create_task(cancel_later())
 
-        # No exceptions here
         with self.assertRaises(asyncio.CancelledError):
             await call
 
@@ -772,9 +788,10 @@ class TestStreamStreamCall(_MulticallableTestMixin, AioTestBase):
 
         cancel_later_task = self.loop.create_task(cancel_later())
 
-        # No exceptions here
-        async for response in call:
-            self.assertEqual(_RESPONSE_PAYLOAD_SIZE, len(response.payload.body))
+        with self.assertRaises(asyncio.CancelledError):
+            async for response in call:
+                self.assertEqual(_RESPONSE_PAYLOAD_SIZE,
+                                 len(response.payload.body))
 
         await request_iterator_received_the_exception.wait()
 
index 37bdbf8..75e4703 100644 (file)
@@ -16,6 +16,7 @@
 import asyncio
 import gc
 import logging
+import socket
 import time
 import unittest
 
@@ -31,7 +32,8 @@ from tests_aio.unit._test_server import start_test_server
 class TestChannelReady(AioTestBase):
 
     async def setUp(self):
-        address, self._port, self._socket = get_socket(listen=False)
+        address, self._port, self._socket = get_socket(
+            listen=False, sock_options=(socket.SO_REUSEADDR,))
         self._channel = aio.insecure_channel(f"{address}:{self._port}")
         self._socket.close()
 
diff --git a/src/python/grpcio_tests/tests_aio/unit/client_stream_stream_interceptor_test.py b/src/python/grpcio_tests/tests_aio/unit/client_stream_stream_interceptor_test.py
new file mode 100644 (file)
index 0000000..9ab54b3
--- /dev/null
@@ -0,0 +1,202 @@
+# Copyright 2020 The gRPC Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import logging
+import unittest
+
+import grpc
+
+from grpc.experimental import aio
+from tests_aio.unit._common import CountingResponseIterator, CountingRequestIterator
+from tests_aio.unit._test_server import start_test_server
+from tests_aio.unit._test_base import AioTestBase
+from src.proto.grpc.testing import messages_pb2, test_pb2_grpc
+
+_NUM_STREAM_RESPONSES = 5
+_NUM_STREAM_REQUESTS = 5
+_RESPONSE_PAYLOAD_SIZE = 7
+
+
+class _StreamStreamInterceptorEmpty(aio.StreamStreamClientInterceptor):
+
+    async def intercept_stream_stream(self, continuation, client_call_details,
+                                      request_iterator):
+        return await continuation(client_call_details, request_iterator)
+
+    def assert_in_final_state(self, test: unittest.TestCase):
+        pass
+
+
+class _StreamStreamInterceptorWithRequestAndResponseIterator(
+        aio.StreamStreamClientInterceptor):
+
+    async def intercept_stream_stream(self, continuation, client_call_details,
+                                      request_iterator):
+        self.request_iterator = CountingRequestIterator(request_iterator)
+        call = await continuation(client_call_details, self.request_iterator)
+        self.response_iterator = CountingResponseIterator(call)
+        return self.response_iterator
+
+    def assert_in_final_state(self, test: unittest.TestCase):
+        test.assertEqual(_NUM_STREAM_REQUESTS,
+                         self.request_iterator.request_cnt)
+        test.assertEqual(_NUM_STREAM_RESPONSES,
+                         self.response_iterator.response_cnt)
+
+
+class TestStreamStreamClientInterceptor(AioTestBase):
+
+    async def setUp(self):
+        self._server_target, self._server = await start_test_server()
+
+    async def tearDown(self):
+        await self._server.stop(None)
+
+    async def test_intercepts(self):
+
+        for interceptor_class in (
+                _StreamStreamInterceptorEmpty,
+                _StreamStreamInterceptorWithRequestAndResponseIterator):
+
+            with self.subTest(name=interceptor_class):
+                interceptor = interceptor_class()
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=[interceptor])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                # Prepares the request
+                request = messages_pb2.StreamingOutputCallRequest()
+                request.response_parameters.append(
+                    messages_pb2.ResponseParameters(
+                        size=_RESPONSE_PAYLOAD_SIZE))
+
+                async def request_iterator():
+                    for _ in range(_NUM_STREAM_REQUESTS):
+                        yield request
+
+                call = stub.FullDuplexCall(request_iterator())
+
+                await call.wait_for_connection()
+
+                response_cnt = 0
+                async for response in call:
+                    response_cnt += 1
+                    self.assertIsInstance(
+                        response, messages_pb2.StreamingOutputCallResponse)
+                    self.assertEqual(_RESPONSE_PAYLOAD_SIZE,
+                                     len(response.payload.body))
+
+                self.assertEqual(response_cnt, _NUM_STREAM_RESPONSES)
+                self.assertEqual(await call.code(), grpc.StatusCode.OK)
+                self.assertEqual(await call.initial_metadata(), ())
+                self.assertEqual(await call.trailing_metadata(), ())
+                self.assertEqual(await call.details(), '')
+                self.assertEqual(await call.debug_error_string(), '')
+                self.assertEqual(call.cancel(), False)
+                self.assertEqual(call.cancelled(), False)
+                self.assertEqual(call.done(), True)
+
+                interceptor.assert_in_final_state(self)
+
+                await channel.close()
+
+    async def test_intercepts_using_write_and_read(self):
+        for interceptor_class in (
+                _StreamStreamInterceptorEmpty,
+                _StreamStreamInterceptorWithRequestAndResponseIterator):
+
+            with self.subTest(name=interceptor_class):
+                interceptor = interceptor_class()
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=[interceptor])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                # Prepares the request
+                request = messages_pb2.StreamingOutputCallRequest()
+                request.response_parameters.append(
+                    messages_pb2.ResponseParameters(
+                        size=_RESPONSE_PAYLOAD_SIZE))
+
+                call = stub.FullDuplexCall()
+
+                for _ in range(_NUM_STREAM_RESPONSES):
+                    await call.write(request)
+                    response = await call.read()
+                    self.assertIsInstance(
+                        response, messages_pb2.StreamingOutputCallResponse)
+                    self.assertEqual(_RESPONSE_PAYLOAD_SIZE,
+                                     len(response.payload.body))
+
+                await call.done_writing()
+
+                self.assertEqual(await call.code(), grpc.StatusCode.OK)
+                self.assertEqual(await call.initial_metadata(), ())
+                self.assertEqual(await call.trailing_metadata(), ())
+                self.assertEqual(await call.details(), '')
+                self.assertEqual(await call.debug_error_string(), '')
+                self.assertEqual(call.cancel(), False)
+                self.assertEqual(call.cancelled(), False)
+                self.assertEqual(call.done(), True)
+
+                interceptor.assert_in_final_state(self)
+
+                await channel.close()
+
+    async def test_multiple_interceptors_request_iterator(self):
+        for interceptor_class in (
+                _StreamStreamInterceptorEmpty,
+                _StreamStreamInterceptorWithRequestAndResponseIterator):
+
+            with self.subTest(name=interceptor_class):
+
+                interceptors = [interceptor_class(), interceptor_class()]
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=interceptors)
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                # Prepares the request
+                request = messages_pb2.StreamingOutputCallRequest()
+                request.response_parameters.append(
+                    messages_pb2.ResponseParameters(
+                        size=_RESPONSE_PAYLOAD_SIZE))
+
+                call = stub.FullDuplexCall()
+
+                for _ in range(_NUM_STREAM_RESPONSES):
+                    await call.write(request)
+                    response = await call.read()
+                    self.assertIsInstance(
+                        response, messages_pb2.StreamingOutputCallResponse)
+                    self.assertEqual(_RESPONSE_PAYLOAD_SIZE,
+                                     len(response.payload.body))
+
+                await call.done_writing()
+
+                self.assertEqual(await call.code(), grpc.StatusCode.OK)
+                self.assertEqual(await call.initial_metadata(), ())
+                self.assertEqual(await call.trailing_metadata(), ())
+                self.assertEqual(await call.details(), '')
+                self.assertEqual(await call.debug_error_string(), '')
+                self.assertEqual(call.cancel(), False)
+                self.assertEqual(call.cancelled(), False)
+                self.assertEqual(call.done(), True)
+
+                for interceptor in interceptors:
+                    interceptor.assert_in_final_state(self)
+
+                await channel.close()
+
+
+if __name__ == '__main__':
+    logging.basicConfig(level=logging.DEBUG)
+    unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests_aio/unit/client_stream_unary_interceptor_test.py b/src/python/grpcio_tests/tests_aio/unit/client_stream_unary_interceptor_test.py
new file mode 100644 (file)
index 0000000..2d58cff
--- /dev/null
@@ -0,0 +1,517 @@
+# Copyright 2020 The gRPC Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import asyncio
+import logging
+import unittest
+import datetime
+
+import grpc
+
+from grpc.experimental import aio
+from tests_aio.unit._constants import UNREACHABLE_TARGET
+from tests_aio.unit._common import inject_callbacks
+from tests_aio.unit._common import CountingRequestIterator
+from tests_aio.unit._test_server import start_test_server
+from tests_aio.unit._test_base import AioTestBase
+from tests.unit.framework.common import test_constants
+from src.proto.grpc.testing import messages_pb2, test_pb2_grpc
+
+_SHORT_TIMEOUT_S = 1.0
+
+_NUM_STREAM_REQUESTS = 5
+_REQUEST_PAYLOAD_SIZE = 7
+_RESPONSE_INTERVAL_US = int(_SHORT_TIMEOUT_S * 1000 * 1000)
+
+
+class _StreamUnaryInterceptorEmpty(aio.StreamUnaryClientInterceptor):
+
+    async def intercept_stream_unary(self, continuation, client_call_details,
+                                     request_iterator):
+        return await continuation(client_call_details, request_iterator)
+
+    def assert_in_final_state(self, test: unittest.TestCase):
+        pass
+
+
+class _StreamUnaryInterceptorWithRequestIterator(
+        aio.StreamUnaryClientInterceptor):
+
+    async def intercept_stream_unary(self, continuation, client_call_details,
+                                     request_iterator):
+        self.request_iterator = CountingRequestIterator(request_iterator)
+        call = await continuation(client_call_details, self.request_iterator)
+        return call
+
+    def assert_in_final_state(self, test: unittest.TestCase):
+        test.assertEqual(_NUM_STREAM_REQUESTS,
+                         self.request_iterator.request_cnt)
+
+
+class TestStreamUnaryClientInterceptor(AioTestBase):
+
+    async def setUp(self):
+        self._server_target, self._server = await start_test_server()
+
+    async def tearDown(self):
+        await self._server.stop(None)
+
+    async def test_intercepts(self):
+        for interceptor_class in (_StreamUnaryInterceptorEmpty,
+                                  _StreamUnaryInterceptorWithRequestIterator):
+
+            with self.subTest(name=interceptor_class):
+                interceptor = interceptor_class()
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=[interceptor])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                payload = messages_pb2.Payload(body=b'\0' *
+                                               _REQUEST_PAYLOAD_SIZE)
+                request = messages_pb2.StreamingInputCallRequest(
+                    payload=payload)
+
+                async def request_iterator():
+                    for _ in range(_NUM_STREAM_REQUESTS):
+                        yield request
+
+                call = stub.StreamingInputCall(request_iterator())
+
+                response = await call
+
+                self.assertEqual(_NUM_STREAM_REQUESTS * _REQUEST_PAYLOAD_SIZE,
+                                 response.aggregated_payload_size)
+                self.assertEqual(await call.code(), grpc.StatusCode.OK)
+                self.assertEqual(await call.initial_metadata(), ())
+                self.assertEqual(await call.trailing_metadata(), ())
+                self.assertEqual(await call.details(), '')
+                self.assertEqual(await call.debug_error_string(), '')
+                self.assertEqual(call.cancel(), False)
+                self.assertEqual(call.cancelled(), False)
+                self.assertEqual(call.done(), True)
+
+                interceptor.assert_in_final_state(self)
+
+                await channel.close()
+
+    async def test_intercepts_using_write(self):
+        for interceptor_class in (_StreamUnaryInterceptorEmpty,
+                                  _StreamUnaryInterceptorWithRequestIterator):
+
+            with self.subTest(name=interceptor_class):
+                interceptor = interceptor_class()
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=[interceptor])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                payload = messages_pb2.Payload(body=b'\0' *
+                                               _REQUEST_PAYLOAD_SIZE)
+                request = messages_pb2.StreamingInputCallRequest(
+                    payload=payload)
+
+                call = stub.StreamingInputCall()
+
+                for _ in range(_NUM_STREAM_REQUESTS):
+                    await call.write(request)
+
+                await call.done_writing()
+
+                response = await call
+
+                self.assertEqual(_NUM_STREAM_REQUESTS * _REQUEST_PAYLOAD_SIZE,
+                                 response.aggregated_payload_size)
+                self.assertEqual(await call.code(), grpc.StatusCode.OK)
+                self.assertEqual(await call.initial_metadata(), ())
+                self.assertEqual(await call.trailing_metadata(), ())
+                self.assertEqual(await call.details(), '')
+                self.assertEqual(await call.debug_error_string(), '')
+                self.assertEqual(call.cancel(), False)
+                self.assertEqual(call.cancelled(), False)
+                self.assertEqual(call.done(), True)
+
+                interceptor.assert_in_final_state(self)
+
+                await channel.close()
+
+    async def test_add_done_callback_interceptor_task_not_finished(self):
+        for interceptor_class in (_StreamUnaryInterceptorEmpty,
+                                  _StreamUnaryInterceptorWithRequestIterator):
+
+            with self.subTest(name=interceptor_class):
+                interceptor = interceptor_class()
+
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=[interceptor])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                payload = messages_pb2.Payload(body=b'\0' *
+                                               _REQUEST_PAYLOAD_SIZE)
+                request = messages_pb2.StreamingInputCallRequest(
+                    payload=payload)
+
+                async def request_iterator():
+                    for _ in range(_NUM_STREAM_REQUESTS):
+                        yield request
+
+                call = stub.StreamingInputCall(request_iterator())
+
+                validation = inject_callbacks(call)
+
+                response = await call
+
+                await validation
+
+                await channel.close()
+
+    async def test_add_done_callback_interceptor_task_finished(self):
+        for interceptor_class in (_StreamUnaryInterceptorEmpty,
+                                  _StreamUnaryInterceptorWithRequestIterator):
+
+            with self.subTest(name=interceptor_class):
+                interceptor = interceptor_class()
+
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=[interceptor])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                payload = messages_pb2.Payload(body=b'\0' *
+                                               _REQUEST_PAYLOAD_SIZE)
+                request = messages_pb2.StreamingInputCallRequest(
+                    payload=payload)
+
+                async def request_iterator():
+                    for _ in range(_NUM_STREAM_REQUESTS):
+                        yield request
+
+                call = stub.StreamingInputCall(request_iterator())
+
+                response = await call
+
+                validation = inject_callbacks(call)
+
+                await validation
+
+                await channel.close()
+
+    async def test_multiple_interceptors_request_iterator(self):
+        for interceptor_class in (_StreamUnaryInterceptorEmpty,
+                                  _StreamUnaryInterceptorWithRequestIterator):
+
+            with self.subTest(name=interceptor_class):
+
+                interceptors = [interceptor_class(), interceptor_class()]
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=interceptors)
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                payload = messages_pb2.Payload(body=b'\0' *
+                                               _REQUEST_PAYLOAD_SIZE)
+                request = messages_pb2.StreamingInputCallRequest(
+                    payload=payload)
+
+                async def request_iterator():
+                    for _ in range(_NUM_STREAM_REQUESTS):
+                        yield request
+
+                call = stub.StreamingInputCall(request_iterator())
+
+                response = await call
+
+                self.assertEqual(_NUM_STREAM_REQUESTS * _REQUEST_PAYLOAD_SIZE,
+                                 response.aggregated_payload_size)
+                self.assertEqual(await call.code(), grpc.StatusCode.OK)
+                self.assertEqual(await call.initial_metadata(), ())
+                self.assertEqual(await call.trailing_metadata(), ())
+                self.assertEqual(await call.details(), '')
+                self.assertEqual(await call.debug_error_string(), '')
+                self.assertEqual(call.cancel(), False)
+                self.assertEqual(call.cancelled(), False)
+                self.assertEqual(call.done(), True)
+
+                for interceptor in interceptors:
+                    interceptor.assert_in_final_state(self)
+
+                await channel.close()
+
+    async def test_intercepts_request_iterator_rpc_error(self):
+        for interceptor_class in (_StreamUnaryInterceptorEmpty,
+                                  _StreamUnaryInterceptorWithRequestIterator):
+
+            with self.subTest(name=interceptor_class):
+                channel = aio.insecure_channel(
+                    UNREACHABLE_TARGET, interceptors=[interceptor_class()])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                payload = messages_pb2.Payload(body=b'\0' *
+                                               _REQUEST_PAYLOAD_SIZE)
+                request = messages_pb2.StreamingInputCallRequest(
+                    payload=payload)
+
+                # When there is an error the request iterator is no longer
+                # consumed.
+                async def request_iterator():
+                    for _ in range(_NUM_STREAM_REQUESTS):
+                        yield request
+
+                call = stub.StreamingInputCall(request_iterator())
+
+                with self.assertRaises(aio.AioRpcError) as exception_context:
+                    await call
+
+                self.assertEqual(grpc.StatusCode.UNAVAILABLE,
+                                 exception_context.exception.code())
+                self.assertTrue(call.done())
+                self.assertEqual(grpc.StatusCode.UNAVAILABLE, await call.code())
+
+                await channel.close()
+
+    async def test_intercepts_request_iterator_rpc_error_using_write(self):
+        for interceptor_class in (_StreamUnaryInterceptorEmpty,
+                                  _StreamUnaryInterceptorWithRequestIterator):
+
+            with self.subTest(name=interceptor_class):
+                channel = aio.insecure_channel(
+                    UNREACHABLE_TARGET, interceptors=[interceptor_class()])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                payload = messages_pb2.Payload(body=b'\0' *
+                                               _REQUEST_PAYLOAD_SIZE)
+                request = messages_pb2.StreamingInputCallRequest(
+                    payload=payload)
+
+                call = stub.StreamingInputCall()
+
+                # When there is an error during the write, exception is raised.
+                with self.assertRaises(asyncio.InvalidStateError):
+                    for _ in range(_NUM_STREAM_REQUESTS):
+                        await call.write(request)
+
+                with self.assertRaises(aio.AioRpcError) as exception_context:
+                    await call
+
+                self.assertEqual(grpc.StatusCode.UNAVAILABLE,
+                                 exception_context.exception.code())
+                self.assertTrue(call.done())
+                self.assertEqual(grpc.StatusCode.UNAVAILABLE, await call.code())
+
+                await channel.close()
+
+    async def test_cancel_before_rpc(self):
+
+        interceptor_reached = asyncio.Event()
+        wait_for_ever = self.loop.create_future()
+
+        class Interceptor(aio.StreamUnaryClientInterceptor):
+
+            async def intercept_stream_unary(self, continuation,
+                                             client_call_details,
+                                             request_iterator):
+                interceptor_reached.set()
+                await wait_for_ever
+
+        channel = aio.insecure_channel(self._server_target,
+                                       interceptors=[Interceptor()])
+        stub = test_pb2_grpc.TestServiceStub(channel)
+
+        payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
+        request = messages_pb2.StreamingInputCallRequest(payload=payload)
+
+        call = stub.StreamingInputCall()
+
+        self.assertFalse(call.cancelled())
+        self.assertFalse(call.done())
+
+        await interceptor_reached.wait()
+        self.assertTrue(call.cancel())
+
+        # When there is an error during the write, exception is raised.
+        with self.assertRaises(asyncio.InvalidStateError):
+            for _ in range(_NUM_STREAM_REQUESTS):
+                await call.write(request)
+
+        with self.assertRaises(asyncio.CancelledError):
+            await call
+
+        self.assertTrue(call.cancelled())
+        self.assertTrue(call.done())
+        self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
+        self.assertEqual(await call.initial_metadata(), None)
+        self.assertEqual(await call.trailing_metadata(), None)
+        await channel.close()
+
+    async def test_cancel_after_rpc(self):
+
+        interceptor_reached = asyncio.Event()
+        wait_for_ever = self.loop.create_future()
+
+        class Interceptor(aio.StreamUnaryClientInterceptor):
+
+            async def intercept_stream_unary(self, continuation,
+                                             client_call_details,
+                                             request_iterator):
+                call = await continuation(client_call_details, request_iterator)
+                interceptor_reached.set()
+                await wait_for_ever
+
+        channel = aio.insecure_channel(self._server_target,
+                                       interceptors=[Interceptor()])
+        stub = test_pb2_grpc.TestServiceStub(channel)
+
+        payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
+        request = messages_pb2.StreamingInputCallRequest(payload=payload)
+
+        call = stub.StreamingInputCall()
+
+        self.assertFalse(call.cancelled())
+        self.assertFalse(call.done())
+
+        await interceptor_reached.wait()
+        self.assertTrue(call.cancel())
+
+        # When there is an error during the write, exception is raised.
+        with self.assertRaises(asyncio.InvalidStateError):
+            for _ in range(_NUM_STREAM_REQUESTS):
+                await call.write(request)
+
+        with self.assertRaises(asyncio.CancelledError):
+            await call
+
+        self.assertTrue(call.cancelled())
+        self.assertTrue(call.done())
+        self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
+        self.assertEqual(await call.initial_metadata(), None)
+        self.assertEqual(await call.trailing_metadata(), None)
+        await channel.close()
+
+    async def test_cancel_while_writing(self):
+        # Test cancelation before making any write or after doing at least 1
+        for num_writes_before_cancel in (0, 1):
+            with self.subTest(name="Num writes before cancel: {}".format(
+                    num_writes_before_cancel)):
+
+                channel = aio.insecure_channel(
+                    UNREACHABLE_TARGET,
+                    interceptors=[_StreamUnaryInterceptorWithRequestIterator()])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                payload = messages_pb2.Payload(body=b'\0' *
+                                               _REQUEST_PAYLOAD_SIZE)
+                request = messages_pb2.StreamingInputCallRequest(
+                    payload=payload)
+
+                call = stub.StreamingInputCall()
+
+                with self.assertRaises(asyncio.InvalidStateError):
+                    for i in range(_NUM_STREAM_REQUESTS):
+                        if i == num_writes_before_cancel:
+                            self.assertTrue(call.cancel())
+                        await call.write(request)
+
+                with self.assertRaises(asyncio.CancelledError):
+                    await call
+
+                self.assertTrue(call.cancelled())
+                self.assertTrue(call.done())
+                self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
+
+                await channel.close()
+
+    async def test_cancel_by_the_interceptor(self):
+
+        class Interceptor(aio.StreamUnaryClientInterceptor):
+
+            async def intercept_stream_unary(self, continuation,
+                                             client_call_details,
+                                             request_iterator):
+                call = await continuation(client_call_details, request_iterator)
+                call.cancel()
+                return call
+
+        channel = aio.insecure_channel(UNREACHABLE_TARGET,
+                                       interceptors=[Interceptor()])
+        stub = test_pb2_grpc.TestServiceStub(channel)
+
+        payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
+        request = messages_pb2.StreamingInputCallRequest(payload=payload)
+
+        call = stub.StreamingInputCall()
+
+        with self.assertRaises(asyncio.InvalidStateError):
+            for i in range(_NUM_STREAM_REQUESTS):
+                await call.write(request)
+
+        with self.assertRaises(asyncio.CancelledError):
+            await call
+
+        self.assertTrue(call.cancelled())
+        self.assertTrue(call.done())
+        self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
+
+        await channel.close()
+
+    async def test_exception_raised_by_interceptor(self):
+
+        class InterceptorException(Exception):
+            pass
+
+        class Interceptor(aio.StreamUnaryClientInterceptor):
+
+            async def intercept_stream_unary(self, continuation,
+                                             client_call_details,
+                                             request_iterator):
+                raise InterceptorException
+
+        channel = aio.insecure_channel(UNREACHABLE_TARGET,
+                                       interceptors=[Interceptor()])
+        stub = test_pb2_grpc.TestServiceStub(channel)
+
+        payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
+        request = messages_pb2.StreamingInputCallRequest(payload=payload)
+
+        call = stub.StreamingInputCall()
+
+        with self.assertRaises(InterceptorException):
+            for i in range(_NUM_STREAM_REQUESTS):
+                await call.write(request)
+
+        with self.assertRaises(InterceptorException):
+            await call
+
+        await channel.close()
+
+    async def test_intercepts_prohibit_mixing_style(self):
+        channel = aio.insecure_channel(
+            self._server_target, interceptors=[_StreamUnaryInterceptorEmpty()])
+        stub = test_pb2_grpc.TestServiceStub(channel)
+
+        payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
+        request = messages_pb2.StreamingInputCallRequest(payload=payload)
+
+        async def request_iterator():
+            for _ in range(_NUM_STREAM_REQUESTS):
+                yield request
+
+        call = stub.StreamingInputCall(request_iterator())
+
+        with self.assertRaises(grpc._cython.cygrpc.UsageError):
+            await call.write(request)
+
+        with self.assertRaises(grpc._cython.cygrpc.UsageError):
+            await call.done_writing()
+
+        await channel.close()
+
+
+if __name__ == '__main__':
+    logging.basicConfig(level=logging.DEBUG)
+    unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests_aio/unit/client_unary_stream_interceptor_test.py b/src/python/grpcio_tests/tests_aio/unit/client_unary_stream_interceptor_test.py
new file mode 100644 (file)
index 0000000..6137538
--- /dev/null
@@ -0,0 +1,395 @@
+# Copyright 2020 The gRPC Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import asyncio
+import logging
+import unittest
+import datetime
+
+import grpc
+
+from grpc.experimental import aio
+from tests_aio.unit._constants import UNREACHABLE_TARGET
+from tests_aio.unit._common import inject_callbacks
+from tests_aio.unit._common import CountingResponseIterator
+from tests_aio.unit._test_server import start_test_server
+from tests_aio.unit._test_base import AioTestBase
+from tests.unit.framework.common import test_constants
+from src.proto.grpc.testing import messages_pb2, test_pb2_grpc
+
+_SHORT_TIMEOUT_S = 1.0
+
+_NUM_STREAM_RESPONSES = 5
+_REQUEST_PAYLOAD_SIZE = 7
+_RESPONSE_PAYLOAD_SIZE = 7
+_RESPONSE_INTERVAL_US = int(_SHORT_TIMEOUT_S * 1000 * 1000)
+
+
+class _UnaryStreamInterceptorEmpty(aio.UnaryStreamClientInterceptor):
+
+    async def intercept_unary_stream(self, continuation, client_call_details,
+                                     request):
+        return await continuation(client_call_details, request)
+
+    def assert_in_final_state(self, test: unittest.TestCase):
+        pass
+
+
+class _UnaryStreamInterceptorWithResponseIterator(
+        aio.UnaryStreamClientInterceptor):
+
+    async def intercept_unary_stream(self, continuation, client_call_details,
+                                     request):
+        call = await continuation(client_call_details, request)
+        self.response_iterator = CountingResponseIterator(call)
+        return self.response_iterator
+
+    def assert_in_final_state(self, test: unittest.TestCase):
+        test.assertEqual(_NUM_STREAM_RESPONSES,
+                         self.response_iterator.response_cnt)
+
+
+class TestUnaryStreamClientInterceptor(AioTestBase):
+
+    async def setUp(self):
+        self._server_target, self._server = await start_test_server()
+
+    async def tearDown(self):
+        await self._server.stop(None)
+
+    async def test_intercepts(self):
+        for interceptor_class in (_UnaryStreamInterceptorEmpty,
+                                  _UnaryStreamInterceptorWithResponseIterator):
+
+            with self.subTest(name=interceptor_class):
+                interceptor = interceptor_class()
+
+                request = messages_pb2.StreamingOutputCallRequest()
+                request.response_parameters.extend([
+                    messages_pb2.ResponseParameters(size=_RESPONSE_PAYLOAD_SIZE)
+                ] * _NUM_STREAM_RESPONSES)
+
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=[interceptor])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+                call = stub.StreamingOutputCall(request)
+
+                await call.wait_for_connection()
+
+                response_cnt = 0
+                async for response in call:
+                    response_cnt += 1
+                    self.assertIs(type(response),
+                                  messages_pb2.StreamingOutputCallResponse)
+                    self.assertEqual(_RESPONSE_PAYLOAD_SIZE,
+                                     len(response.payload.body))
+
+                self.assertEqual(response_cnt, _NUM_STREAM_RESPONSES)
+                self.assertEqual(await call.code(), grpc.StatusCode.OK)
+                self.assertEqual(await call.initial_metadata(), ())
+                self.assertEqual(await call.trailing_metadata(), ())
+                self.assertEqual(await call.details(), '')
+                self.assertEqual(await call.debug_error_string(), '')
+                self.assertEqual(call.cancel(), False)
+                self.assertEqual(call.cancelled(), False)
+                self.assertEqual(call.done(), True)
+
+                interceptor.assert_in_final_state(self)
+
+                await channel.close()
+
+    async def test_add_done_callback_interceptor_task_not_finished(self):
+        for interceptor_class in (_UnaryStreamInterceptorEmpty,
+                                  _UnaryStreamInterceptorWithResponseIterator):
+
+            with self.subTest(name=interceptor_class):
+                interceptor = interceptor_class()
+
+                request = messages_pb2.StreamingOutputCallRequest()
+                request.response_parameters.extend([
+                    messages_pb2.ResponseParameters(size=_RESPONSE_PAYLOAD_SIZE)
+                ] * _NUM_STREAM_RESPONSES)
+
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=[interceptor])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+                call = stub.StreamingOutputCall(request)
+
+                validation = inject_callbacks(call)
+
+                async for response in call:
+                    pass
+
+                await validation
+
+                await channel.close()
+
+    async def test_add_done_callback_interceptor_task_finished(self):
+        for interceptor_class in (_UnaryStreamInterceptorEmpty,
+                                  _UnaryStreamInterceptorWithResponseIterator):
+
+            with self.subTest(name=interceptor_class):
+                interceptor = interceptor_class()
+
+                request = messages_pb2.StreamingOutputCallRequest()
+                request.response_parameters.extend([
+                    messages_pb2.ResponseParameters(size=_RESPONSE_PAYLOAD_SIZE)
+                ] * _NUM_STREAM_RESPONSES)
+
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=[interceptor])
+                stub = test_pb2_grpc.TestServiceStub(channel)
+                call = stub.StreamingOutputCall(request)
+
+                # This ensures that the callbacks will be registered
+                # with the intercepted call rather than saving in the
+                # pending state list.
+                await call.wait_for_connection()
+
+                validation = inject_callbacks(call)
+
+                async for response in call:
+                    pass
+
+                await validation
+
+                await channel.close()
+
+    async def test_response_iterator_using_read(self):
+        interceptor = _UnaryStreamInterceptorWithResponseIterator()
+
+        channel = aio.insecure_channel(self._server_target,
+                                       interceptors=[interceptor])
+        stub = test_pb2_grpc.TestServiceStub(channel)
+
+        request = messages_pb2.StreamingOutputCallRequest()
+        request.response_parameters.extend(
+            [messages_pb2.ResponseParameters(size=_RESPONSE_PAYLOAD_SIZE)] *
+            _NUM_STREAM_RESPONSES)
+
+        call = stub.StreamingOutputCall(request)
+
+        response_cnt = 0
+        for response in range(_NUM_STREAM_RESPONSES):
+            response = await call.read()
+            response_cnt += 1
+            self.assertIs(type(response),
+                          messages_pb2.StreamingOutputCallResponse)
+            self.assertEqual(_RESPONSE_PAYLOAD_SIZE, len(response.payload.body))
+
+        self.assertEqual(response_cnt, _NUM_STREAM_RESPONSES)
+        self.assertEqual(interceptor.response_iterator.response_cnt,
+                         _NUM_STREAM_RESPONSES)
+        self.assertEqual(await call.code(), grpc.StatusCode.OK)
+
+        await channel.close()
+
+    async def test_multiple_interceptors_response_iterator(self):
+        for interceptor_class in (_UnaryStreamInterceptorEmpty,
+                                  _UnaryStreamInterceptorWithResponseIterator):
+
+            with self.subTest(name=interceptor_class):
+
+                interceptors = [interceptor_class(), interceptor_class()]
+
+                channel = aio.insecure_channel(self._server_target,
+                                               interceptors=interceptors)
+                stub = test_pb2_grpc.TestServiceStub(channel)
+
+                request = messages_pb2.StreamingOutputCallRequest()
+                request.response_parameters.extend([
+                    messages_pb2.ResponseParameters(size=_RESPONSE_PAYLOAD_SIZE)
+                ] * _NUM_STREAM_RESPONSES)
+
+                call = stub.StreamingOutputCall(request)
+
+                response_cnt = 0
+                async for response in call:
+                    response_cnt += 1
+                    self.assertIs(type(response),
+                                  messages_pb2.StreamingOutputCallResponse)
+                    self.assertEqual(_RESPONSE_PAYLOAD_SIZE,
+                                     len(response.payload.body))
+
+                self.assertEqual(response_cnt, _NUM_STREAM_RESPONSES)
+                self.assertEqual(await call.code(), grpc.StatusCode.OK)
+
+                await channel.close()
+
+    async def test_intercepts_response_iterator_rpc_error(self):
+        for interceptor_class in (_UnaryStreamInterceptorEmpty,
+                                  _UnaryStreamInterceptorWithResponseIterator):
+
+            with self.subTest(name=interceptor_class):
+
+                channel = aio.insecure_channel(
+                    UNREACHABLE_TARGET, interceptors=[interceptor_class()])
+                request = messages_pb2.StreamingOutputCallRequest()
+                stub = test_pb2_grpc.TestServiceStub(channel)
+                call = stub.StreamingOutputCall(request)
+
+                with self.assertRaises(aio.AioRpcError) as exception_context:
+                    async for response in call:
+                        pass
+
+                self.assertEqual(grpc.StatusCode.UNAVAILABLE,
+                                 exception_context.exception.code())
+
+                self.assertTrue(call.done())
+                self.assertEqual(grpc.StatusCode.UNAVAILABLE, await call.code())
+                await channel.close()
+
+    async def test_cancel_before_rpc(self):
+
+        interceptor_reached = asyncio.Event()
+        wait_for_ever = self.loop.create_future()
+
+        class Interceptor(aio.UnaryStreamClientInterceptor):
+
+            async def intercept_unary_stream(self, continuation,
+                                             client_call_details, request):
+                interceptor_reached.set()
+                await wait_for_ever
+
+        channel = aio.insecure_channel(UNREACHABLE_TARGET,
+                                       interceptors=[Interceptor()])
+        request = messages_pb2.StreamingOutputCallRequest()
+        stub = test_pb2_grpc.TestServiceStub(channel)
+        call = stub.StreamingOutputCall(request)
+
+        self.assertFalse(call.cancelled())
+        self.assertFalse(call.done())
+
+        await interceptor_reached.wait()
+        self.assertTrue(call.cancel())
+
+        with self.assertRaises(asyncio.CancelledError):
+            async for response in call:
+                pass
+
+        self.assertTrue(call.cancelled())
+        self.assertTrue(call.done())
+        self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
+        self.assertEqual(await call.initial_metadata(), None)
+        self.assertEqual(await call.trailing_metadata(), None)
+        await channel.close()
+
+    async def test_cancel_after_rpc(self):
+
+        interceptor_reached = asyncio.Event()
+        wait_for_ever = self.loop.create_future()
+
+        class Interceptor(aio.UnaryStreamClientInterceptor):
+
+            async def intercept_unary_stream(self, continuation,
+                                             client_call_details, request):
+                call = await continuation(client_call_details, request)
+                interceptor_reached.set()
+                await wait_for_ever
+
+        channel = aio.insecure_channel(UNREACHABLE_TARGET,
+                                       interceptors=[Interceptor()])
+        request = messages_pb2.StreamingOutputCallRequest()
+        stub = test_pb2_grpc.TestServiceStub(channel)
+        call = stub.StreamingOutputCall(request)
+
+        self.assertFalse(call.cancelled())
+        self.assertFalse(call.done())
+
+        await interceptor_reached.wait()
+        self.assertTrue(call.cancel())
+
+        with self.assertRaises(asyncio.CancelledError):
+            async for response in call:
+                pass
+
+        self.assertTrue(call.cancelled())
+        self.assertTrue(call.done())
+        self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
+        self.assertEqual(await call.initial_metadata(), None)
+        self.assertEqual(await call.trailing_metadata(), None)
+        await channel.close()
+
+    async def test_cancel_consuming_response_iterator(self):
+        request = messages_pb2.StreamingOutputCallRequest()
+        request.response_parameters.extend(
+            [messages_pb2.ResponseParameters(size=_RESPONSE_PAYLOAD_SIZE)] *
+            _NUM_STREAM_RESPONSES)
+
+        channel = aio.insecure_channel(
+            self._server_target,
+            interceptors=[_UnaryStreamInterceptorWithResponseIterator()])
+        stub = test_pb2_grpc.TestServiceStub(channel)
+        call = stub.StreamingOutputCall(request)
+
+        with self.assertRaises(asyncio.CancelledError):
+            async for response in call:
+                call.cancel()
+
+        self.assertTrue(call.cancelled())
+        self.assertTrue(call.done())
+        self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
+        await channel.close()
+
+    async def test_cancel_by_the_interceptor(self):
+
+        class Interceptor(aio.UnaryStreamClientInterceptor):
+
+            async def intercept_unary_stream(self, continuation,
+                                             client_call_details, request):
+                call = await continuation(client_call_details, request)
+                call.cancel()
+                return call
+
+        channel = aio.insecure_channel(UNREACHABLE_TARGET,
+                                       interceptors=[Interceptor()])
+        request = messages_pb2.StreamingOutputCallRequest()
+        stub = test_pb2_grpc.TestServiceStub(channel)
+        call = stub.StreamingOutputCall(request)
+
+        with self.assertRaises(asyncio.CancelledError):
+            async for response in call:
+                pass
+
+        self.assertTrue(call.cancelled())
+        self.assertTrue(call.done())
+        self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
+        await channel.close()
+
+    async def test_exception_raised_by_interceptor(self):
+
+        class InterceptorException(Exception):
+            pass
+
+        class Interceptor(aio.UnaryStreamClientInterceptor):
+
+            async def intercept_unary_stream(self, continuation,
+                                             client_call_details, request):
+                raise InterceptorException
+
+        channel = aio.insecure_channel(UNREACHABLE_TARGET,
+                                       interceptors=[Interceptor()])
+        request = messages_pb2.StreamingOutputCallRequest()
+        stub = test_pb2_grpc.TestServiceStub(channel)
+        call = stub.StreamingOutputCall(request)
+
+        with self.assertRaises(InterceptorException):
+            async for response in call:
+                pass
+
+        await channel.close()
+
+
+if __name__ == '__main__':
+    logging.basicConfig(level=logging.DEBUG)
+    unittest.main(verbosity=2)
index e3d85e7..1e6e359 100644 (file)
@@ -20,32 +20,63 @@ import random
 import threading
 import unittest
 from concurrent.futures import ThreadPoolExecutor
-from typing import Callable, Sequence, Tuple
+from typing import Callable, Iterable, Sequence, Tuple
 
 import grpc
 from grpc.experimental import aio
 
 from src.proto.grpc.testing import messages_pb2, test_pb2_grpc
 from tests.unit.framework.common import test_constants
+from tests_aio.unit import _common
 from tests_aio.unit._test_base import AioTestBase
-from tests_aio.unit._test_server import start_test_server
+from tests_aio.unit._test_server import TestServiceServicer, start_test_server
 
 _NUM_STREAM_RESPONSES = 5
 _REQUEST_PAYLOAD_SIZE = 7
 _RESPONSE_PAYLOAD_SIZE = 42
+_REQUEST = b'\x03\x07'
+_ADHOC_METHOD = '/test/AdHoc'
 
 
 def _unique_options() -> Sequence[Tuple[str, float]]:
     return (('iv', random.random()),)
 
 
+class _AdhocGenericHandler(grpc.GenericRpcHandler):
+    _handler: grpc.RpcMethodHandler
+
+    def __init__(self):
+        self._handler = None
+
+    def set_adhoc_handler(self, handler: grpc.RpcMethodHandler):
+        self._handler = handler
+
+    def service(self, handler_call_details):
+        if handler_call_details.method == _ADHOC_METHOD:
+            return self._handler
+        else:
+            return None
+
+
 @unittest.skipIf(
-    os.environ.get('GRPC_ASYNCIO_ENGINE', '').lower() != 'poller',
+    os.environ.get('GRPC_ASYNCIO_ENGINE', '').lower() == 'custom_io_manager',
     'Compatible mode needs POLLER completion queue.')
 class TestCompatibility(AioTestBase):
 
     async def setUp(self):
-        address, self._async_server = await start_test_server()
+        self._async_server = aio.server(
+            options=(('grpc.so_reuseport', 0),),
+            migration_thread_pool=ThreadPoolExecutor())
+
+        test_pb2_grpc.add_TestServiceServicer_to_server(TestServiceServicer(),
+                                                        self._async_server)
+        self._adhoc_handlers = _AdhocGenericHandler()
+        self._async_server.add_generic_rpc_handlers((self._adhoc_handlers,))
+
+        port = self._async_server.add_insecure_port('[::]:0')
+        address = 'localhost:%d' % port
+        await self._async_server.start()
+
         # Create async stub
         self._async_channel = aio.insecure_channel(address,
                                                    options=_unique_options())
@@ -202,6 +233,146 @@ class TestCompatibility(AioTestBase):
         await self._run_in_another_thread(sync_work)
         await server.stop(None)
 
+    async def test_sync_unary_unary_success(self):
+
+        @grpc.unary_unary_rpc_method_handler
+        def echo_unary_unary(request: bytes, unused_context):
+            return request
+
+        self._adhoc_handlers.set_adhoc_handler(echo_unary_unary)
+        response = await self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST
+                                                                       )
+        self.assertEqual(_REQUEST, response)
+
+    async def test_sync_unary_unary_metadata(self):
+        metadata = (('unique', 'key-42'),)
+
+        @grpc.unary_unary_rpc_method_handler
+        def metadata_unary_unary(request: bytes, context: grpc.ServicerContext):
+            context.send_initial_metadata(metadata)
+            return request
+
+        self._adhoc_handlers.set_adhoc_handler(metadata_unary_unary)
+        call = self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST)
+        self.assertTrue(
+            _common.seen_metadata(metadata, await call.initial_metadata()))
+
+    async def test_sync_unary_unary_abort(self):
+
+        @grpc.unary_unary_rpc_method_handler
+        def abort_unary_unary(request: bytes, context: grpc.ServicerContext):
+            context.abort(grpc.StatusCode.INTERNAL, 'Test')
+
+        self._adhoc_handlers.set_adhoc_handler(abort_unary_unary)
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST)
+        self.assertEqual(grpc.StatusCode.INTERNAL,
+                         exception_context.exception.code())
+
+    async def test_sync_unary_unary_set_code(self):
+
+        @grpc.unary_unary_rpc_method_handler
+        def set_code_unary_unary(request: bytes, context: grpc.ServicerContext):
+            context.set_code(grpc.StatusCode.INTERNAL)
+
+        self._adhoc_handlers.set_adhoc_handler(set_code_unary_unary)
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            await self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST)
+        self.assertEqual(grpc.StatusCode.INTERNAL,
+                         exception_context.exception.code())
+
+    async def test_sync_unary_stream_success(self):
+
+        @grpc.unary_stream_rpc_method_handler
+        def echo_unary_stream(request: bytes, unused_context):
+            for _ in range(_NUM_STREAM_RESPONSES):
+                yield request
+
+        self._adhoc_handlers.set_adhoc_handler(echo_unary_stream)
+        call = self._async_channel.unary_stream(_ADHOC_METHOD)(_REQUEST)
+        async for response in call:
+            self.assertEqual(_REQUEST, response)
+
+    async def test_sync_unary_stream_error(self):
+
+        @grpc.unary_stream_rpc_method_handler
+        def error_unary_stream(request: bytes, unused_context):
+            for _ in range(_NUM_STREAM_RESPONSES):
+                yield request
+            raise RuntimeError('Test')
+
+        self._adhoc_handlers.set_adhoc_handler(error_unary_stream)
+        call = self._async_channel.unary_stream(_ADHOC_METHOD)(_REQUEST)
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            async for response in call:
+                self.assertEqual(_REQUEST, response)
+        self.assertEqual(grpc.StatusCode.UNKNOWN,
+                         exception_context.exception.code())
+
+    async def test_sync_stream_unary_success(self):
+
+        @grpc.stream_unary_rpc_method_handler
+        def echo_stream_unary(request_iterator: Iterable[bytes],
+                              unused_context):
+            self.assertEqual(len(list(request_iterator)), _NUM_STREAM_RESPONSES)
+            return _REQUEST
+
+        self._adhoc_handlers.set_adhoc_handler(echo_stream_unary)
+        request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES)
+        response = await self._async_channel.stream_unary(_ADHOC_METHOD)(
+            request_iterator)
+        self.assertEqual(_REQUEST, response)
+
+    async def test_sync_stream_unary_error(self):
+
+        @grpc.stream_unary_rpc_method_handler
+        def echo_stream_unary(request_iterator: Iterable[bytes],
+                              unused_context):
+            self.assertEqual(len(list(request_iterator)), _NUM_STREAM_RESPONSES)
+            raise RuntimeError('Test')
+
+        self._adhoc_handlers.set_adhoc_handler(echo_stream_unary)
+        request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES)
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            response = await self._async_channel.stream_unary(_ADHOC_METHOD)(
+                request_iterator)
+        self.assertEqual(grpc.StatusCode.UNKNOWN,
+                         exception_context.exception.code())
+
+    async def test_sync_stream_stream_success(self):
+
+        @grpc.stream_stream_rpc_method_handler
+        def echo_stream_stream(request_iterator: Iterable[bytes],
+                               unused_context):
+            for request in request_iterator:
+                yield request
+
+        self._adhoc_handlers.set_adhoc_handler(echo_stream_stream)
+        request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES)
+        call = self._async_channel.stream_stream(_ADHOC_METHOD)(
+            request_iterator)
+        async for response in call:
+            self.assertEqual(_REQUEST, response)
+
+    async def test_sync_stream_stream_error(self):
+
+        @grpc.stream_stream_rpc_method_handler
+        def echo_stream_stream(request_iterator: Iterable[bytes],
+                               unused_context):
+            for request in request_iterator:
+                yield request
+            raise RuntimeError('test')
+
+        self._adhoc_handlers.set_adhoc_handler(echo_stream_stream)
+        request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES)
+        call = self._async_channel.stream_stream(_ADHOC_METHOD)(
+            request_iterator)
+        with self.assertRaises(aio.AioRpcError) as exception_context:
+            async for response in call:
+                self.assertEqual(_REQUEST, response)
+        self.assertEqual(grpc.StatusCode.UNKNOWN,
+                         exception_context.exception.code())
+
 
 if __name__ == '__main__':
     logging.basicConfig(level=logging.DEBUG)
index a312e45..481bafd 100644 (file)
@@ -21,6 +21,7 @@ import gc
 
 import grpc
 from grpc.experimental import aio
+from tests_aio.unit._common import inject_callbacks
 from tests_aio.unit._test_base import AioTestBase
 from tests.unit.framework.common import test_constants
 from src.proto.grpc.testing import messages_pb2, test_pb2_grpc
@@ -31,29 +32,6 @@ _REQUEST_PAYLOAD_SIZE = 7
 _RESPONSE_PAYLOAD_SIZE = 42
 
 
-def _inject_callbacks(call):
-    first_callback_ran = asyncio.Event()
-
-    def first_callback(unused_call):
-        first_callback_ran.set()
-
-    second_callback_ran = asyncio.Event()
-
-    def second_callback(unused_call):
-        second_callback_ran.set()
-
-    call.add_done_callback(first_callback)
-    call.add_done_callback(second_callback)
-
-    async def validation():
-        await asyncio.wait_for(
-            asyncio.gather(first_callback_ran.wait(),
-                           second_callback_ran.wait()),
-            test_constants.SHORT_TIMEOUT)
-
-    return validation()
-
-
 class TestDoneCallback(AioTestBase):
 
     async def setUp(self):
@@ -69,12 +47,12 @@ class TestDoneCallback(AioTestBase):
         call = self._stub.UnaryCall(messages_pb2.SimpleRequest())
         self.assertEqual(grpc.StatusCode.OK, await call.code())
 
-        validation = _inject_callbacks(call)
+        validation = inject_callbacks(call)
         await validation
 
     async def test_unary_unary(self):
         call = self._stub.UnaryCall(messages_pb2.SimpleRequest())
-        validation = _inject_callbacks(call)
+        validation = inject_callbacks(call)
 
         self.assertEqual(grpc.StatusCode.OK, await call.code())
 
@@ -87,7 +65,7 @@ class TestDoneCallback(AioTestBase):
                 messages_pb2.ResponseParameters(size=_RESPONSE_PAYLOAD_SIZE))
 
         call = self._stub.StreamingOutputCall(request)
-        validation = _inject_callbacks(call)
+        validation = inject_callbacks(call)
 
         response_cnt = 0
         async for response in call:
@@ -110,7 +88,7 @@ class TestDoneCallback(AioTestBase):
                 yield request
 
         call = self._stub.StreamingInputCall(gen())
-        validation = _inject_callbacks(call)
+        validation = inject_callbacks(call)
 
         response = await call
         self.assertIsInstance(response, messages_pb2.StreamingInputCallResponse)
@@ -122,7 +100,7 @@ class TestDoneCallback(AioTestBase):
 
     async def test_stream_stream(self):
         call = self._stub.FullDuplexCall()
-        validation = _inject_callbacks(call)
+        validation = inject_callbacks(call)
 
         request = messages_pb2.StreamingOutputCallRequest()
         request.response_parameters.append(
index dabf005..f85e46c 100644 (file)
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+"""Test the functionality of server interceptors."""
+
+import asyncio
+import functools
 import logging
 import unittest
-from typing import Callable, Awaitable, Any
+from typing import Any, Awaitable, Callable, Tuple
 
 import grpc
+from grpc.experimental import aio, wrap_server_method_handler
 
-from grpc.experimental import aio
-
-from tests_aio.unit._test_server import start_test_server
+from src.proto.grpc.testing import messages_pb2, test_pb2_grpc
 from tests_aio.unit._test_base import AioTestBase
-from src.proto.grpc.testing import messages_pb2
+from tests_aio.unit._test_server import start_test_server
+
+_NUM_STREAM_RESPONSES = 5
+_REQUEST_PAYLOAD_SIZE = 7
+_RESPONSE_PAYLOAD_SIZE = 42
 
 
 class _LoggingInterceptor(aio.ServerInterceptor):
@@ -73,6 +80,55 @@ def _filter_server_interceptor(condition: Callable,
     return _GenericInterceptor(intercept_service)
 
 
+class _CacheInterceptor(aio.ServerInterceptor):
+    """An interceptor that caches response based on request message."""
+
+    def __init__(self, cache_store=None):
+        self.cache_store = cache_store or {}
+
+    async def intercept_service(
+            self, continuation: Callable[[grpc.HandlerCallDetails], Awaitable[
+                grpc.RpcMethodHandler]],
+            handler_call_details: grpc.HandlerCallDetails
+    ) -> grpc.RpcMethodHandler:
+        # Get the actual handler
+        handler = await continuation(handler_call_details)
+
+        # Only intercept unary call RPCs
+        if handler and (handler.request_streaming or  # pytype: disable=attribute-error
+                        handler.response_streaming):  # pytype: disable=attribute-error
+            return handler
+
+        def wrapper(behavior: Callable[
+            [messages_pb2.SimpleRequest, aio.
+             ServicerContext], messages_pb2.SimpleResponse]):
+
+            @functools.wraps(behavior)
+            async def wrapper(request: messages_pb2.SimpleRequest,
+                              context: aio.ServicerContext
+                             ) -> messages_pb2.SimpleResponse:
+                if request.response_size not in self.cache_store:
+                    self.cache_store[request.response_size] = await behavior(
+                        request, context)
+                return self.cache_store[request.response_size]
+
+            return wrapper
+
+        return wrap_server_method_handler(wrapper, handler)
+
+
+async def _create_server_stub_pair(
+        *interceptors: aio.ServerInterceptor
+) -> Tuple[aio.Server, test_pb2_grpc.TestServiceStub]:
+    """Creates a server-stub pair with given interceptors.
+
+    Returning the server object to protect it from being garbage collected.
+    """
+    server_target, server = await start_test_server(interceptors=interceptors)
+    channel = aio.insecure_channel(server_target)
+    return server, test_pb2_grpc.TestServiceStub(channel)
+
+
 class TestServerInterceptor(AioTestBase):
 
     async def test_invalid_interceptor(self):
@@ -162,6 +218,112 @@ class TestServerInterceptor(AioTestBase):
                 'log2:intercept_service',
             ], record)
 
+    async def test_response_caching(self):
+        # Prepares a preset value to help testing
+        interceptor = _CacheInterceptor({
+            42:
+                messages_pb2.SimpleResponse(payload=messages_pb2.Payload(
+                    body=b'\x42'))
+        })
+
+        # Constructs a server with the cache interceptor
+        server, stub = await _create_server_stub_pair(interceptor)
+
+        # Tests if the cache store is used
+        response = await stub.UnaryCall(
+            messages_pb2.SimpleRequest(response_size=42))
+        self.assertEqual(1, len(interceptor.cache_store[42].payload.body))
+        self.assertEqual(interceptor.cache_store[42], response)
+
+        # Tests response can be cached
+        response = await stub.UnaryCall(
+            messages_pb2.SimpleRequest(response_size=1337))
+        self.assertEqual(1337, len(interceptor.cache_store[1337].payload.body))
+        self.assertEqual(interceptor.cache_store[1337], response)
+        response = await stub.UnaryCall(
+            messages_pb2.SimpleRequest(response_size=1337))
+        self.assertEqual(interceptor.cache_store[1337], response)
+
+    async def test_interceptor_unary_stream(self):
+        record = []
+        server, stub = await _create_server_stub_pair(
+            _LoggingInterceptor('log_unary_stream', record))
+
+        # Prepares the request
+        request = messages_pb2.StreamingOutputCallRequest()
+        for _ in range(_NUM_STREAM_RESPONSES):
+            request.response_parameters.append(
+                messages_pb2.ResponseParameters(size=_RESPONSE_PAYLOAD_SIZE,))
+
+        # Tests if the cache store is used
+        call = stub.StreamingOutputCall(request)
+
+        # Ensures the RPC goes fine
+        async for response in call:
+            self.assertEqual(_RESPONSE_PAYLOAD_SIZE, len(response.payload.body))
+        self.assertEqual(await call.code(), grpc.StatusCode.OK)
+
+        self.assertSequenceEqual([
+            'log_unary_stream:intercept_service',
+        ], record)
+
+    async def test_interceptor_stream_unary(self):
+        record = []
+        server, stub = await _create_server_stub_pair(
+            _LoggingInterceptor('log_stream_unary', record))
+
+        # Invokes the actual RPC
+        call = stub.StreamingInputCall()
+
+        # Prepares the request
+        payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
+        request = messages_pb2.StreamingInputCallRequest(payload=payload)
+
+        # Sends out requests
+        for _ in range(_NUM_STREAM_RESPONSES):
+            await call.write(request)
+        await call.done_writing()
+
+        # Validates the responses
+        response = await call
+        self.assertIsInstance(response, messages_pb2.StreamingInputCallResponse)
+        self.assertEqual(_NUM_STREAM_RESPONSES * _REQUEST_PAYLOAD_SIZE,
+                         response.aggregated_payload_size)
+
+        self.assertEqual(await call.code(), grpc.StatusCode.OK)
+
+        self.assertSequenceEqual([
+            'log_stream_unary:intercept_service',
+        ], record)
+
+    async def test_interceptor_stream_stream(self):
+        record = []
+        server, stub = await _create_server_stub_pair(
+            _LoggingInterceptor('log_stream_stream', record))
+
+        # Prepares the request
+        payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
+        request = messages_pb2.StreamingInputCallRequest(payload=payload)
+
+        async def gen():
+            for _ in range(_NUM_STREAM_RESPONSES):
+                yield request
+
+        # Invokes the actual RPC
+        call = stub.StreamingInputCall(gen())
+
+        # Validates the responses
+        response = await call
+        self.assertIsInstance(response, messages_pb2.StreamingInputCallResponse)
+        self.assertEqual(_NUM_STREAM_RESPONSES * _REQUEST_PAYLOAD_SIZE,
+                         response.aggregated_payload_size)
+
+        self.assertEqual(await call.code(), grpc.StatusCode.OK)
+
+        self.assertSequenceEqual([
+            'log_stream_stream:intercept_service',
+        ], record)
+
 
 if __name__ == '__main__':
     logging.basicConfig(level=logging.DEBUG)
diff --git a/src/python/grpcio_tests/tests_py3_only/unit/_leak_test.py b/src/python/grpcio_tests/tests_py3_only/unit/_leak_test.py
new file mode 100644 (file)
index 0000000..3b3f12f
--- /dev/null
@@ -0,0 +1,98 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""A smoke test for memory leaks on short-lived channels without close.
+
+This test doesn't guarantee all resources are cleaned if `Channel.close` is not
+explicitly invoked. The recommended way of using Channel object is using `with`
+clause, and let context manager automatically close the channel.
+"""
+
+import logging
+import os
+import resource
+import sys
+import unittest
+from concurrent.futures import ThreadPoolExecutor
+
+import grpc
+
+_TEST_METHOD = '/test/Test'
+_REQUEST = b'\x23\x33'
+_LARGE_NUM_OF_ITERATIONS = 5000
+
+# If MAX_RSS inflated more than this size, the test is failed.
+_FAIL_THRESHOLD = 25 * 1024 * 1024  #  25 MiB
+
+
+def _get_max_rss():
+    return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
+
+
+def _pretty_print_bytes(x):
+    if x > 1024 * 1024 * 1024:
+        return "%.2f GiB" % (x / 1024.0 / 1024 / 1024)
+    elif x > 1024 * 1024:
+        return "%.2f MiB" % (x / 1024.0 / 1024)
+    elif x > 1024:
+        return "%.2f KiB" % (x / 1024.0)
+    else:
+        return "%d B" % x
+
+
+class _GenericHandler(grpc.GenericRpcHandler):
+
+    def service(self, handler_call_details):
+        if handler_call_details.method == _TEST_METHOD:
+            return grpc.unary_unary_rpc_method_handler(lambda x, _: x)
+
+
+def _start_a_test_server():
+    server = grpc.server(ThreadPoolExecutor(max_workers=1),
+                         options=(('grpc.so_reuseport', 0),))
+    server.add_generic_rpc_handlers((_GenericHandler(),))
+    port = server.add_insecure_port('localhost:0')
+    server.start()
+    return 'localhost:%d' % port, server
+
+
+def _perform_an_rpc(address):
+    channel = grpc.insecure_channel(address)
+    multicallable = channel.unary_unary(_TEST_METHOD)
+    response = multicallable(_REQUEST)
+    assert _REQUEST == response
+
+
+class TestLeak(unittest.TestCase):
+
+    def test_leak_with_single_shot_rpcs(self):
+        address, server = _start_a_test_server()
+
+        # Records memory before experiment.
+        before = _get_max_rss()
+
+        # Amplifies the leak.
+        for n in range(_LARGE_NUM_OF_ITERATIONS):
+            _perform_an_rpc(address)
+
+        # Fails the test if memory leak detected.
+        diff = _get_max_rss() - before
+        if diff > _FAIL_THRESHOLD:
+            self.fail("Max RSS inflated {} > {}".format(
+                _pretty_print_bytes(diff),
+                _pretty_print_bytes(_FAIL_THRESHOLD)))
+
+
+if __name__ == "__main__":
+    logging.basicConfig(level=logging.DEBUG)
+    unittest.main(verbosity=2)
index b8d7025..fe61581 100644 (file)
@@ -620,6 +620,7 @@ typedef struct run_batch_stack {
   int recv_cancelled;
   grpc_status_code recv_status;
   grpc_slice recv_status_details;
+  const char* recv_status_debug_error_string;
   unsigned write_flag;
   grpc_slice send_status_details;
 } run_batch_stack;
@@ -729,6 +730,8 @@ static void grpc_run_batch_stack_fill_ops(run_batch_stack* st, VALUE ops_hash) {
             &st->recv_status;
         st->ops[st->op_num].data.recv_status_on_client.status_details =
             &st->recv_status_details;
+        st->ops[st->op_num].data.recv_status_on_client.error_string =
+            &st->recv_status_debug_error_string;
         break;
       case GRPC_OP_RECV_CLOSE_ON_SERVER:
         st->ops[st->op_num].data.recv_close_on_server.cancelled =
@@ -780,7 +783,12 @@ static VALUE grpc_run_batch_stack_build_result(run_batch_stack* st) {
                 (GRPC_SLICE_START_PTR(st->recv_status_details) == NULL
                      ? Qnil
                      : grpc_rb_slice_to_ruby_string(st->recv_status_details)),
-                grpc_rb_md_ary_to_h(&st->recv_trailing_metadata), NULL));
+                grpc_rb_md_ary_to_h(&st->recv_trailing_metadata),
+                st->recv_status_debug_error_string == NULL
+                    ? Qnil
+                    : rb_str_new_cstr(st->recv_status_debug_error_string),
+                NULL));
+        gpr_free((void*)st->recv_status_debug_error_string);
         break;
       case GRPC_OP_RECV_CLOSE_ON_SERVER:
         rb_struct_aset(result, sym_send_close, Qtrue);
index 7a300eb..1ab0811 100644 (file)
@@ -30,18 +30,26 @@ module GRPC
   # https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/status.h
   # for detailed descriptions of each status code.
   class BadStatus < StandardError
-    attr_reader :code, :details, :metadata
+    attr_reader :code, :details, :metadata, :debug_error_string
 
     include GRPC::Core::StatusCodes
 
     # @param code [Numeric] the status code
     # @param details [String] the details of the exception
     # @param metadata [Hash] the error's metadata
-    def initialize(code, details = 'unknown cause', metadata = {})
-      super("#{code}:#{details}")
+    def initialize(code,
+                   details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      exception_message = "#{code}:#{details}"
+      if debug_error_string
+        exception_message += ". debug_error_string:#{debug_error_string}"
+      end
+      super(exception_message)
       @code = code
       @details = details
       @metadata = metadata
+      @debug_error_string = debug_error_string
     end
 
     # Converts the exception to a {Struct::Status} for use in the networking
@@ -49,7 +57,7 @@ module GRPC
     #
     # @return [Struct::Status] with the same code and details
     def to_status
-      Struct::Status.new(code, details, metadata)
+      Struct::Status.new(code, details, metadata, debug_error_string)
     end
 
     # Converts the exception to a deserialized {Google::Rpc::Status} object.
@@ -66,8 +74,10 @@ module GRPC
       nil
     end
 
-    def self.new_status_exception(code, details = 'unknown cause',
-                                  metadata = {})
+    def self.new_status_exception(code,
+                                  details = 'unknown cause',
+                                  metadata = {},
+                                  debug_error_string = nil)
       codes = {}
       codes[OK] = Ok
       codes[CANCELLED] = Cancelled
@@ -88,129 +98,180 @@ module GRPC
       codes[DATA_LOSS] = DataLoss
 
       if codes[code].nil?
-        BadStatus.new(code, details, metadata)
+        BadStatus.new(code, details, metadata, debug_error_string)
       else
-        codes[code].new(details, metadata)
+        codes[code].new(details, metadata, debug_error_string)
       end
     end
   end
 
   # GRPC status code corresponding to status OK
   class Ok < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::OK, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::OK,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status CANCELLED
   class Cancelled < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::CANCELLED, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::CANCELLED,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status UNKNOWN
   class Unknown < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::UNKNOWN, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::UNKNOWN,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status INVALID_ARGUMENT
   class InvalidArgument < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::INVALID_ARGUMENT, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::INVALID_ARGUMENT,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status DEADLINE_EXCEEDED
   class DeadlineExceeded < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::DEADLINE_EXCEEDED, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::DEADLINE_EXCEEDED,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status NOT_FOUND
   class NotFound < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::NOT_FOUND, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::NOT_FOUND,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status ALREADY_EXISTS
   class AlreadyExists < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::ALREADY_EXISTS, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::ALREADY_EXISTS,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status PERMISSION_DENIED
   class PermissionDenied < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::PERMISSION_DENIED, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::PERMISSION_DENIED,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status UNAUTHENTICATED
   class Unauthenticated < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::UNAUTHENTICATED, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::UNAUTHENTICATED,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status RESOURCE_EXHAUSTED
   class ResourceExhausted < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::RESOURCE_EXHAUSTED, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::RESOURCE_EXHAUSTED,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status FAILED_PRECONDITION
   class FailedPrecondition < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::FAILED_PRECONDITION, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::FAILED_PRECONDITION,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status ABORTED
   class Aborted < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::ABORTED, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::ABORTED,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status OUT_OF_RANGE
   class OutOfRange < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::OUT_OF_RANGE, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::OUT_OF_RANGE,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status UNIMPLEMENTED
   class Unimplemented < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::UNIMPLEMENTED, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::UNIMPLEMENTED,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status INTERNAL
   class Internal < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::INTERNAL, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::INTERNAL,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status UNAVAILABLE
   class Unavailable < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::UNAVAILABLE, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::UNAVAILABLE,
+            details, metadata, debug_error_string)
     end
   end
 
   # GRPC status code corresponding to status DATA_LOSS
   class DataLoss < BadStatus
-    def initialize(details = 'unknown cause', metadata = {})
-      super(Core::StatusCodes::DATA_LOSS, details, metadata)
+    def initialize(details = 'unknown cause',
+                   metadata = {},
+                   debug_error_string = nil)
+      super(Core::StatusCodes::DATA_LOSS,
+            details, metadata, debug_error_string)
     end
   end
 end
index 688726e..11db1f4 100644 (file)
@@ -23,13 +23,12 @@ class Struct
     # is non-nil and not OK.
     def check_status
       return nil if status.nil?
-      fail GRPC::Cancelled if status.code == GRPC::Core::StatusCodes::CANCELLED
       if status.code != GRPC::Core::StatusCodes::OK
         GRPC.logger.debug("Failing with status #{status}")
         # raise BadStatus, propagating the metadata if present.
-        md = status.metadata
         fail GRPC::BadStatus.new_status_exception(
-          status.code, status.details, md)
+          status.code, status.details, status.metadata,
+          status.debug_error_string)
       end
       status
     end
index 56d3cec..ace2220 100644 (file)
@@ -38,7 +38,7 @@ module GRPC
     #
     # @param [Object] request
     # @param [GRPC::ActiveCall] call
-    # @param [Method] method
+    # @param [String] method
     # @param [Hash] metadata
     #
     def request_response(request: nil, call: nil, method: nil, metadata: nil)
@@ -52,7 +52,7 @@ module GRPC
     #
     # @param [Enumerable] requests
     # @param [GRPC::ActiveCall] call
-    # @param [Method] method
+    # @param [String] method
     # @param [Hash] metadata
     #
     def client_streamer(requests: nil, call: nil, method: nil, metadata: nil)
@@ -66,7 +66,7 @@ module GRPC
     #
     # @param [Object] request
     # @param [GRPC::ActiveCall] call
-    # @param [Method] method
+    # @param [String] method
     # @param [Hash] metadata
     #
     def server_streamer(request: nil, call: nil, method: nil, metadata: nil)
@@ -80,7 +80,7 @@ module GRPC
     #
     # @param [Enumerable] requests
     # @param [GRPC::ActiveCall] call
-    # @param [Method] method
+    # @param [String] method
     # @param [Hash] metadata
     #
     def bidi_streamer(requests: nil, call: nil, method: nil, metadata: nil)
index 2914d0f..2731680 100644 (file)
@@ -391,22 +391,21 @@ module GRPC
       # register signal handlers
       signals.each do |sig|
         # input validation
-        if sig.class == String
-          sig.upcase!
-          if sig.start_with?('SIG')
-            # cut out the SIG prefix to see if valid signal
-            sig = sig[3..-1]
-          end
-        end
+        target_sig = if sig.class == String
+                       # cut out the SIG prefix to see if valid signal
+                       sig.upcase.start_with?('SIG') ? sig.upcase[3..-1] : sig.upcase
+                     else
+                       sig
+                     end
 
         # register signal traps for all valid signals
-        if valid_signals.value?(sig) || valid_signals.key?(sig)
-          Signal.trap(sig) do
+        if valid_signals.value?(target_sig) || valid_signals.key?(target_sig)
+          Signal.trap(target_sig) do
             @stop_server = true
             @stop_server_cv.broadcast
           end
         else
-          fail "#{sig} not a valid signal"
+          fail "#{target_sig} not a valid signal"
         end
       end
 
index 169a62f..86de6e8 100644 (file)
@@ -31,6 +31,7 @@ module GRPC
     #
     # @param s [String] the string to be converted.
     def self.underscore(s)
+      s = +s # Avoid mutating the argument, as it might be frozen.
       s.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
       s.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
       s.tr!('-', '_')
@@ -167,22 +168,22 @@ module GRPC
             if desc.request_response?
               define_method(mth_name) do |req, metadata = {}|
                 GRPC.logger.debug("calling #{@host}:#{route}")
-                request_response(route, req, marshal, unmarshal, metadata)
+                request_response(route, req, marshal, unmarshal, **metadata)
               end
             elsif desc.client_streamer?
               define_method(mth_name) do |reqs, metadata = {}|
                 GRPC.logger.debug("calling #{@host}:#{route}")
-                client_streamer(route, reqs, marshal, unmarshal, metadata)
+                client_streamer(route, reqs, marshal, unmarshal, **metadata)
               end
             elsif desc.server_streamer?
               define_method(mth_name) do |req, metadata = {}, &blk|
                 GRPC.logger.debug("calling #{@host}:#{route}")
-                server_streamer(route, req, marshal, unmarshal, metadata, &blk)
+                server_streamer(route, req, marshal, unmarshal, **metadata, &blk)
               end
             else  # is a bidi_stream
               define_method(mth_name) do |reqs, metadata = {}, &blk|
                 GRPC.logger.debug("calling #{@host}:#{route}")
-                bidi_streamer(route, reqs, marshal, unmarshal, metadata, &blk)
+                bidi_streamer(route, reqs, marshal, unmarshal, **metadata, &blk)
               end
             end
           end
index e57f1b6..5f0608b 100644 (file)
@@ -12,4 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-Struct.new('Status', :code, :details, :metadata)
+Struct.new('Status', :code, :details, :metadata, :debug_error_string)
index 7478d35..94836e3 100644 (file)
@@ -14,5 +14,5 @@
 
 # GRPC contains the General RPC module.
 module GRPC
-  VERSION = '1.29.1'
+  VERSION = '1.30.0'
 end
diff --git a/src/ruby/pb/test/xds_client.rb b/src/ruby/pb/test/xds_client.rb
new file mode 100755 (executable)
index 0000000..a70095c
--- /dev/null
@@ -0,0 +1,213 @@
+#!/usr/bin/env ruby
+
+# Copyright 2015 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This is the xDS interop test Ruby client. This is meant to be run by
+# the run_xds_tests.py test runner.
+#
+# Usage: $ tools/run_tests/run_xds_tests.py --test_case=... ...
+#    --client_cmd="path/to/xds_client.rb --server=<hostname> \
+#                                        --stats_port=<port> \
+#                                        --qps=<qps>"
+
+# These lines are required for the generated files to load grpc
+this_dir = File.expand_path(File.dirname(__FILE__))
+lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib')
+pb_dir = File.dirname(this_dir)
+$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
+$LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
+
+require 'optparse'
+require 'logger'
+
+require_relative '../../lib/grpc'
+require 'google/protobuf'
+
+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'
+
+# Some global variables to be shared by server and client
+$watchers = Array.new
+$watchers_mutex = Mutex.new
+$watchers_cv = ConditionVariable.new
+$shutdown = false
+
+# RubyLogger defines a logger for gRPC based on the standard ruby logger.
+module RubyLogger
+  def logger
+    LOGGER
+  end
+
+  LOGGER = Logger.new(STDOUT)
+  LOGGER.level = Logger::INFO
+end
+
+# GRPC is the general RPC module
+module GRPC
+  # Inject the noop #logger if no module-level logger method has been injected.
+  extend RubyLogger
+end
+
+# creates a test stub
+def create_stub(opts)
+  address = "#{opts.server}"
+  GRPC.logger.info("... connecting insecurely to #{address}")
+  Grpc::Testing::TestService::Stub.new(
+    address,
+    :this_channel_is_insecure,
+  )
+end
+
+# This implements LoadBalancerStatsService required by the test runner
+class TestTarget < Grpc::Testing::LoadBalancerStatsService::Service
+  include Grpc::Testing
+
+  def get_client_stats(req, _call)
+    finish_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) +
+                  req['timeout_sec']
+    watcher = {}
+    $watchers_mutex.synchronize do
+      watcher = {
+        "rpcs_by_peer" => Hash.new(0),
+        "rpcs_needed" => req['num_rpcs'],
+        "no_remote_peer" => 0
+      }
+      $watchers << watcher
+      seconds_remaining = finish_time -
+                          Process.clock_gettime(Process::CLOCK_MONOTONIC)
+      while watcher['rpcs_needed'] > 0 && seconds_remaining > 0
+        $watchers_cv.wait($watchers_mutex, seconds_remaining)
+        seconds_remaining = finish_time -
+                            Process.clock_gettime(Process::CLOCK_MONOTONIC)
+      end
+      $watchers.delete_at($watchers.index(watcher))
+    end
+    LoadBalancerStatsResponse.new(
+      rpcs_by_peer: watcher['rpcs_by_peer'],
+      num_failures: watcher['no_remote_peer'] + watcher['rpcs_needed']
+    );
+  end
+end
+
+# send 1 rpc every 1/qps second
+def run_test_loop(stub, target_seconds_between_rpcs, fail_on_failed_rpcs)
+  include Grpc::Testing
+  req = SimpleRequest.new()
+  target_next_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+  while !$shutdown
+    now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+    sleep_seconds = target_next_start - now
+    if sleep_seconds < 0
+      target_next_start = now + target_seconds_between_rpcs
+      GRPC.logger.info(
+        "ruby xds: warning, rpc takes too long to finish. " \
+        "Deficit = %.1fms. " \
+        "If you consistently see this, the qps is too high." \
+        % [(sleep_seconds * 1000).abs().round(1)])
+    else
+      target_next_start += target_seconds_between_rpcs
+      sleep(sleep_seconds)
+    end
+    begin
+      deadline = GRPC::Core::TimeConsts::from_relative_time(30) # 30 seconds
+      resp = stub.unary_call(req, deadline: deadline)
+      remote_peer = resp.hostname
+    rescue GRPC::BadStatus => e
+      remote_peer = ""
+      GRPC.logger.info("ruby xds: rpc failed:|#{e.message}|, " \
+                       "this may or may not be expected")
+      if fail_on_failed_rpcs
+        raise e
+      end
+    end
+    $watchers_mutex.synchronize do
+      $watchers.each do |watcher|
+        watcher['rpcs_needed'] -= 1
+        if remote_peer.strip.empty?
+          watcher['no_remote_peer'] += 1
+        else
+          watcher['rpcs_by_peer'][remote_peer] += 1
+        end
+      end
+      $watchers_cv.broadcast
+    end
+  end
+end
+
+# Args is used to hold the command line info.
+Args = Struct.new(:fail_on_failed_rpcs, :num_channels,
+                  :server, :stats_port, :qps)
+
+# validates the command line options, returning them as a Hash.
+def parse_args
+  args = Args.new
+  args['fail_on_failed_rpcs'] = false
+  args['num_channels'] = 1
+  OptionParser.new do |opts|
+    opts.on('--fail_on_failed_rpcs BOOL', ['false', 'true']) do |v|
+      args['fail_on_failed_rpcs'] = v == 'true'
+    end
+    opts.on('--num_channels CHANNELS', 'number of channels') do |v|
+      args['num_channels'] = v.to_i
+    end
+    opts.on('--server SERVER_HOST', 'server hostname') do |v|
+      GRPC.logger.info("ruby xds: server address is #{v}")
+      args['server'] = v
+    end
+    opts.on('--stats_port STATS_PORT', 'stats port') do |v|
+      GRPC.logger.info("ruby xds: stats port is #{v}")
+      args['stats_port'] = v
+    end
+    opts.on('--qps QPS', 'qps') do |v|
+      GRPC.logger.info("ruby xds: qps is #{v}")
+      args['qps'] = v
+    end
+  end.parse!
+  args
+end
+
+def main
+  opts = parse_args
+
+  # This server hosts the LoadBalancerStatsService
+  host = "0.0.0.0:#{opts['stats_port']}"
+  s = GRPC::RpcServer.new
+  s.add_http2_port(host, :this_port_is_insecure)
+  s.handle(TestTarget)
+  server_thread = Thread.new {
+    # run the server until the main test runner terminates this process
+    s.run_till_terminated_or_interrupted(['TERM'])
+  }
+
+  # The client just sends unary rpcs continuously in a regular interval
+  stub = create_stub(opts)
+  target_seconds_between_rpcs = (1.0 / opts['qps'].to_f)
+  client_threads = Array.new
+  opts['num_channels'].times {
+    client_threads << Thread.new {
+      run_test_loop(stub, target_seconds_between_rpcs,
+                    opts['fail_on_failed_rpcs'])
+    }
+  }
+
+  server_thread.join
+  $shutdown = true
+  client_threads.each { |thd| thd.join }
+end
+
+if __FILE__ == $0
+  main
+end
diff --git a/src/ruby/spec/debug_message_spec.rb b/src/ruby/spec/debug_message_spec.rb
new file mode 100644 (file)
index 0000000..e07b9cd
--- /dev/null
@@ -0,0 +1,134 @@
+# Copyright 2015 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'spec_helper'
+
+TEST_DEBUG_MESSAGE = 'raised by test server'.freeze
+
+# a test service that checks the cert of its peer
+class DebugMessageTestService
+  include GRPC::GenericService
+  rpc :an_rpc_raises_abort, EchoMsg, EchoMsg
+  rpc :an_rpc_raises_standarderror, EchoMsg, EchoMsg
+
+  def an_rpc_raises_abort(_req, _call)
+    fail GRPC::Aborted.new(
+      'aborted',
+      {},
+      TEST_DEBUG_MESSAGE)
+  end
+
+  def an_rpc_raises_standarderror(_req, _call)
+    fail(StandardError, TEST_DEBUG_MESSAGE)
+  end
+end
+
+DebugMessageTestServiceStub = DebugMessageTestService.rpc_stub_class
+
+describe 'surfacing and transmitting of debug messages' do
+  RpcServer = GRPC::RpcServer
+
+  before(:all) do
+    server_opts = {
+      poll_period: 1
+    }
+    @srv = new_rpc_server_for_testing(**server_opts)
+    @port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
+    @srv.handle(DebugMessageTestService)
+    @srv_thd = Thread.new { @srv.run }
+    @srv.wait_till_running
+  end
+
+  after(:all) do
+    expect(@srv.stopped?).to be(false)
+    @srv.stop
+    @srv_thd.join
+  end
+
+  it 'debug error message is not present BadStatus exceptions that dont set it' do
+    exception_message = ''
+    begin
+      fail GRPC::Unavailable('unavailable', {})
+    rescue StandardError => e
+      p "Got exception: #{e.message}"
+      exception_message = e.message
+    end
+    expect(exception_message.empty?).to be(false)
+    expect(exception_message.include?('debug_error_string')).to be(false)
+  end
+
+  it 'debug error message is present in locally generated errors' do
+    # Create a secure channel. This is just one way to force a
+    # connection handshake error, which shoud result in C-core
+    # generating a status and error message and surfacing them up.
+    test_root = File.join(File.dirname(__FILE__), 'testdata')
+    files = ['ca.pem', 'client.key', 'client.pem']
+    creds = files.map { |f| File.open(File.join(test_root, f)).read }
+    creds = GRPC::Core::ChannelCredentials.new(creds[0], creds[1], creds[2])
+    stub = DebugMessageTestServiceStub.new(
+      "localhost:#{@port}", creds)
+    begin
+      stub.an_rpc_raises_abort(EchoMsg.new)
+    rescue StandardError => e
+      p "Got exception: #{e.message}"
+      exception_message = e.message
+      # check that the RPC did actually result in a BadStatus exception
+      expect(e.is_a?(GRPC::BadStatus)).to be(true)
+    end
+    # just check that the debug_error_string is non-empty (we know that
+    # it's a JSON object, so the first character is '{').
+    expect(exception_message.include?('. debug_error_string:{')).to be(true)
+  end
+
+  it 'debug message is not transmitted from server to client' do
+    # in order to not accidentally leak internal details about a
+    # server to untrusted clients, avoid including the debug_error_string
+    # field of a BadStatusException raised at a server in the
+    # RPC status that it sends to clients.
+    stub = DebugMessageTestServiceStub.new(
+      "localhost:#{@port}", :this_channel_is_insecure)
+    exception_message = ''
+    begin
+      stub.an_rpc_raises_abort(EchoMsg.new)
+    rescue StandardError => e
+      p "Got exception: #{e.message}"
+      exception_message = e.message
+      # check that the status was aborted is an indirect way to
+      # tell that the RPC did actually get handled by the server
+      expect(e.is_a?(GRPC::Aborted)).to be(true)
+    end
+    # just assert that the contents of the server-side BadStatus
+    # debug_error_string field were *not* propagated to the client.
+    expect(exception_message.include?('. debug_error_string:{')).to be(true)
+    expect(exception_message.include?(TEST_DEBUG_MESSAGE)).to be(false)
+  end
+
+  it 'standard_error messages are transmitted from server to client' do
+    # this test exists mostly in order to understand the test case
+    # above, by comparison.
+    stub = DebugMessageTestServiceStub.new(
+      "localhost:#{@port}", :this_channel_is_insecure)
+    exception_message = ''
+    begin
+      stub.an_rpc_raises_standarderror(EchoMsg.new)
+    rescue StandardError => e
+      p "Got exception: #{e.message}"
+      exception_message = e.message
+      expect(e.is_a?(GRPC::BadStatus)).to be(true)
+    end
+    # assert that the contents of the StandardError exception message
+    # are propagated to the client.
+    expect(exception_message.include?(TEST_DEBUG_MESSAGE)).to be(true)
+  end
+end
index 57aec89..16f8783 100644 (file)
@@ -55,6 +55,8 @@ describe GenericService do
       expect(GenericService.underscore('AMethod')).to eq('a_method')
       expect(GenericService.underscore('PrintHTML')).to eq('print_html')
       expect(GenericService.underscore('SeeHTMLBooks')).to eq('see_html_books')
+
+      expect(GenericService.underscore('SeeHTMLBooks'.freeze)).to eq('see_html_books')
     end
   end
 
index 4bfe61e..40400b6 100644 (file)
@@ -27,8 +27,13 @@ message AnotherTestResponse { }
 
 message Foo { }
 
+message Bar {
+  message Baz { }
+}
+
 service AnotherTestService {
   rpc GetTest(AnotherTestRequest) returns (AnotherTestResponse) { }
   rpc OtherTest(Thing) returns (Thing) { }
   rpc FooTest(Foo) returns (Foo) { }
+  rpc NestedMessageTest(Foo) returns (Bar.Baz) { }
 }
index 870f53e..cc6649c 100644 (file)
@@ -40,6 +40,8 @@ describe 'Code Generation Options' do
       expect(services[:OtherTest].output).to eq(A::Other::Thing)
       expect(services[:FooTest].input).to eq(RPC::Test::New::Package::Options::Foo)
       expect(services[:FooTest].output).to eq(RPC::Test::New::Package::Options::Foo)
+      expect(services[:NestedMessageTest].input).to eq(RPC::Test::New::Package::Options::Foo)
+      expect(services[:NestedMessageTest].output).to eq(RPC::Test::New::Package::Options::Bar::Baz)
     end
   end
 end
index afb557d..6a239eb 100644 (file)
@@ -14,6 +14,6 @@
 
 module GRPC
   module Tools
-    VERSION = '1.29.1'
+    VERSION = '1.30.0'
   end
 end
index e6fc6c0..761c8af 100644 (file)
   endif()
 
    # Use C99 standard
-  set(CMAKE_C_STANDARD 99)
+  if (NOT DEFINED CMAKE_C_STANDARD)
+    set(CMAKE_C_STANDARD 99)
+  endif()
 
   # Add c++11 flags
-  set(CMAKE_CXX_STANDARD 11)
-  set(CMAKE_CXX_STANDARD_REQUIRED ON)
-  set(CMAKE_CXX_EXTENSIONS OFF)
+  if (NOT DEFINED CMAKE_CXX_STANDARD)
+    set(CMAKE_CXX_STANDARD 11)
+  else()
+    if (CMAKE_CXX_STANDARD LESS 11)
+      message(FATAL_ERROR "CMAKE_CXX_STANDARD is less than 11, please specify at least SET(CMAKE_CXX_STANDARD 11)")
+    endif()
+  endif()
+  if (NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED)
+    set(CMAKE_CXX_STANDARD_REQUIRED ON)
+  endif()
+  if (NOT DEFINED CMAKE_CXX_EXTENSIONS)
+    set(CMAKE_CXX_EXTENSIONS OFF)
+  endif()
 
   ## Some libraries are shared even with BUILD_SHARED_LIBRARIES=OFF
-  set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
+  if (NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
+    set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
+  endif()
   list(APPEND CMAKE_MODULE_PATH "<%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/cmake/modules")
 
   if(MSVC)
     # TODO(jtattermusch): needed to build boringssl with VS2017, revisit later
     set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /wd4987 /wd4774 /wd4819 /wd4996 /wd4619")
   endif()
+  if (MINGW)
+    add_definitions(-D_WIN32_WINNT=0x600)
+  endif()
   set(CMAKE_C_FLAGS "<%text>${CMAKE_C_FLAGS} ${_gRPC_C_CXX_FLAGS}</%text>")
   set(CMAKE_CXX_FLAGS "<%text>${CMAKE_CXX_FLAGS} ${_gRPC_C_CXX_FLAGS}</%text>")
 
     set(_gRPC_ALLTARGETS_LIBRARIES <%text>${CMAKE_DL_LIBS}</%text> rt m pthread)
   endif()
 
-  if(WIN32 AND MSVC)
+  if(WIN32)
     set(_gRPC_BASELIB_LIBRARIES wsock32 ws2_32 crypt32)
   endif()
 
index e8bccfd..46ef974 100644 (file)
       ss.header_mappings_dir = '.'
       ss.libraries = 'z'
       ss.dependency "#{s.name}/Interface", version
-      ss.dependency 'BoringSSL-GRPC', '0.0.8'
+      ss.dependency 'BoringSSL-GRPC', '0.0.9'
       abseil_version = '1.20200225.0'
       % for abseil_spec in grpc_abseil_specs:
       ss.dependency '${abseil_spec}', abseil_version
index 6420045..29dd724 100644 (file)
@@ -68,7 +68,8 @@
                         "src/objective-c/GRPCClient/GRPCCall+OAuth2.h",
                         "src/objective-c/GRPCClient/GRPCCall+Tests.h",
                         "src/objective-c/GRPCClient/GRPCCallLegacy.h",
-                        "src/objective-c/GRPCClient/GRPCTypes.h"
+                        "src/objective-c/GRPCClient/GRPCTypes.h",
+                        "src/objective-c/GRPCClient/GRPCTypes.m"
       ss.dependency "gRPC-RxLibrary/Interface", version
 
       ss.ios.deployment_target = '7.0'
index ba6ea17..43405ad 100644 (file)
@@ -9,7 +9,7 @@
     s.name          = 'grpc'
     s.version       = GRPC::VERSION
     s.authors       = ['gRPC Authors']
-    s.email         = 'temiola@google.com'
+    s.email         = 'grpc-io@googlegroups.com'
     s.homepage      = 'https://github.com/google/grpc/tree/master/src/ruby'
     s.summary       = 'GRPC system in Ruby'
     s.description   = 'Send RPCs from Ruby using GRPC'
@@ -34,7 +34,7 @@
     s.require_paths = %w( src/ruby/lib src/ruby/bin src/ruby/pb )
     s.platform      = Gem::Platform::RUBY
 
-    s.add_dependency 'google-protobuf', '~> 3.11'
+    s.add_dependency 'google-protobuf', '~> 3.12'
     s.add_dependency 'googleapis-common-protos-types', '~> 1.0'
 
     s.add_development_dependency 'bundler',            '>= 1.9'
index f2b3a16..e6fe0a2 100644 (file)
@@ -9,6 +9,7 @@ native_method_signatures = [
     'int grpcsharp_batch_context_recv_message_next_slice_peek(BatchContextSafeHandle ctx, out UIntPtr sliceLen, out IntPtr sliceDataPtr)',
     'StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx)',
     'IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx, out UIntPtr detailsLength)',
+    'IntPtr grpcsharp_batch_context_recv_status_on_client_error_string(BatchContextSafeHandle ctx)',
     'IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx)',
     'int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx)',
     'void grpcsharp_batch_context_reset(BatchContextSafeHandle ctx)',
index d3edb75..c74a79f 100755 (executable)
@@ -4,6 +4,6 @@
   <Project>
     <PropertyGroup>
       <GrpcCsharpVersion>${settings.csharp_version}</GrpcCsharpVersion>
-      <GoogleProtobufVersion>3.11.2</GoogleProtobufVersion>
+      <GoogleProtobufVersion>3.12.2</GoogleProtobufVersion>
     </PropertyGroup>
   </Project>
index 4c9fce9..e988c78 100644 (file)
     s.preserve_paths = plugin
 
     # Restrict the protoc version to the one supported by this plugin.
-    s.dependency '!ProtoCompiler', '3.11.2'
+    s.dependency '!ProtoCompiler', '3.12.2'
     # For the Protobuf dependency not to complain:
     s.ios.deployment_target = '7.0'
     s.osx.deployment_target = '10.9'
index 1e1d1ef..af422a0 100644 (file)
     s.preserve_paths = plugin
 
     # Restrict the protoc version to the one supported by this plugin.
-    s.dependency '!ProtoCompiler', '3.11.2'
+    s.dependency '!ProtoCompiler', '3.12.2'
     # For the Protobuf dependency not to complain:
     s.ios.deployment_target = '7.0'
     s.osx.deployment_target = '10.9'
index 7503658..d1cf851 100644 (file)
@@ -69,7 +69,7 @@
 
   Pod::Spec.new do |s|
     s.name     = 'BoringSSL-GRPC'
-    version = '0.0.8'
+    version = '0.0.9'
     s.version  = version
     s.summary  = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.'
     # Adapted from the homepage:
diff --git a/templates/src/php/docker/centos7/Dockerfile.template b/templates/src/php/docker/centos7/Dockerfile.template
new file mode 100644 (file)
index 0000000..47084bf
--- /dev/null
@@ -0,0 +1,44 @@
+%YAML 1.2
+--- |
+  # Copyright 2019 gRPC authors.
+  #
+  # Licensed under the Apache License, Version 2.0 (the "License");
+  # you may not use this file except in compliance with the License.
+  # You may obtain a copy of the License at
+  #
+  #     http://www.apache.org/licenses/LICENSE-2.0
+  #
+  # Unless required by applicable law or agreed to in writing, software
+  # distributed under the License is distributed on an "AS IS" BASIS,
+  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  # See the License for the specific language governing permissions and
+  # limitations under the License.
+
+  FROM centos:centos7
+
+  RUN yum update -y && ${'\\'}
+    yum install -y centos-release-scl && ${'\\'}
+    yum install -y devtoolset-7-gcc*
+
+  SHELL [ "/usr/bin/scl", "enable", "devtoolset-7"]
+  
+  RUN yum install epel-release -y && ${'\\'}
+    rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm && ${'\\'}
+    rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm && ${'\\'}
+    yum --enablerepo=remi-php72 install php -y && ${'\\'}
+    yum-config-manager --enable remi-php72 > /dev/null && ${'\\'}
+    yum install -y make wget which ${'\\'}
+      gmp-devel libmpc-devel mpfr-devel yum-utils ${'\\'}                                                            
+      php-devel php-fpm php-pear && ${'\\'}                                                                          
+    yum clean all -y  
+
+  ARG MAKEFLAGS=-j8
+
+
+  WORKDIR /tmp
+
+  <%include file="../download_phpunit.include" />
+
+  <%include file="../pecl_ext_build_src.include" />
+
+  CMD ["/github/grpc/src/php/bin/run_tests.sh", "--skip-persistent-channel-tests"]
index f9abb2f..f7aebd1 100644 (file)
   # See the License for the specific language governing permissions and
   # limitations under the License.
 
-  FROM php:7.4.0RC1-buster
+  FROM php:7.4.5-buster
 
   RUN apt-get -qq update && apt-get -qq install -y ${'\\'}
     autoconf automake git libtool pkg-config ${'\\'}
-    wget zlib1g-dev
+    valgrind wget zlib1g-dev
 
   ARG MAKEFLAGS=-j8
 
@@ -29,4 +29,4 @@
 
   <%include file="../pecl_ext_build_src.include" />
 
-  CMD ["/github/grpc/src/php/bin/run_tests.sh", "--skip-persistent-channel-tests"]
+  CMD ["/github/grpc/src/php/bin/run_tests.sh", "--skip-persistent-channel-tests", "--ignore-valgrind-undef-errors"]
index 5a26364..f93c241 100644 (file)
@@ -1,3 +1,2 @@
 # Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
 RUN pip install --upgrade google-api-python-client oauth2client
index c8463da..9c9cbce 100755 (executable)
@@ -22,7 +22,9 @@ cp -r /var/local/jenkins/grpc-java /tmp/grpc-java
 cp -r /var/local/jenkins/service_account $HOME || true
 
 pushd /tmp/grpc-java
-./gradlew --no-daemon :grpc-interop-testing:installDist -PskipCodegen=true -PskipAndroid=true
+# make two attempts; downloads can fail. See https://github.com/grpc/grpc/issues/18892
+./gradlew --no-daemon :grpc-interop-testing:installDist -PskipCodegen=true -PskipAndroid=true || ${'\\'}
+    ./gradlew --no-daemon :grpc-interop-testing:installDist -PskipCodegen=true -PskipAndroid=true
 
 mkdir -p /var/local/git/grpc-java/
 cp -r --parents -t /var/local/git/grpc-java/ ${'\\'}
index 883ece2..f65c9ff 100644 (file)
@@ -1,6 +1,6 @@
 FROM debian:10
   
 <%include file="./apt_get_basic.include"/>
-<%include file="./gcp_api_libraries.include"/>
 <%include file="./apt_get_python_27.include"/>
+<%include file="./gcp_api_libraries.include"/>
 <%include file="./run_tests_addons.include"/>
index 8c3f32f..cdacfdd 100644 (file)
@@ -6,9 +6,10 @@
 RUN apt-get update && apt-get install -y ${'\\'}
     python-all-dev ${'\\'}
     python3-all-dev ${'\\'}
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index 8591e75..63ea6ae 100644 (file)
@@ -1,8 +1,8 @@
 FROM debian:stretch
   
 <%include file="./apt_get_basic.include"/>
-<%include file="./gcp_api_libraries.include"/>
 <%include file="./apt_get_python_27.include"/>
+<%include file="./gcp_api_libraries.include"/>
 # Add Debian 'buster' repository, we will need it for installing newer versions of python
 RUN echo 'deb http://ftp.de.debian.org/debian buster main' >> /etc/apt/sources.list
 RUN echo 'APT::Default-Release "stretch";' | tee -a /etc/apt/apt.conf.d/00local
index 1526d07..355b47e 100644 (file)
@@ -17,8 +17,8 @@
   FROM debian:stretch
   
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../csharp_deps.include"/>
   <%include file="../../csharp_dotnetcli_deps.include"/>
   <%include file="../../run_tests_addons.include"/>
index c628aac..e1b1d20 100644 (file)
@@ -14,7 +14,7 @@
   # See the License for the specific language governing permissions and
   # limitations under the License.
   
-  FROM alpine:3.5
+  FROM alpine:3.9
   
   # Install Git and basic packages.
   RUN apk update && apk add ${'\\'}
index d3da8ab..5d398e4 100644 (file)
@@ -17,8 +17,8 @@
   FROM debian:buster
   
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../cxx_deps.include"/>
   <%include file="../../run_tests_addons.include"/>
   
index 9d358a0..1fa7c3b 100644 (file)
@@ -17,8 +17,8 @@
   <%include file="../../debian_jessie_header.include"/>
 
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../cxx_deps.include"/>
   <%include file="../../cmake_jessie_backports.include"/>
   <%include file="../../run_tests_addons.include"/>
index fc79ecc..064b2ab 100644 (file)
@@ -18,8 +18,8 @@
   RUN sed -i '/deb http:\/\/http.debian.net\/debian jessie-updates main/d' /etc/apt/sources.list
   
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../cxx_deps.include"/>
   <%include file="../../run_tests_addons.include"/>
   <%include file="../../cmake_jessie_backports.include"/>
index 7d17323..8d2a40a 100644 (file)
@@ -19,8 +19,8 @@
   RUN sed -i '/deb http:\/\/httpredir.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list
 
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   #=================
   # C++ dependencies (purposely excluding Clang because it's part of the base image)
   RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev && apt-get clean
index 3668c97..3e92dd1 100644 (file)
@@ -17,8 +17,8 @@
   FROM ubuntu:14.04
   
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../cxx_deps.include"/>
   <%include file="../../run_tests_addons.include"/>
   # Define the default command.
index a311b12..2ab8379 100644 (file)
@@ -17,8 +17,8 @@
   FROM ubuntu:16.04
   
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../cxx_deps.include"/>
   <%include file="../../run_tests_addons.include"/>
   
index 76faebd..dd833b9 100644 (file)
@@ -17,8 +17,8 @@
   FROM ubuntu:18.04
   
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../cxx_deps.include"/>
   <%include file="../../run_tests_addons.include"/>
   
index 345da08..8ad5b06 100644 (file)
@@ -17,8 +17,8 @@
   <%include file="../../debian_jessie_header.include"/>
 
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../cxx_deps.include"/>
   <%include file="../../cmake_jessie_backports.include"/>
   <%include file="../../clang_update.include"/>
index cd0513a..d5c4153 100644 (file)
@@ -17,7 +17,6 @@
   <%include file="../../debian_jessie_header.include"/>
 
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
 
   # Install Electron apt dependencies
   RUN apt-get update && apt-get install -y ${'\\'}
@@ -30,6 +29,7 @@
     xvfb
 
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../node_deps.include"/>
   <%include file="../../run_tests_addons.include"/>
   # Install Mako to generate files in grpc/grpc-node
index d29cd7e..cf83681 100644 (file)
@@ -17,8 +17,8 @@
   <%include file="../../debian_jessie_header.include"/>
   
   <%include file="../../php7_deps.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../php_valgrind.include"/>
   <%include file="../../run_tests_addons.include"/>
   # Define the default command.
index 3bd8f9c..f3459f4 100644 (file)
@@ -17,8 +17,8 @@
   <%include file="../../debian_jessie_header.include"/>
   
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../php_deps.include"/>
   <%include file="../../run_tests_addons.include"/>
   # Define the default command.
index 2fed022..af90c93 100644 (file)
@@ -17,8 +17,8 @@
   <%include file="../../debian_jessie_header.include"/>
   
   <%include file="../../apt_get_basic.include"/>
-  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../ruby_deps.include"/>
   <%include file="../../run_tests_addons.include"/>
   # Define the default command.
index 8206afa..e8b153f 100644 (file)
@@ -20,6 +20,9 @@
 
 #include <string.h>
 
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
 #include "src/core/lib/gpr/string.h"
@@ -144,22 +147,17 @@ int main(int argc, char** argv) {
   grpc::testing::TestEnvironment env(argc, argv);
 
   // Test sending more metadata than the server will accept.
-  gpr_strvec headers;
-  gpr_strvec_init(&headers);
+  std::vector<std::string> headers;
   for (i = 0; i < NUM_HEADERS; ++i) {
-    char* str;
-    gpr_asprintf(&str, "%s%02d%s",
-                 PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR, i,
-                 PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR);
-    gpr_strvec_add(&headers, str);
+    headers.push_back(absl::StrFormat(
+        "%s%02d%s", PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR, i,
+        PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR));
   }
-  size_t headers_len;
-  const char* client_headers = gpr_strvec_flatten(&headers, &headers_len);
-  gpr_strvec_destroy(&headers);
+  std::string client_headers = absl::StrJoin(headers, "");
   char client_payload[TOO_MUCH_METADATA_FROM_CLIENT_REQUEST_SIZE] =
       PFX_TOO_MUCH_METADATA_FROM_CLIENT_REQUEST;
   memcpy(client_payload + sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_REQUEST) - 1,
-         client_headers, headers_len);
+         client_headers.data(), client_headers.size());
   grpc_bad_client_arg args[2];
   args[0] = connection_preface_arg;
   args[1].client_validator = rst_stream_client_validator;
@@ -167,7 +165,6 @@ int main(int argc, char** argv) {
   args[1].client_payload_length = sizeof(client_payload) - 1;
 
   grpc_run_bad_client_test(server_verifier_request_call, args, 2, 0);
-  gpr_free((void*)client_headers);
 
   // Test sending more metadata than the client will accept.
   GRPC_RUN_BAD_CLIENT_TEST(server_verifier_sends_too_much_metadata,
index 4c1662d..9ef027f 100644 (file)
@@ -145,9 +145,8 @@ int main(int argc, char** argv) {
   gpr_asprintf(&args[0], "%s/bad_ssl_%s_server%s", root, test,
                gpr_subprocess_binary_extension());
   args[1] = const_cast<char*>("--bind");
-  grpc_core::UniquePtr<char> joined;
-  grpc_core::JoinHostPort(&joined, "::", port);
-  args[2] = joined.get();
+  std::string joined = grpc_core::JoinHostPort("::", port);
+  args[2] = const_cast<char*>(joined.c_str());
   svr = gpr_subprocess_create(4, (const char**)args);
   gpr_free(args[0]);
 
index 6f9698e..79e82b3 100755 (executable)
@@ -29,7 +29,6 @@ def grpc_bad_ssl_tests():
         deps = [
             "//test/core/util:grpc_test_util",
             "//:grpc",
-            "//test/core/end2end:ssl_test_data",
         ],
     )
     for t in BAD_SSL_TESTS:
@@ -45,6 +44,9 @@ def grpc_bad_ssl_tests():
                 ":bad_ssl_%s_server" % t,
                 "//src/core/tsi/test_creds:badserver.key",
                 "//src/core/tsi/test_creds:badserver.pem",
+                "//src/core/tsi/test_creds:ca.pem",
+                "//src/core/tsi/test_creds:server1.key",
+                "//src/core/tsi/test_creds:server1.pem",
             ],
             deps = [
                 "//test/core/util:grpc_test_util",
index 4a04178..795a856 100644 (file)
  *
  */
 
-#include <string.h>
+#include "src/core/ext/transport/chttp2/alpn/alpn.h"
 
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
 #include <grpc/support/log.h>
+#include <string.h>
 
-#include "src/core/ext/transport/chttp2/alpn/alpn.h"
 #include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/iomgr/load_file.h"
 #include "test/core/bad_ssl/server_common.h"
-#include "test/core/end2end/data/ssl_test_data.h"
+
+#define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
+#define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem"
+#define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key"
 
 /* This test starts a server that is configured to advertise (via alpn and npn)
  * a protocol that the connecting client does not support. It does this by
@@ -52,8 +56,16 @@ const char* grpc_chttp2_get_alpn_version_index(size_t i) {
 
 int main(int argc, char** argv) {
   const char* addr = bad_ssl_addr(argc, argv);
-  grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key,
-                                                  test_server1_cert};
+  grpc_slice cert_slice, key_slice;
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice)));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+                               grpc_load_file(SERVER_KEY_PATH, 1, &key_slice)));
+  const char* server_cert =
+      reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
+  const char* server_key =
+      reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
+  grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert};
   grpc_server_credentials* ssl_creds;
   grpc_server* server;
 
@@ -65,6 +77,8 @@ int main(int argc, char** argv) {
   grpc_server_credentials_release(ssl_creds);
 
   bad_ssl_run(server);
+  grpc_slice_unref(cert_slice);
+  grpc_slice_unref(key_slice);
   grpc_shutdown();
 
   return 0;
index 0722d6b..785e10b 100644 (file)
@@ -25,7 +25,6 @@
 #include "src/core/lib/iomgr/load_file.h"
 
 #include "test/core/bad_ssl/server_common.h"
-#include "test/core/end2end/data/ssl_test_data.h"
 
 /* This server will present an untrusted cert to the connecting client,
  * causing the SSL handshake to fail */
index 2383620..88ddea9 100644 (file)
@@ -87,7 +87,6 @@ grpc_cc_test(
     external_deps = [
         "gtest",
     ],
-    flaky = True,  # TODO(b/151792070)
     language = "C++",
     deps = [
         "//:gpr",
index b16d2d5..338cd0f 100644 (file)
@@ -48,11 +48,11 @@ namespace testing {
 class CallCountingHelperPeer {
  public:
   explicit CallCountingHelperPeer(CallCountingHelper* node) : node_(node) {}
-  grpc_millis last_call_started_millis() const {
+
+  gpr_timespec last_call_started_time() const {
     CallCountingHelper::CounterData data;
     node_->CollectData(&data);
-    gpr_timespec ts = gpr_cycle_counter_to_time(data.last_call_started_cycle);
-    return grpc_timespec_to_millis_round_up(ts);
+    return gpr_cycle_counter_to_time(data.last_call_started_cycle);
   }
 
  private:
@@ -243,9 +243,9 @@ void ValidateServer(ServerNode* server, const ValidateChannelDataArgs& args) {
   gpr_free(core_api_json_str);
 }
 
-grpc_millis GetLastCallStartedMillis(CallCountingHelper* channel) {
+gpr_timespec GetLastCallStartedTime(CallCountingHelper* channel) {
   CallCountingHelperPeer peer(channel);
-  return peer.last_call_started_millis();
+  return peer.last_call_started_time();
 }
 
 void ChannelzSleep(int64_t sleep_us) {
@@ -301,28 +301,28 @@ TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) {
   ValidateChannel(channelz_channel, {3, 3, 3});
 }
 
-TEST_P(ChannelzChannelTest, LastCallStartedMillis) {
+TEST_P(ChannelzChannelTest, LastCallStartedTime) {
   grpc_core::ExecCtx exec_ctx;
   CallCountingHelper counter;
   // start a call to set the last call started timestamp
   counter.RecordCallStarted();
-  grpc_millis millis1 = GetLastCallStartedMillis(&counter);
+  gpr_timespec time1 = GetLastCallStartedTime(&counter);
   // time gone by should not affect the timestamp
   ChannelzSleep(100);
-  grpc_millis millis2 = GetLastCallStartedMillis(&counter);
-  EXPECT_EQ(millis1, millis2);
+  gpr_timespec time2 = GetLastCallStartedTime(&counter);
+  EXPECT_EQ(gpr_time_cmp(time1, time2), 0);
   // calls succeeded or failed should not affect the timestamp
   ChannelzSleep(100);
   counter.RecordCallFailed();
   counter.RecordCallSucceeded();
-  grpc_millis millis3 = GetLastCallStartedMillis(&counter);
-  EXPECT_EQ(millis1, millis3);
+  gpr_timespec time3 = GetLastCallStartedTime(&counter);
+  EXPECT_EQ(gpr_time_cmp(time1, time3), 0);
   // another call started should affect the timestamp
   // sleep for extra long to avoid flakes (since we cache Now())
   ChannelzSleep(5000);
   counter.RecordCallStarted();
-  grpc_millis millis4 = GetLastCallStartedMillis(&counter);
-  EXPECT_NE(millis1, millis4);
+  gpr_timespec time4 = GetLastCallStartedTime(&counter);
+  EXPECT_NE(gpr_time_cmp(time1, time4), 0);
 }
 
 class ChannelzRegistryBasedTest : public ::testing::TestWithParam<size_t> {
index 858fd56..455d6ae 100644 (file)
 #include <grpc/support/string_util.h>
 #include <string.h>
 
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include "src/core/lib/channel/channel_stack_builder.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/surface/channel_init.h"
@@ -138,64 +142,51 @@ static int check_stack(const char* file, int line, const char* transport_name,
   }
 
   // build up our expectation list
-  gpr_strvec v;
-  gpr_strvec_init(&v);
+  std::vector<std::string> parts;
   va_list args;
   va_start(args, channel_stack_type);
   for (;;) {
     char* a = va_arg(args, char*);
     if (a == nullptr) break;
-    if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", "));
-    gpr_strvec_add(&v, gpr_strdup(a));
+    parts.push_back(a);
   }
   va_end(args);
-  char* expect = gpr_strvec_flatten(&v, nullptr);
-  gpr_strvec_destroy(&v);
+  std::string expect = absl::StrJoin(parts, ", ");
 
   // build up our "got" list
-  gpr_strvec_init(&v);
+  parts.clear();
   grpc_channel_stack_builder_iterator* it =
       grpc_channel_stack_builder_create_iterator_at_first(builder);
   while (grpc_channel_stack_builder_move_next(it)) {
     const char* name = grpc_channel_stack_builder_iterator_filter_name(it);
     if (name == nullptr) continue;
-    if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", "));
-    gpr_strvec_add(&v, gpr_strdup(name));
+    parts.push_back(name);
   }
-  char* got = gpr_strvec_flatten(&v, nullptr);
-  gpr_strvec_destroy(&v);
+  std::string got = absl::StrJoin(parts, ", ");
   grpc_channel_stack_builder_iterator_destroy(it);
 
   // figure out result, log if there's an error
   int result = 0;
-  if (0 != strcmp(got, expect)) {
-    gpr_strvec_init(&v);
-    gpr_strvec_add(&v, gpr_strdup("{"));
+  if (got != expect) {
+    parts.clear();
     for (size_t i = 0; i < channel_args->num_args; i++) {
-      if (i > 0) gpr_strvec_add(&v, gpr_strdup(", "));
-      gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].key));
-      gpr_strvec_add(&v, gpr_strdup("="));
+      std::string value;
       switch (channel_args->args[i].type) {
         case GRPC_ARG_INTEGER: {
-          char* tmp;
-          gpr_asprintf(&tmp, "%d", channel_args->args[i].value.integer);
-          gpr_strvec_add(&v, tmp);
+          value = absl::StrCat(channel_args->args[i].value.integer);
           break;
         }
         case GRPC_ARG_STRING:
-          gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].value.string));
+          value = channel_args->args[i].value.string;
           break;
         case GRPC_ARG_POINTER: {
-          char* tmp;
-          gpr_asprintf(&tmp, "%p", channel_args->args[i].value.pointer.p);
-          gpr_strvec_add(&v, tmp);
+          value = absl::StrFormat("%p", channel_args->args[i].value.pointer.p);
           break;
         }
       }
+      parts.push_back(absl::StrCat(channel_args->args[i].key, "=", value));
     }
-    gpr_strvec_add(&v, gpr_strdup("}"));
-    char* args_str = gpr_strvec_flatten(&v, nullptr);
-    gpr_strvec_destroy(&v);
+    std::string args_str = absl::StrCat("{", absl::StrJoin(parts, ", "), "}");
 
     gpr_log(file, line, GPR_LOG_SEVERITY_ERROR,
             "**************************************************");
@@ -204,17 +195,12 @@ static int check_stack(const char* file, int line, const char* transport_name,
         "FAILED transport=%s; stack_type=%s; channel_args=%s:", transport_name,
         grpc_channel_stack_type_string(
             static_cast<grpc_channel_stack_type>(channel_stack_type)),
-        args_str);
-    gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "EXPECTED: %s", expect);
-    gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "GOT:      %s", got);
+        args_str.c_str());
+    gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "EXPECTED: %s", expect.c_str());
+    gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "GOT:      %s", got.c_str());
     result = 1;
-
-    gpr_free(args_str);
   }
 
-  gpr_free(got);
-  gpr_free(expect);
-
   {
     grpc_core::ExecCtx exec_ctx;
     grpc_channel_stack_builder_destroy(builder);
index 79b50d0..fedbc25 100644 (file)
@@ -61,8 +61,8 @@ static void test_grpc_parse_ipv6_parity_with_getaddrinfo(
 
 struct sockaddr_in6 resolve_with_gettaddrinfo(const char* uri_text) {
   grpc_uri* uri = grpc_uri_parse(uri_text, 0);
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
+  std::string host;
+  std::string port;
   grpc_core::SplitHostPort(uri->path, &host, &port);
   struct addrinfo hints;
   memset(&hints, 0, sizeof(hints));
@@ -70,11 +70,11 @@ struct sockaddr_in6 resolve_with_gettaddrinfo(const char* uri_text) {
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_flags = AI_NUMERICHOST;
   struct addrinfo* result;
-  int res = getaddrinfo(host.get(), port.get(), &hints, &result);
+  int res = getaddrinfo(host.c_str(), port.c_str(), &hints, &result);
   if (res != 0) {
     gpr_log(GPR_ERROR,
             "getaddrinfo failed to resolve host:%s port:%s. Error: %d.",
-            host.get(), port.get(), res);
+            host.c_str(), port.c_str(), res);
     abort();
   }
   size_t num_addrs_from_getaddrinfo = 0;
index 2dc86f1..6b67aa1 100644 (file)
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
 #include "src/core/ext/filters/client_channel/server_address.h"
 #include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "test/core/util/test_config.h"
 
 static gpr_mu g_mu;
 static bool g_fail_resolution = true;
-static grpc_core::Combiner* g_combiner;
+static std::shared_ptr<grpc_core::WorkSerializer>* g_work_serializer;
 
 static void my_resolve_address(const char* addr, const char* /*default_port*/,
                                grpc_pollset_set* /*interested_parties*/,
@@ -66,7 +66,7 @@ static grpc_ares_request* my_dns_lookup_ares_locked(
     std::unique_ptr<grpc_core::ServerAddressList>* addresses,
     std::unique_ptr<grpc_core::ServerAddressList>* /*balancer_addresses*/,
     char** /*service_config_json*/, int /*query_timeout_ms*/,
-    grpc_core::Combiner* /*combiner*/) {
+    std::shared_ptr<grpc_core::WorkSerializer> /*combiner*/) {  // NOLINT
   gpr_mu_lock(&g_mu);
   GPR_ASSERT(0 == strcmp("test", addr));
   grpc_error* error = GRPC_ERROR_NONE;
@@ -99,7 +99,7 @@ static grpc_core::OrphanablePtr<grpc_core::Resolver> create_resolver(
   GPR_ASSERT(uri);
   grpc_core::ResolverArgs args;
   args.uri = uri;
-  args.combiner = g_combiner;
+  args.work_serializer = *g_work_serializer;
   args.result_handler = std::move(result_handler);
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
       factory->CreateResolver(std::move(args));
@@ -161,7 +161,8 @@ int main(int argc, char** argv) {
 
   grpc_init();
   gpr_mu_init(&g_mu);
-  g_combiner = grpc_combiner_create();
+  auto work_serializer = std::make_shared<grpc_core::WorkSerializer>();
+  g_work_serializer = &work_serializer;
   grpc_set_resolver_impl(&test_resolver);
   grpc_dns_lookup_ares_locked = my_dns_lookup_ares_locked;
   grpc_cancel_ares_request_locked = my_cancel_ares_request_locked;
@@ -186,8 +187,6 @@ int main(int argc, char** argv) {
     GPR_ASSERT(wait_loop(30, &output2.ev));
     GPR_ASSERT(!output2.result.addresses.empty());
     GPR_ASSERT(output2.error == GRPC_ERROR_NONE);
-
-    GRPC_COMBINER_UNREF(g_combiner, "test");
   }
 
   grpc_shutdown();
index 14b0d9f..9f3f31c 100644 (file)
@@ -26,8 +26,8 @@
 #include "src/core/ext/filters/client_channel/server_address.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gprpp/memory.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "test/core/util/test_config.h"
 
 constexpr int kMinResolutionPeriodMs = 1000;
@@ -37,7 +37,7 @@ constexpr int kMinResolutionPeriodForCheckMs = 900;
 extern grpc_address_resolver_vtable* grpc_resolve_address_impl;
 static grpc_address_resolver_vtable* default_resolve_address;
 
-static grpc_core::Combiner* g_combiner;
+static std::shared_ptr<grpc_core::WorkSerializer>* g_work_serializer;
 
 static grpc_ares_request* (*g_default_dns_lookup_ares_locked)(
     const char* dns_server, const char* name, const char* default_port,
@@ -45,7 +45,7 @@ static grpc_ares_request* (*g_default_dns_lookup_ares_locked)(
     std::unique_ptr<grpc_core::ServerAddressList>* addresses,
     std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses,
     char** service_config_json, int query_timeout_ms,
-    grpc_core::Combiner* combiner);
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer);
 
 // Counter incremented by test_resolve_address_impl indicating the number of
 // times a system-level resolution has happened.
@@ -97,11 +97,11 @@ static grpc_ares_request* test_dns_lookup_ares_locked(
     std::unique_ptr<grpc_core::ServerAddressList>* addresses,
     std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses,
     char** service_config_json, int query_timeout_ms,
-    grpc_core::Combiner* combiner) {
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer) {
   grpc_ares_request* result = g_default_dns_lookup_ares_locked(
       dns_server, name, default_port, g_iomgr_args.pollset_set, on_done,
       addresses, balancer_addresses, service_config_json, query_timeout_ms,
-      combiner);
+      std::move(work_serializer));
   ++g_resolution_count;
   static grpc_millis last_resolution_time = 0;
   grpc_millis now =
@@ -274,7 +274,7 @@ static void on_first_resolution(OnResolutionCallbackArg* cb_arg) {
   gpr_mu_unlock(g_iomgr_args.mu);
 }
 
-static void start_test_under_combiner(void* arg, grpc_error* /*error*/) {
+static void start_test_under_work_serializer(void* arg) {
   OnResolutionCallbackArg* res_cb_arg =
       static_cast<OnResolutionCallbackArg*>(arg);
   res_cb_arg->result_handler = new ResultHandler();
@@ -286,7 +286,7 @@ static void start_test_under_combiner(void* arg, grpc_error* /*error*/) {
   GPR_ASSERT(uri != nullptr);
   grpc_core::ResolverArgs args;
   args.uri = uri;
-  args.combiner = g_combiner;
+  args.work_serializer = *g_work_serializer;
   args.result_handler = std::unique_ptr<grpc_core::Resolver::ResultHandler>(
       res_cb_arg->result_handler);
   g_resolution_count = 0;
@@ -310,9 +310,9 @@ static void test_cooldown() {
   OnResolutionCallbackArg* res_cb_arg = new OnResolutionCallbackArg();
   res_cb_arg->uri_str = "dns:127.0.0.1";
 
-  g_combiner->Run(
-      GRPC_CLOSURE_CREATE(start_test_under_combiner, res_cb_arg, nullptr),
-      GRPC_ERROR_NONE);
+  (*g_work_serializer)
+      ->Run([res_cb_arg]() { start_test_under_work_serializer(res_cb_arg); },
+            DEBUG_LOCATION);
   grpc_core::ExecCtx::Get()->Flush();
   poll_pollset_until_request_done(&g_iomgr_args);
   iomgr_args_finish(&g_iomgr_args);
@@ -322,7 +322,8 @@ int main(int argc, char** argv) {
   grpc::testing::TestEnvironment env(argc, argv);
   grpc_init();
 
-  g_combiner = grpc_combiner_create();
+  auto work_serializer = std::make_shared<grpc_core::WorkSerializer>();
+  g_work_serializer = &work_serializer;
 
   g_default_dns_lookup_ares_locked = grpc_dns_lookup_ares_locked;
   grpc_dns_lookup_ares_locked = test_dns_lookup_ares_locked;
@@ -330,10 +331,7 @@ int main(int argc, char** argv) {
   grpc_set_resolver_impl(&test_resolver);
 
   test_cooldown();
-  {
-    grpc_core::ExecCtx exec_ctx;
-    GRPC_COMBINER_UNREF(g_combiner, "test");
-  }
+
   grpc_shutdown_blocking();
   GPR_ASSERT(g_all_callbacks_invoked);
   return 0;
index 12d5d18..107ba1f 100644 (file)
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/memory.h"
-#include "src/core/lib/iomgr/combiner.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "test/core/util/test_config.h"
 
-static grpc_core::Combiner* g_combiner;
+static std::shared_ptr<grpc_core::WorkSerializer>* g_work_serializer;
 
 class TestResultHandler : public grpc_core::Resolver::ResultHandler {
   void ReturnResult(grpc_core::Resolver::Result /*result*/) override {}
@@ -44,7 +44,7 @@ static void test_succeeds(grpc_core::ResolverFactory* factory,
   GPR_ASSERT(uri);
   grpc_core::ResolverArgs args;
   args.uri = uri;
-  args.combiner = g_combiner;
+  args.work_serializer = *g_work_serializer;
   args.result_handler = absl::make_unique<TestResultHandler>();
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
       factory->CreateResolver(std::move(args));
@@ -61,7 +61,7 @@ static void test_fails(grpc_core::ResolverFactory* factory,
   GPR_ASSERT(uri);
   grpc_core::ResolverArgs args;
   args.uri = uri;
-  args.combiner = g_combiner;
+  args.work_serializer = *g_work_serializer;
   args.result_handler = absl::make_unique<TestResultHandler>();
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
       factory->CreateResolver(std::move(args));
@@ -73,7 +73,8 @@ int main(int argc, char** argv) {
   grpc::testing::TestEnvironment env(argc, argv);
   grpc_init();
 
-  g_combiner = grpc_combiner_create();
+  auto work_serializer = std::make_shared<grpc_core::WorkSerializer>();
+  g_work_serializer = &work_serializer;
 
   grpc_core::ResolverFactory* dns =
       grpc_core::ResolverRegistry::LookupResolverFactory("dns");
@@ -89,10 +90,6 @@ int main(int argc, char** argv) {
   } else {
     test_succeeds(dns, "dns://8.8.8.8/8.8.8.8:8888");
   }
-  {
-    grpc_core::ExecCtx exec_ctx;
-    GRPC_COMBINER_UNREF(g_combiner, "test");
-  }
   grpc_shutdown();
 
   return 0;
index c9b5828..fb1e3e2 100644 (file)
@@ -28,7 +28,7 @@
 #include "src/core/ext/filters/client_channel/server_address.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/iomgr/combiner.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "src/core/lib/security/credentials/fake/fake_credentials.h"
 
 #include "test/core/util/test_config.h"
@@ -63,7 +63,7 @@ class ResultHandler : public grpc_core::Resolver::ResultHandler {
 };
 
 static grpc_core::OrphanablePtr<grpc_core::Resolver> build_fake_resolver(
-    grpc_core::Combiner* combiner,
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer,
     grpc_core::FakeResolverResponseGenerator* response_generator,
     std::unique_ptr<grpc_core::Resolver::ResultHandler> result_handler) {
   grpc_core::ResolverFactory* factory =
@@ -74,7 +74,7 @@ static grpc_core::OrphanablePtr<grpc_core::Resolver> build_fake_resolver(
   grpc_channel_args channel_args = {1, &generator_arg};
   grpc_core::ResolverArgs args;
   args.args = &channel_args;
-  args.combiner = combiner;
+  args.work_serializer = std::move(work_serializer);
   args.result_handler = std::move(result_handler);
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
       factory->CreateResolver(std::move(args));
@@ -94,7 +94,7 @@ static grpc_core::Resolver::Result create_new_resolver_result() {
     grpc_uri* uri = grpc_uri_parse(uri_string, true);
     grpc_resolved_address address;
     GPR_ASSERT(grpc_parse_uri(uri, &address));
-    grpc_core::InlinedVector<grpc_arg, 2> args_to_add;
+    absl::InlinedVector<grpc_arg, 2> args_to_add;
     result.addresses.emplace_back(
         address.addr, address.len,
         grpc_channel_args_copy_and_add(nullptr, nullptr, 0));
@@ -107,14 +107,15 @@ static grpc_core::Resolver::Result create_new_resolver_result() {
 
 static void test_fake_resolver() {
   grpc_core::ExecCtx exec_ctx;
-  grpc_core::Combiner* combiner = grpc_combiner_create();
+  std::shared_ptr<grpc_core::WorkSerializer> work_serializer =
+      std::make_shared<grpc_core::WorkSerializer>();
   // Create resolver.
   ResultHandler* result_handler = new ResultHandler();
   grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator>
       response_generator =
           grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver = build_fake_resolver(
-      combiner, response_generator.get(),
+      work_serializer, response_generator.get(),
       std::unique_ptr<grpc_core::Resolver::ResultHandler>(result_handler));
   GPR_ASSERT(resolver.get() != nullptr);
   resolver->StartLocked();
@@ -195,7 +196,6 @@ static void test_fake_resolver() {
              nullptr);
   // Clean up.
   resolver.reset();
-  GRPC_COMBINER_UNREF(combiner, "test_fake_resolver");
 }
 
 int main(int argc, char** argv) {
index a6999f6..ef6a7c7 100644 (file)
 
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
 #include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/iomgr/combiner.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 
 #include "test/core/util/test_config.h"
 
-static grpc_core::Combiner* g_combiner;
+static std::shared_ptr<grpc_core::WorkSerializer>* g_work_serializer;
 
 class ResultHandler : public grpc_core::Resolver::ResultHandler {
  public:
@@ -46,7 +46,7 @@ static void test_succeeds(grpc_core::ResolverFactory* factory,
   GPR_ASSERT(uri);
   grpc_core::ResolverArgs args;
   args.uri = uri;
-  args.combiner = g_combiner;
+  args.work_serializer = *g_work_serializer;
   args.result_handler = absl::make_unique<ResultHandler>();
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
       factory->CreateResolver(std::move(args));
@@ -67,7 +67,7 @@ static void test_fails(grpc_core::ResolverFactory* factory,
   GPR_ASSERT(uri);
   grpc_core::ResolverArgs args;
   args.uri = uri;
-  args.combiner = g_combiner;
+  args.work_serializer = *g_work_serializer;
   args.result_handler = absl::make_unique<ResultHandler>();
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
       factory->CreateResolver(std::move(args));
@@ -79,7 +79,8 @@ int main(int argc, char** argv) {
   grpc::testing::TestEnvironment env(argc, argv);
   grpc_init();
 
-  g_combiner = grpc_combiner_create();
+  auto work_serializer = std::make_shared<grpc_core::WorkSerializer>();
+  g_work_serializer = &work_serializer;
 
   grpc_core::ResolverFactory* ipv4 =
       grpc_core::ResolverRegistry::LookupResolverFactory("ipv4");
@@ -100,10 +101,6 @@ int main(int argc, char** argv) {
   test_fails(ipv6, "ipv6:[::]:123456");
   test_fails(ipv6, "ipv6:www.google.com");
 
-  {
-    grpc_core::ExecCtx exec_ctx;
-    GRPC_COMBINER_UNREF(g_combiner, "test");
-  }
   grpc_shutdown();
 
   return 0;
index 5cdb513..07c171a 100644 (file)
@@ -25,6 +25,7 @@
 #include <grpc/grpc.h>
 #include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
 #include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/filters/client_channel/service_config_parser.h"
 #include "src/core/ext/filters/message_size/message_size_filter.h"
 #include "src/core/lib/gpr/string.h"
 #include "test/core/util/port.h"
@@ -33,7 +34,7 @@
 namespace grpc_core {
 namespace testing {
 
-class TestParsedConfig1 : public ServiceConfig::ParsedConfig {
+class TestParsedConfig1 : public ServiceConfigParser::ParsedConfig {
  public:
   TestParsedConfig1(int value) : value_(value) {}
 
@@ -43,9 +44,9 @@ class TestParsedConfig1 : public ServiceConfig::ParsedConfig {
   int value_;
 };
 
-class TestParser1 : public ServiceConfig::Parser {
+class TestParser1 : public ServiceConfigParser::Parser {
  public:
-  std::unique_ptr<ServiceConfig::ParsedConfig> ParseGlobalParams(
+  std::unique_ptr<ServiceConfigParser::ParsedConfig> ParseGlobalParams(
       const Json& json, grpc_error** error) override {
     GPR_DEBUG_ASSERT(error != nullptr);
     auto it = json.object_value().find("global_param");
@@ -75,9 +76,9 @@ class TestParser1 : public ServiceConfig::Parser {
   }
 };
 
-class TestParser2 : public ServiceConfig::Parser {
+class TestParser2 : public ServiceConfigParser::Parser {
  public:
-  std::unique_ptr<ServiceConfig::ParsedConfig> ParsePerMethodParams(
+  std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
       const Json& json, grpc_error** error) override {
     GPR_DEBUG_ASSERT(error != nullptr);
     auto it = json.object_value().find("method_param");
@@ -108,16 +109,16 @@ class TestParser2 : public ServiceConfig::Parser {
 };
 
 // This parser always adds errors
-class ErrorParser : public ServiceConfig::Parser {
+class ErrorParser : public ServiceConfigParser::Parser {
  public:
-  std::unique_ptr<ServiceConfig::ParsedConfig> ParsePerMethodParams(
+  std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
       const Json& /*json*/, grpc_error** error) override {
     GPR_DEBUG_ASSERT(error != nullptr);
     *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(MethodError());
     return nullptr;
   }
 
-  std::unique_ptr<ServiceConfig::ParsedConfig> ParseGlobalParams(
+  std::unique_ptr<ServiceConfigParser::ParsedConfig> ParseGlobalParams(
       const Json& /*json*/, grpc_error** error) override {
     GPR_DEBUG_ASSERT(error != nullptr);
     *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(GlobalError());
@@ -139,12 +140,14 @@ void VerifyRegexMatch(grpc_error* error, const std::regex& regex) {
 class ServiceConfigTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    ServiceConfig::Shutdown();
-    ServiceConfig::Init();
-    EXPECT_EQ(ServiceConfig::RegisterParser(absl::make_unique<TestParser1>()),
-              0);
-    EXPECT_EQ(ServiceConfig::RegisterParser(absl::make_unique<TestParser2>()),
-              1);
+    ServiceConfigParser::Shutdown();
+    ServiceConfigParser::Init();
+    EXPECT_EQ(
+        ServiceConfigParser::RegisterParser(absl::make_unique<TestParser1>()),
+        0);
+    EXPECT_EQ(
+        ServiceConfigParser::RegisterParser(absl::make_unique<TestParser2>()),
+        1);
   }
 };
 
@@ -375,12 +378,14 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) {
 class ErroredParsersScopingTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    ServiceConfig::Shutdown();
-    ServiceConfig::Init();
-    EXPECT_EQ(ServiceConfig::RegisterParser(absl::make_unique<ErrorParser>()),
-              0);
-    EXPECT_EQ(ServiceConfig::RegisterParser(absl::make_unique<ErrorParser>()),
-              1);
+    ServiceConfigParser::Shutdown();
+    ServiceConfigParser::Init();
+    EXPECT_EQ(
+        ServiceConfigParser::RegisterParser(absl::make_unique<ErrorParser>()),
+        0);
+    EXPECT_EQ(
+        ServiceConfigParser::RegisterParser(absl::make_unique<ErrorParser>()),
+        1);
   }
 };
 
@@ -411,10 +416,10 @@ TEST_F(ErroredParsersScopingTest, MethodParams) {
 class ClientChannelParserTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    ServiceConfig::Shutdown();
-    ServiceConfig::Init();
+    ServiceConfigParser::Shutdown();
+    ServiceConfigParser::Init();
     EXPECT_EQ(
-        ServiceConfig::RegisterParser(
+        ServiceConfigParser::RegisterParser(
             absl::make_unique<internal::ClientChannelServiceConfigParser>()),
         0);
   }
@@ -938,11 +943,11 @@ TEST_F(ClientChannelParserTest, InvalidHealthCheckMultipleEntries) {
 class MessageSizeParserTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    ServiceConfig::Shutdown();
-    ServiceConfig::Init();
-    EXPECT_EQ(
-        ServiceConfig::RegisterParser(absl::make_unique<MessageSizeParser>()),
-        0);
+    ServiceConfigParser::Shutdown();
+    ServiceConfigParser::Init();
+    EXPECT_EQ(ServiceConfigParser::RegisterParser(
+                  absl::make_unique<MessageSizeParser>()),
+              0);
   }
 };
 
index e2abf2d..9615582 100644 (file)
@@ -196,6 +196,34 @@ static void test_bad_decompression_data_crc(void) {
   grpc_slice_buffer_destroy(&output);
 }
 
+static void test_bad_decompression_data_missing_trailer(void) {
+  grpc_slice_buffer input;
+  grpc_slice_buffer decompressed;
+  grpc_slice_buffer garbage;
+  grpc_slice_buffer output;
+
+  grpc_slice_buffer_init(&input);
+  grpc_slice_buffer_init(&decompressed);
+  grpc_slice_buffer_init(&garbage);
+  grpc_slice_buffer_init(&output);
+  grpc_slice_buffer_add(&input, create_test_value(ONE_MB_A));
+
+  grpc_core::ExecCtx exec_ctx;
+  /* compress it */
+  grpc_msg_compress(GRPC_MESSAGE_COMPRESS_GZIP, &input, &decompressed);
+  GPR_ASSERT(decompressed.length > 8);
+  /* Remove the footer from the decompressed message */
+  grpc_slice_buffer_trim_end(&decompressed, 8, &garbage);
+  /* try (and fail) to decompress the compressed buffer without the footer */
+  GPR_ASSERT(0 == grpc_msg_decompress(GRPC_MESSAGE_COMPRESS_GZIP, &decompressed,
+                                      &output));
+
+  grpc_slice_buffer_destroy(&input);
+  grpc_slice_buffer_destroy(&decompressed);
+  grpc_slice_buffer_destroy(&garbage);
+  grpc_slice_buffer_destroy(&output);
+}
+
 static void test_bad_decompression_data_trailing_garbage(void) {
   grpc_slice_buffer input;
   grpc_slice_buffer output;
@@ -315,6 +343,7 @@ int main(int argc, char** argv) {
 
   test_tiny_data_compress();
   test_bad_decompression_data_crc();
+  test_bad_decompression_data_missing_trailer();
   test_bad_decompression_data_stream();
   test_bad_decompression_data_trailing_garbage();
   test_bad_compression_algorithm();
index 3dac90e..e05cf4c 100644 (file)
@@ -41,7 +41,7 @@
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_tcp_server.h"
 
-#define HTTP1_RESP                           \
+#define HTTP1_RESP_400                       \
   "HTTP/1.0 400 Bad Request\n"               \
   "Content-Type: text/html; charset=UTF-8\n" \
   "Content-Length: 0\n"                      \
@@ -71,7 +71,7 @@
 #define SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD (size_t)200
 
 struct rpc_state {
-  grpc_core::UniquePtr<char> target;
+  std::string target;
   grpc_completion_queue* cq;
   grpc_channel* channel;
   grpc_call* call;
@@ -165,9 +165,9 @@ static void start_rpc(int target_port, grpc_status_code expected_status,
 
   state.cq = grpc_completion_queue_create_for_next(nullptr);
   cqv = cq_verifier_create(state.cq);
-  grpc_core::JoinHostPort(&state.target, "127.0.0.1", target_port);
+  state.target = grpc_core::JoinHostPort("127.0.0.1", target_port);
   state.channel =
-      grpc_insecure_channel_create(state.target.get(), nullptr, nullptr);
+      grpc_insecure_channel_create(state.target.c_str(), nullptr, nullptr);
   grpc_slice host = grpc_slice_from_static_string("localhost");
   state.call = grpc_channel_create_call(
       state.channel, nullptr, GRPC_PROPAGATE_DEFAULTS, state.cq,
@@ -231,7 +231,7 @@ static void cleanup_rpc() {
   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
   grpc_completion_queue_destroy(state.cq);
   grpc_channel_destroy(state.channel);
-  state.target.reset();
+  state.target.clear();
 }
 
 typedef struct {
@@ -309,40 +309,41 @@ int main(int argc, char** argv) {
   grpc_init();
 
   /* status defined in hpack static table */
-  run_test(HTTP2_RESP(204), sizeof(HTTP2_RESP(204)) - 1, GRPC_STATUS_CANCELLED,
+  run_test(HTTP2_RESP(204), sizeof(HTTP2_RESP(204)) - 1, GRPC_STATUS_UNKNOWN,
            HTTP2_DETAIL_MSG(204));
-
-  run_test(HTTP2_RESP(206), sizeof(HTTP2_RESP(206)) - 1, GRPC_STATUS_CANCELLED,
+  run_test(HTTP2_RESP(206), sizeof(HTTP2_RESP(206)) - 1, GRPC_STATUS_UNKNOWN,
            HTTP2_DETAIL_MSG(206));
-
-  run_test(HTTP2_RESP(304), sizeof(HTTP2_RESP(304)) - 1, GRPC_STATUS_CANCELLED,
+  run_test(HTTP2_RESP(304), sizeof(HTTP2_RESP(304)) - 1, GRPC_STATUS_UNKNOWN,
            HTTP2_DETAIL_MSG(304));
-
-  run_test(HTTP2_RESP(400), sizeof(HTTP2_RESP(400)) - 1, GRPC_STATUS_CANCELLED,
+  run_test(HTTP2_RESP(400), sizeof(HTTP2_RESP(400)) - 1, GRPC_STATUS_INTERNAL,
            HTTP2_DETAIL_MSG(400));
-
-  run_test(HTTP2_RESP(404), sizeof(HTTP2_RESP(404)) - 1, GRPC_STATUS_CANCELLED,
-           HTTP2_DETAIL_MSG(404));
-
-  run_test(HTTP2_RESP(500), sizeof(HTTP2_RESP(500)) - 1, GRPC_STATUS_CANCELLED,
+  run_test(HTTP2_RESP(404), sizeof(HTTP2_RESP(404)) - 1,
+           GRPC_STATUS_UNIMPLEMENTED, HTTP2_DETAIL_MSG(404));
+  run_test(HTTP2_RESP(500), sizeof(HTTP2_RESP(500)) - 1, GRPC_STATUS_UNKNOWN,
            HTTP2_DETAIL_MSG(500));
 
   /* status not defined in hpack static table */
-  run_test(HTTP2_RESP(401), sizeof(HTTP2_RESP(401)) - 1, GRPC_STATUS_CANCELLED,
-           HTTP2_DETAIL_MSG(401));
-
-  run_test(HTTP2_RESP(403), sizeof(HTTP2_RESP(403)) - 1, GRPC_STATUS_CANCELLED,
-           HTTP2_DETAIL_MSG(403));
-
-  run_test(HTTP2_RESP(502), sizeof(HTTP2_RESP(502)) - 1, GRPC_STATUS_CANCELLED,
-           HTTP2_DETAIL_MSG(502));
+  run_test(HTTP2_RESP(401), sizeof(HTTP2_RESP(401)) - 1,
+           GRPC_STATUS_UNAUTHENTICATED, HTTP2_DETAIL_MSG(401));
+  run_test(HTTP2_RESP(403), sizeof(HTTP2_RESP(403)) - 1,
+           GRPC_STATUS_PERMISSION_DENIED, HTTP2_DETAIL_MSG(403));
+  run_test(HTTP2_RESP(429), sizeof(HTTP2_RESP(429)) - 1,
+           GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(429));
+  run_test(HTTP2_RESP(499), sizeof(HTTP2_RESP(499)) - 1, GRPC_STATUS_UNKNOWN,
+           HTTP2_DETAIL_MSG(499));
+  run_test(HTTP2_RESP(502), sizeof(HTTP2_RESP(502)) - 1,
+           GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(502));
+  run_test(HTTP2_RESP(503), sizeof(HTTP2_RESP(503)) - 1,
+           GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(503));
+  run_test(HTTP2_RESP(504), sizeof(HTTP2_RESP(504)) - 1,
+           GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(504));
 
   /* unparseable response */
   run_test(UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1, GRPC_STATUS_UNKNOWN,
            nullptr);
 
   /* http1 response */
-  run_test(HTTP1_RESP, sizeof(HTTP1_RESP) - 1, GRPC_STATUS_UNAVAILABLE,
+  run_test(HTTP1_RESP_400, sizeof(HTTP1_RESP_400) - 1, GRPC_STATUS_INTERNAL,
            HTTP1_DETAIL_MSG);
 
   grpc_shutdown();
index 3bb6d2e..bbbebe9 100644 (file)
@@ -77,10 +77,9 @@ static void run_test(bool wait_for_ready, bool use_service_config) {
 
   /* create a call, channel to a port which will refuse connection */
   int port = grpc_pick_unused_port_or_die();
-  grpc_core::UniquePtr<char> addr;
-  grpc_core::JoinHostPort(&addr, "127.0.0.1", port);
-  gpr_log(GPR_INFO, "server: %s", addr.get());
-  chan = grpc_insecure_channel_create(addr.get(), args, nullptr);
+  std::string addr = grpc_core::JoinHostPort("127.0.0.1", port);
+  gpr_log(GPR_INFO, "server: %s", addr.c_str());
+  chan = grpc_insecure_channel_create(addr.c_str(), args, nullptr);
   grpc_slice host = grpc_slice_from_static_string("nonexistant");
   gpr_timespec deadline = grpc_timeout_seconds_to_deadline(2);
   call =
index 3d45b6d..6030b49 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
+#include <string>
+#include <vector>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/byte_buffer.h>
 #include <grpc/byte_buffer_reader.h>
 #include <grpc/support/alloc.h>
@@ -52,6 +58,7 @@ typedef struct expectation {
   int line;
   grpc_completion_type type;
   void* tag;
+  bool check_success;
   int success;
 } expectation;
 
@@ -170,21 +177,19 @@ int byte_buffer_eq_string(grpc_byte_buffer* bb, const char* str) {
 
 static bool is_probably_integer(void* p) { return ((uintptr_t)p) < 1000000; }
 
-static void expectation_to_strvec(gpr_strvec* buf, expectation* e) {
-  char* tmp;
+namespace {
 
-  if (is_probably_integer(e->tag)) {
-    gpr_asprintf(&tmp, "tag(%" PRIdPTR ") ", (intptr_t)e->tag);
+std::string ExpectationString(const expectation& e) {
+  std::string out;
+  if (is_probably_integer(e.tag)) {
+    out = absl::StrFormat("tag(%" PRIdPTR ") ", (intptr_t)e.tag);
   } else {
-    gpr_asprintf(&tmp, "%p ", e->tag);
+    out = absl::StrFormat("%p ", e.tag);
   }
-  gpr_strvec_add(buf, tmp);
-
-  switch (e->type) {
+  switch (e.type) {
     case GRPC_OP_COMPLETE:
-      gpr_asprintf(&tmp, "GRPC_OP_COMPLETE success=%d %s:%d", e->success,
-                   e->file, e->line);
-      gpr_strvec_add(buf, tmp);
+      absl::StrAppendFormat(&out, "GRPC_OP_COMPLETE success=%d %s:%d",
+                            e.success, e.file, e.line);
       break;
     case GRPC_QUEUE_TIMEOUT:
     case GRPC_QUEUE_SHUTDOWN:
@@ -192,27 +197,22 @@ static void expectation_to_strvec(gpr_strvec* buf, expectation* e) {
       abort();
       break;
   }
+  return out;
 }
 
-static void expectations_to_strvec(gpr_strvec* buf, cq_verifier* v) {
-  expectation* e;
-
-  for (e = v->first_expectation; e != nullptr; e = e->next) {
-    expectation_to_strvec(buf, e);
-    gpr_strvec_add(buf, gpr_strdup("\n"));
+std::string ExpectationsString(const cq_verifier& v) {
+  std::vector<std::string> expectations;
+  for (expectation* e = v.first_expectation; e != nullptr; e = e->next) {
+    expectations.push_back(ExpectationString(*e));
   }
+  return absl::StrJoin(expectations, "\n");
 }
 
+}  // namespace
+
 static void fail_no_event_received(cq_verifier* v) {
-  gpr_strvec buf;
-  char* msg;
-  gpr_strvec_init(&buf);
-  gpr_strvec_add(&buf, gpr_strdup("no event received, but expected:\n"));
-  expectations_to_strvec(&buf, v);
-  msg = gpr_strvec_flatten(&buf, nullptr);
-  gpr_log(GPR_ERROR, "%s", msg);
-  gpr_strvec_destroy(&buf);
-  gpr_free(msg);
+  gpr_log(GPR_ERROR, "no event received, but expected:%s",
+          ExpectationsString(*v).c_str());
   abort();
 }
 
@@ -220,14 +220,9 @@ static void verify_matches(expectation* e, grpc_event* ev) {
   GPR_ASSERT(e->type == ev->type);
   switch (e->type) {
     case GRPC_OP_COMPLETE:
-      if (e->success != ev->success) {
-        gpr_strvec expected;
-        gpr_strvec_init(&expected);
-        expectation_to_strvec(&expected, e);
-        char* s = gpr_strvec_flatten(&expected, nullptr);
-        gpr_strvec_destroy(&expected);
-        gpr_log(GPR_ERROR, "actual success does not match expected: %s", s);
-        gpr_free(s);
+      if (e->check_success && e->success != ev->success) {
+        gpr_log(GPR_ERROR, "actual success does not match expected: %s",
+                ExpectationString(*e).c_str());
         abort();
       }
       break;
@@ -263,16 +258,9 @@ void cq_verify(cq_verifier* v) {
       prev = e;
     }
     if (e == nullptr) {
-      char* s = grpc_event_string(&ev);
-      gpr_log(GPR_ERROR, "cq returned unexpected event: %s", s);
-      gpr_free(s);
-      gpr_strvec expectations;
-      gpr_strvec_init(&expectations);
-      expectations_to_strvec(&expectations, v);
-      s = gpr_strvec_flatten(&expectations, nullptr);
-      gpr_strvec_destroy(&expectations);
-      gpr_log(GPR_ERROR, "expected tags:\n%s", s);
-      gpr_free(s);
+      gpr_log(GPR_ERROR, "cq returned unexpected event: %s",
+              grpc_event_string(&ev).c_str());
+      gpr_log(GPR_ERROR, "expected tags:\n%s", ExpectationsString(*v).c_str());
       abort();
     }
   }
@@ -289,9 +277,8 @@ void cq_verify_empty_timeout(cq_verifier* v, int timeout_sec) {
 
   ev = grpc_completion_queue_next(v->cq, deadline, nullptr);
   if (ev.type != GRPC_QUEUE_TIMEOUT) {
-    char* s = grpc_event_string(&ev);
-    gpr_log(GPR_ERROR, "unexpected event (expected nothing): %s", s);
-    gpr_free(s);
+    gpr_log(GPR_ERROR, "unexpected event (expected nothing): %s",
+            grpc_event_string(&ev).c_str());
     abort();
   }
 }
@@ -299,12 +286,14 @@ void cq_verify_empty_timeout(cq_verifier* v, int timeout_sec) {
 void cq_verify_empty(cq_verifier* v) { cq_verify_empty_timeout(v, 1); }
 
 static void add(cq_verifier* v, const char* file, int line,
-                grpc_completion_type type, void* tag, bool success) {
+                grpc_completion_type type, void* tag, bool check_success,
+                bool success) {
   expectation* e = static_cast<expectation*>(gpr_malloc(sizeof(expectation)));
   e->type = type;
   e->file = file;
   e->line = line;
   e->tag = tag;
+  e->check_success = check_success;
   e->success = success;
   e->next = v->first_expectation;
   v->first_expectation = e;
@@ -312,5 +301,10 @@ static void add(cq_verifier* v, const char* file, int line,
 
 void cq_expect_completion(cq_verifier* v, const char* file, int line, void* tag,
                           bool success) {
-  add(v, file, line, GRPC_OP_COMPLETE, tag, success);
+  add(v, file, line, GRPC_OP_COMPLETE, tag, true, success);
+}
+
+void cq_expect_completion_any_status(cq_verifier* v, const char* file, int line,
+                                     void* tag) {
+  add(v, file, line, GRPC_OP_COMPLETE, tag, false, false);
 }
index 959f849..f5f2a9f 100644 (file)
@@ -49,8 +49,12 @@ void cq_verify_empty_timeout(cq_verifier* v, int timeout_sec);
    the event. */
 void cq_expect_completion(cq_verifier* v, const char* file, int line, void* tag,
                           bool success);
+void cq_expect_completion_any_status(cq_verifier* v, const char* file, int line,
+                                     void* tag);
 #define CQ_EXPECT_COMPLETION(v, tag, success) \
   cq_expect_completion(v, __FILE__, __LINE__, tag, success)
+#define CQ_EXPECT_COMPLETION_ANY_STATUS(v, tag) \
+  cq_expect_completion_any_status(v, __FILE__, __LINE__, tag)
 
 int byte_buffer_eq_slice(grpc_byte_buffer* bb, grpc_slice b);
 int byte_buffer_eq_string(grpc_byte_buffer* byte_buffer, const char* string);
index 303f3a6..c679ffa 100644 (file)
 #ifndef GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H
 #define GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H
 
+// These credentials are hardcoded as char arrays and are hence considered to
+// be deprecated. Please consider using credentials in
+// "src/core/tsi/test_creds" instead.
+
 extern const char test_root_cert[];
 extern const char test_server1_cert[];
 extern const char test_server1_key[];
index 9f0f981..affe6d9 100644 (file)
 
 #include <string.h>
 
+#include <vector>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -51,8 +58,6 @@ static void drain_cq(grpc_completion_queue* cq) {
   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
 }
 
-static void do_nothing(void* /*ignored*/) {}
-
 static void log_resolved_addrs(const char* label, const char* hostname) {
   grpc_resolved_addresses* res = nullptr;
   grpc_error* error = grpc_blocking_resolve_address(hostname, "80", &res);
@@ -97,8 +102,7 @@ void test_connect(const char* server_host, const char* client_host, int port,
     picked_port = 1;
   }
 
-  grpc_core::UniquePtr<char> server_hostport;
-  grpc_core::JoinHostPort(&server_hostport, server_host, port);
+  std::string server_hostport = grpc_core::JoinHostPort(server_host, port);
 
   grpc_metadata_array_init(&initial_metadata_recv);
   grpc_metadata_array_init(&trailing_metadata_recv);
@@ -110,7 +114,7 @@ void test_connect(const char* server_host, const char* client_host, int port,
   server = grpc_server_create(nullptr, nullptr);
   grpc_server_register_completion_queue(server, cq, nullptr);
   GPR_ASSERT((got_port = grpc_server_add_insecure_http2_port(
-                  server, server_hostport.get())) > 0);
+                  server, server_hostport.c_str())) > 0);
   if (port == 0) {
     port = got_port;
   } else {
@@ -120,41 +124,25 @@ void test_connect(const char* server_host, const char* client_host, int port,
   cqv = cq_verifier_create(cq);
 
   /* Create client. */
-  grpc_core::UniquePtr<char> client_hostport;
+  std::string client_hostport;
   if (client_host[0] == 'i') {
     /* for ipv4:/ipv6: addresses, concatenate the port to each of the parts */
-    size_t i;
-    grpc_slice uri_slice;
-    grpc_slice_buffer uri_parts;
-    char** hosts_with_port;
-
-    uri_slice = grpc_slice_new(const_cast<char*>(client_host),
-                               strlen(client_host), do_nothing);
-    grpc_slice_buffer_init(&uri_parts);
-    grpc_slice_split(uri_slice, ",", &uri_parts);
-    hosts_with_port =
-        static_cast<char**>(gpr_malloc(sizeof(char*) * uri_parts.count));
-    for (i = 0; i < uri_parts.count; i++) {
-      char* uri_part_str = grpc_slice_to_c_string(uri_parts.slices[i]);
-      gpr_asprintf(&hosts_with_port[i], "%s:%d", uri_part_str, port);
-      gpr_free(uri_part_str);
-    }
-    client_hostport.reset(gpr_strjoin_sep((const char**)hosts_with_port,
-                                          uri_parts.count, ",", nullptr));
-    for (i = 0; i < uri_parts.count; i++) {
-      gpr_free(hosts_with_port[i]);
+    std::vector<absl::string_view> uri_parts =
+        absl::StrSplit(client_host, ",", absl::SkipEmpty());
+    std::vector<std::string> hosts_with_port;
+    hosts_with_port.reserve(uri_parts.size());
+    for (const absl::string_view& uri_part : uri_parts) {
+      hosts_with_port.push_back(absl::StrFormat("%s:%d", uri_part, port));
     }
-    gpr_free(hosts_with_port);
-    grpc_slice_buffer_destroy(&uri_parts);
-    grpc_slice_unref(uri_slice);
+    client_hostport = absl::StrJoin(hosts_with_port, ",");
   } else {
-    grpc_core::JoinHostPort(&client_hostport, client_host, port);
+    client_hostport = grpc_core::JoinHostPort(client_host, port);
   }
   client =
-      grpc_insecure_channel_create(client_hostport.get(), nullptr, nullptr);
+      grpc_insecure_channel_create(client_hostport.c_str(), nullptr, nullptr);
 
   gpr_log(GPR_INFO, "Testing with server=%s client=%s (expecting %s)",
-          server_hostport.get(), client_hostport.get(),
+          server_hostport.c_str(), client_hostport.c_str(),
           expect_ok ? "success" : "failure");
   log_resolved_addrs("server resolved addr", server_host);
   log_resolved_addrs("client resolved addr", client_host);
index e01e6ad..f5c9c5c 100644 (file)
@@ -55,6 +55,8 @@ extern void cancel_with_status(grpc_end2end_test_config config);
 extern void cancel_with_status_pre_init(void);
 extern void channelz(grpc_end2end_test_config config);
 extern void channelz_pre_init(void);
+extern void client_streaming(grpc_end2end_test_config config);
+extern void client_streaming_pre_init(void);
 extern void compressed_payload(grpc_end2end_test_config config);
 extern void compressed_payload_pre_init(void);
 extern void connectivity(grpc_end2end_test_config config);
@@ -200,6 +202,7 @@ void grpc_end2end_tests_pre_init(void) {
   cancel_in_a_vacuum_pre_init();
   cancel_with_status_pre_init();
   channelz_pre_init();
+  client_streaming_pre_init();
   compressed_payload_pre_init();
   connectivity_pre_init();
   default_host_pre_init();
@@ -286,6 +289,7 @@ void grpc_end2end_tests(int argc, char **argv,
     cancel_in_a_vacuum(config);
     cancel_with_status(config);
     channelz(config);
+    client_streaming(config);
     compressed_payload(config);
     connectivity(config);
     default_host(config);
@@ -406,6 +410,10 @@ void grpc_end2end_tests(int argc, char **argv,
       channelz(config);
       continue;
     }
+    if (0 == strcmp("client_streaming", argv[i])) {
+      client_streaming(config);
+      continue;
+    }
     if (0 == strcmp("compressed_payload", argv[i])) {
       compressed_payload(config);
       continue;
index 76fb046..3d81b61 100644 (file)
@@ -57,6 +57,8 @@ extern void cancel_with_status(grpc_end2end_test_config config);
 extern void cancel_with_status_pre_init(void);
 extern void channelz(grpc_end2end_test_config config);
 extern void channelz_pre_init(void);
+extern void client_streaming(grpc_end2end_test_config config);
+extern void client_streaming_pre_init(void);
 extern void compressed_payload(grpc_end2end_test_config config);
 extern void compressed_payload_pre_init(void);
 extern void connectivity(grpc_end2end_test_config config);
@@ -203,6 +205,7 @@ void grpc_end2end_tests_pre_init(void) {
   cancel_in_a_vacuum_pre_init();
   cancel_with_status_pre_init();
   channelz_pre_init();
+  client_streaming_pre_init();
   compressed_payload_pre_init();
   connectivity_pre_init();
   default_host_pre_init();
@@ -290,6 +293,7 @@ void grpc_end2end_tests(int argc, char **argv,
     cancel_in_a_vacuum(config);
     cancel_with_status(config);
     channelz(config);
+    client_streaming(config);
     compressed_payload(config);
     connectivity(config);
     default_host(config);
@@ -414,6 +418,10 @@ void grpc_end2end_tests(int argc, char **argv,
       channelz(config);
       continue;
     }
+    if (0 == strcmp("client_streaming", argv[i])) {
+      client_streaming(config);
+      continue;
+    }
     if (0 == strcmp("compressed_payload", argv[i])) {
       compressed_payload(config);
       continue;
index afabae1..2e84296 100644 (file)
@@ -36,7 +36,7 @@
 #include "test/core/util/test_config.h"
 
 struct fullstack_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
 };
 
 static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
@@ -45,7 +45,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
   int port = grpc_pick_unused_port_or_die();
   fullstack_fixture_data* ffd = new fullstack_fixture_data();
   memset(&f, 0, sizeof(f));
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
@@ -68,8 +68,8 @@ void chttp2_init_client_fullstack(grpc_end2end_test_fixture* f,
       static_cast<fullstack_fixture_data*>(f->fixture_data);
   grpc_arg arg = make_census_enable_arg();
   client_args = grpc_channel_args_copy_and_add(client_args, &arg, 1);
-  f->client =
-      grpc_insecure_channel_create(ffd->localaddr.get(), client_args, nullptr);
+  f->client = grpc_insecure_channel_create(ffd->localaddr.c_str(), client_args,
+                                           nullptr);
   GPR_ASSERT(f->client);
   {
     grpc_core::ExecCtx exec_ctx;
@@ -93,7 +93,7 @@ void chttp2_init_server_fullstack(grpc_end2end_test_fixture* f,
   }
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
   GPR_ASSERT(
-      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.get()));
+      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.c_str()));
   grpc_server_start(f->server);
 }
 
index a0a7c29..9bc359a 100644 (file)
@@ -41,7 +41,7 @@ struct fullstack_compression_fixture_data {
     grpc_channel_args_destroy(client_args_compression);
     grpc_channel_args_destroy(server_args_compression);
   }
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
   grpc_channel_args* client_args_compression = nullptr;
   grpc_channel_args* server_args_compression = nullptr;
 };
@@ -52,7 +52,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack_compression(
   int port = grpc_pick_unused_port_or_die();
   fullstack_compression_fixture_data* ffd =
       new fullstack_compression_fixture_data();
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
 
   memset(&f, 0, sizeof(f));
   f.fixture_data = ffd;
@@ -74,7 +74,7 @@ void chttp2_init_client_fullstack_compression(grpc_end2end_test_fixture* f,
       grpc_channel_args_set_channel_default_compression_algorithm(
           client_args, GRPC_COMPRESS_GZIP);
   f->client = grpc_insecure_channel_create(
-      ffd->localaddr.get(), ffd->client_args_compression, nullptr);
+      ffd->localaddr.c_str(), ffd->client_args_compression, nullptr);
 }
 
 void chttp2_init_server_fullstack_compression(grpc_end2end_test_fixture* f,
@@ -94,7 +94,7 @@ void chttp2_init_server_fullstack_compression(grpc_end2end_test_fixture* f,
   f->server = grpc_server_create(ffd->server_args_compression, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
   GPR_ASSERT(
-      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.get()));
+      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.c_str()));
   grpc_server_start(f->server);
 }
 
index 5dacbe4..099bf0d 100644 (file)
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gprpp/host_port.h"
 #include "src/core/lib/security/credentials/fake/fake_credentials.h"
-#include "test/core/end2end/data/ssl_test_data.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
 struct fullstack_secure_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
 };
 
 static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
@@ -41,7 +40,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
   int port = grpc_pick_unused_port_or_die();
   fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
   memset(&f, 0, sizeof(f));
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
@@ -64,7 +63,7 @@ static void chttp2_init_client_secure_fullstack(
     grpc_channel_credentials* creds) {
   fullstack_secure_fixture_data* ffd =
       static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
-  f->client = grpc_secure_channel_create(creds, ffd->localaddr.get(),
+  f->client = grpc_secure_channel_create(creds, ffd->localaddr.c_str(),
                                          client_args, nullptr);
   GPR_ASSERT(f->client != nullptr);
   grpc_channel_credentials_release(creds);
@@ -80,8 +79,8 @@ static void chttp2_init_server_secure_fullstack(
   }
   f->server = grpc_server_create(server_args, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
-  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr.get(),
-                                               server_creds));
+  GPR_ASSERT(grpc_server_add_secure_http2_port(
+      f->server, ffd->localaddr.c_str(), server_creds));
   grpc_server_credentials_release(server_creds);
   grpc_server_start(f->server);
 }
index a9807e6..dd5ae5b 100644 (file)
@@ -41,7 +41,7 @@
 #include "test/core/util/test_config.h"
 
 struct fullstack_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
 };
 
 static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
@@ -51,7 +51,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
   fullstack_fixture_data* ffd = new fullstack_fixture_data();
   memset(&f, 0, sizeof(f));
 
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
@@ -64,8 +64,8 @@ void chttp2_init_client_fullstack(grpc_end2end_test_fixture* f,
                                   grpc_channel_args* client_args) {
   fullstack_fixture_data* ffd =
       static_cast<fullstack_fixture_data*>(f->fixture_data);
-  f->client =
-      grpc_insecure_channel_create(ffd->localaddr.get(), client_args, nullptr);
+  f->client = grpc_insecure_channel_create(ffd->localaddr.c_str(), client_args,
+                                           nullptr);
   GPR_ASSERT(f->client);
 }
 
@@ -79,7 +79,7 @@ void chttp2_init_server_fullstack(grpc_end2end_test_fixture* f,
   f->server = grpc_server_create(server_args, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
   GPR_ASSERT(
-      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.get()));
+      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.c_str()));
   grpc_server_start(f->server);
 }
 
index 64fdca7..68cf39a 100644 (file)
@@ -41,7 +41,7 @@
 #include "test/core/util/test_config.h"
 
 struct fullstack_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
 };
 
 static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
@@ -51,7 +51,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
   fullstack_fixture_data* ffd = new fullstack_fixture_data();
   memset(&f, 0, sizeof(f));
 
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
@@ -64,8 +64,8 @@ void chttp2_init_client_fullstack(grpc_end2end_test_fixture* f,
                                   grpc_channel_args* client_args) {
   fullstack_fixture_data* ffd =
       static_cast<fullstack_fixture_data*>(f->fixture_data);
-  f->client =
-      grpc_insecure_channel_create(ffd->localaddr.get(), client_args, nullptr);
+  f->client = grpc_insecure_channel_create(ffd->localaddr.c_str(), client_args,
+                                           nullptr);
   GPR_ASSERT(f->client);
 }
 
@@ -79,7 +79,7 @@ void chttp2_init_server_fullstack(grpc_end2end_test_fixture* f,
   f->server = grpc_server_create(server_args, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
   GPR_ASSERT(
-      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.get()));
+      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.c_str()));
   grpc_server_start(f->server);
 }
 
index d524175..13c1f1f 100644 (file)
@@ -40,7 +40,7 @@ static char* workarounds_arg[GRPC_MAX_WORKAROUND_ID] = {
     const_cast<char*>(GRPC_ARG_WORKAROUND_CRONET_COMPRESSION)};
 
 struct fullstack_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
 };
 
 static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
@@ -49,7 +49,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
   int port = grpc_pick_unused_port_or_die();
   fullstack_fixture_data* ffd = new fullstack_fixture_data();
   memset(&f, 0, sizeof(f));
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
   f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
@@ -60,8 +60,8 @@ void chttp2_init_client_fullstack(grpc_end2end_test_fixture* f,
                                   grpc_channel_args* client_args) {
   fullstack_fixture_data* ffd =
       static_cast<fullstack_fixture_data*>(f->fixture_data);
-  f->client =
-      grpc_insecure_channel_create(ffd->localaddr.get(), client_args, nullptr);
+  f->client = grpc_insecure_channel_create(ffd->localaddr.c_str(), client_args,
+                                           nullptr);
   GPR_ASSERT(f->client);
 }
 
@@ -85,7 +85,7 @@ void chttp2_init_server_fullstack(grpc_end2end_test_fixture* f,
   f->server = grpc_server_create(server_args_new, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
   GPR_ASSERT(
-      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.get()));
+      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.c_str()));
   grpc_server_start(f->server);
   grpc_channel_args_destroy(server_args_new);
 }
index 485c792..16c9128 100644 (file)
@@ -35,7 +35,7 @@
 #include "test/core/util/test_config.h"
 
 struct fullstack_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
 };
 
 static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
@@ -45,7 +45,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
   fullstack_fixture_data* ffd = new fullstack_fixture_data();
   memset(&f, 0, sizeof(f));
 
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
@@ -58,8 +58,8 @@ void chttp2_init_client_fullstack(grpc_end2end_test_fixture* f,
                                   grpc_channel_args* client_args) {
   fullstack_fixture_data* ffd =
       static_cast<fullstack_fixture_data*>(f->fixture_data);
-  f->client =
-      grpc_insecure_channel_create(ffd->localaddr.get(), client_args, nullptr);
+  f->client = grpc_insecure_channel_create(ffd->localaddr.c_str(), client_args,
+                                           nullptr);
   GPR_ASSERT(f->client);
 }
 
@@ -73,7 +73,7 @@ void chttp2_init_server_fullstack(grpc_end2end_test_fixture* f,
   f->server = grpc_server_create(server_args, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
   GPR_ASSERT(
-      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.get()));
+      grpc_server_add_insecure_http2_port(f->server, ffd->localaddr.c_str()));
   grpc_server_start(f->server);
 }
 
index e88042d..949356c 100644 (file)
@@ -39,7 +39,7 @@
 
 struct fullstack_fixture_data {
   ~fullstack_fixture_data() { grpc_end2end_http_proxy_destroy(proxy); }
-  grpc_core::UniquePtr<char> server_addr;
+  std::string server_addr;
   grpc_end2end_http_proxy* proxy = nullptr;
 };
 
@@ -49,7 +49,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
   memset(&f, 0, sizeof(f));
   fullstack_fixture_data* ffd = new fullstack_fixture_data();
   const int server_port = grpc_pick_unused_port_or_die();
-  grpc_core::JoinHostPort(&ffd->server_addr, "localhost", server_port);
+  ffd->server_addr = grpc_core::JoinHostPort("localhost", server_port);
 
   /* Passing client_args to proxy_create for the case of checking for proxy auth
    */
@@ -81,8 +81,8 @@ void chttp2_init_client_fullstack(grpc_end2end_test_fixture* f,
   }
   gpr_setenv("http_proxy", proxy_uri);
   gpr_free(proxy_uri);
-  f->client = grpc_insecure_channel_create(ffd->server_addr.get(), client_args,
-                                           nullptr);
+  f->client = grpc_insecure_channel_create(ffd->server_addr.c_str(),
+                                           client_args, nullptr);
   GPR_ASSERT(f->client);
 }
 
@@ -96,7 +96,7 @@ void chttp2_init_server_fullstack(grpc_end2end_test_fixture* f,
   f->server = grpc_server_create(server_args, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
   GPR_ASSERT(
-      grpc_server_add_insecure_http2_port(f->server, ffd->server_addr.get()));
+      grpc_server_add_insecure_http2_port(f->server, ffd->server_addr.c_str()));
   grpc_server_start(f->server);
 }
 
index 4fbe787..f174807 100644 (file)
@@ -31,10 +31,8 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack_ipv4(
   grpc_end2end_test_fixture f =
       grpc_end2end_local_chttp2_create_fixture_fullstack();
   int port = grpc_pick_unused_port_or_die();
-  grpc_core::JoinHostPort(
-      &static_cast<grpc_end2end_local_fullstack_fixture_data*>(f.fixture_data)
-           ->localaddr,
-      "127.0.0.1", port);
+  static_cast<grpc_end2end_local_fullstack_fixture_data*>(f.fixture_data)
+      ->localaddr = grpc_core::JoinHostPort("127.0.0.1", port);
   return f;
 }
 
index 3e6cdee..b074659 100644 (file)
@@ -31,10 +31,8 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack_ipv6(
   grpc_end2end_test_fixture f =
       grpc_end2end_local_chttp2_create_fixture_fullstack();
   int port = grpc_pick_unused_port_or_die();
-  grpc_core::JoinHostPort(
-      &static_cast<grpc_end2end_local_fullstack_fixture_data*>(f.fixture_data)
-           ->localaddr,
-      "[::1]", port);
+  static_cast<grpc_end2end_local_fullstack_fixture_data*>(f.fixture_data)
+      ->localaddr = grpc_core::JoinHostPort("[::1]", port);
   return f;
 }
 
index 6b27c41..c8db899 100644 (file)
@@ -18,6 +18,8 @@
 
 #include <unistd.h>
 
+#include "absl/strings/str_format.h"
+
 #include <grpc/support/string_util.h>
 
 #include "test/core/end2end/end2end_tests.h"
@@ -30,10 +32,9 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack_uds(
     grpc_channel_args* /*client_args*/, grpc_channel_args* /*server_args*/) {
   grpc_end2end_test_fixture f =
       grpc_end2end_local_chttp2_create_fixture_fullstack();
-  char* out = nullptr;
-  gpr_asprintf(&out, "unix:/tmp/grpc_fullstack_test.%d.%d", getpid(), unique++);
   static_cast<grpc_end2end_local_fullstack_fixture_data*>(f.fixture_data)
-      ->localaddr.reset(out);
+      ->localaddr = absl::StrFormat("unix:/tmp/grpc_fullstack_test.%d.%d",
+                                    getpid(), unique++);
   return f;
 }
 
index 13a9e1c..ce37f89 100644 (file)
@@ -39,7 +39,7 @@ static const char* client_identity_property_name = "smurf_name";
 static const char* client_identity = "Brainy Smurf";
 
 struct fullstack_secure_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
 };
 
 static const grpc_metadata* find_metadata(const grpc_metadata* md,
@@ -98,7 +98,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
   int port = grpc_pick_unused_port_or_die();
   fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
   memset(&f, 0, sizeof(f));
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
   f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
@@ -110,7 +110,7 @@ static void chttp2_init_client_secure_fullstack(
     grpc_channel_credentials* creds) {
   fullstack_secure_fixture_data* ffd =
       static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
-  f->client = grpc_secure_channel_create(creds, ffd->localaddr.get(),
+  f->client = grpc_secure_channel_create(creds, ffd->localaddr.c_str(),
                                          client_args, nullptr);
   GPR_ASSERT(f->client != nullptr);
   grpc_channel_credentials_release(creds);
@@ -126,8 +126,8 @@ static void chttp2_init_server_secure_fullstack(
   }
   f->server = grpc_server_create(server_args, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
-  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr.get(),
-                                               server_creds));
+  GPR_ASSERT(grpc_server_add_secure_http2_port(
+      f->server, ffd->localaddr.c_str(), server_creds));
   grpc_server_credentials_release(server_creds);
   grpc_server_start(f->server);
 }
index 9cb9aaf..c44e069 100644 (file)
@@ -37,7 +37,7 @@
 #define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key"
 
 struct fullstack_secure_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
 };
 
 static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
@@ -47,7 +47,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
   fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
   memset(&f, 0, sizeof(f));
 
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
@@ -70,7 +70,7 @@ static void chttp2_init_client_secure_fullstack(
     grpc_channel_credentials* creds) {
   fullstack_secure_fixture_data* ffd =
       static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
-  f->client = grpc_secure_channel_create(creds, ffd->localaddr.get(),
+  f->client = grpc_secure_channel_create(creds, ffd->localaddr.c_str(),
                                          client_args, nullptr);
   GPR_ASSERT(f->client != nullptr);
   grpc_channel_credentials_release(creds);
@@ -86,8 +86,8 @@ static void chttp2_init_server_secure_fullstack(
   }
   f->server = grpc_server_create(server_args, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
-  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr.get(),
-                                               server_creds));
+  GPR_ASSERT(grpc_server_add_secure_http2_port(
+      f->server, ffd->localaddr.c_str(), server_creds));
   grpc_server_credentials_release(server_creds);
   grpc_server_start(f->server);
 }
index 589f2fd..96f796d 100644 (file)
@@ -37,7 +37,7 @@
 #define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key"
 
 struct fullstack_secure_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
   bool server_credential_reloaded = false;
 };
 
@@ -82,7 +82,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
   int port = grpc_pick_unused_port_or_die();
   fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
   memset(&f, 0, sizeof(f));
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
@@ -105,7 +105,7 @@ static void chttp2_init_client_secure_fullstack(
     grpc_channel_credentials* creds) {
   fullstack_secure_fixture_data* ffd =
       static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
-  f->client = grpc_secure_channel_create(creds, ffd->localaddr.get(),
+  f->client = grpc_secure_channel_create(creds, ffd->localaddr.c_str(),
                                          client_args, nullptr);
   GPR_ASSERT(f->client != nullptr);
   grpc_channel_credentials_release(creds);
@@ -122,8 +122,8 @@ static void chttp2_init_server_secure_fullstack(
   ffd->server_credential_reloaded = false;
   f->server = grpc_server_create(server_args, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
-  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr.get(),
-                                               server_creds));
+  GPR_ASSERT(grpc_server_add_secure_http2_port(
+      f->server, ffd->localaddr.c_str(), server_creds));
   grpc_server_credentials_release(server_creds);
   grpc_server_start(f->server);
 }
index 95cff3a..bacbf7e 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
+#include "absl/container/inlined_vector.h"
+
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/tmpfile.h"
 #include "src/core/lib/gprpp/host_port.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
 #include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/security/credentials/credentials.h"
@@ -42,7 +43,7 @@
 #define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem"
 #define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key"
 
-typedef grpc_core::InlinedVector<grpc_core::Thread, 1> ThreadList;
+typedef absl::InlinedVector<grpc_core::Thread, 1> ThreadList;
 
 struct fullstack_secure_fixture_data {
   ~fullstack_secure_fixture_data() {
@@ -50,7 +51,7 @@ struct fullstack_secure_fixture_data {
       thd_list[ind].Join();
     }
   }
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
   ThreadList thd_list;
 };
 
@@ -60,7 +61,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
   int port = grpc_pick_unused_port_or_die();
   fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
   memset(&f, 0, sizeof(f));
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
   f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
@@ -81,7 +82,7 @@ static void chttp2_init_client_secure_fullstack(
     grpc_channel_credentials* creds) {
   fullstack_secure_fixture_data* ffd =
       static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
-  f->client = grpc_secure_channel_create(creds, ffd->localaddr.get(),
+  f->client = grpc_secure_channel_create(creds, ffd->localaddr.c_str(),
                                          client_args, nullptr);
   GPR_ASSERT(f->client != nullptr);
   grpc_channel_credentials_release(creds);
@@ -97,8 +98,8 @@ static void chttp2_init_server_secure_fullstack(
   }
   f->server = grpc_server_create(server_args, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
-  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr.get(),
-                                               server_creds));
+  GPR_ASSERT(grpc_server_add_secure_http2_port(
+      f->server, ffd->localaddr.c_str(), server_creds));
   grpc_server_credentials_release(server_creds);
   grpc_server_start(f->server);
 }
index de8cec3..b827f58 100644 (file)
@@ -61,7 +61,7 @@ struct grpc_end2end_http_proxy {
     gpr_ref_init(&users, 1);
     combiner = grpc_combiner_create();
   }
-  grpc_core::UniquePtr<char> proxy_name;
+  std::string proxy_name;
   grpc_core::Thread thd;
   grpc_tcp_server* server;
   grpc_channel_args* channel_args;
@@ -612,8 +612,8 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(
   grpc_end2end_http_proxy* proxy = new grpc_end2end_http_proxy();
   // Construct proxy address.
   const int proxy_port = grpc_pick_unused_port_or_die();
-  grpc_core::JoinHostPort(&proxy->proxy_name, "localhost", proxy_port);
-  gpr_log(GPR_INFO, "Proxy address: %s", proxy->proxy_name.get());
+  proxy->proxy_name = grpc_core::JoinHostPort("localhost", proxy_port);
+  gpr_log(GPR_INFO, "Proxy address: %s", proxy->proxy_name.c_str());
   // Create TCP server.
   proxy->channel_args = grpc_channel_args_copy(args);
   grpc_error* error =
@@ -663,5 +663,5 @@ void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy) {
 
 const char* grpc_end2end_http_proxy_get_proxy_name(
     grpc_end2end_http_proxy* proxy) {
-  return proxy->proxy_name.get();
+  return proxy->proxy_name.c_str();
 }
index fadf80c..73679dd 100644 (file)
@@ -50,7 +50,7 @@ void grpc_end2end_local_chttp2_init_client_fullstack(
   grpc_channel_credentials* creds = grpc_local_credentials_create(type);
   grpc_end2end_local_fullstack_fixture_data* ffd =
       static_cast<grpc_end2end_local_fullstack_fixture_data*>(f->fixture_data);
-  f->client = grpc_secure_channel_create(creds, ffd->localaddr.get(),
+  f->client = grpc_secure_channel_create(creds, ffd->localaddr.c_str(),
                                          client_args, nullptr);
   GPR_ASSERT(f->client != nullptr);
   grpc_channel_credentials_release(creds);
@@ -98,8 +98,8 @@ void grpc_end2end_local_chttp2_init_server_fullstack(
                                               nullptr};
     grpc_server_credentials_set_auth_metadata_processor(creds, processor);
   }
-  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr.get(),
-                                               creds));
+  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server,
+                                               ffd->localaddr.c_str(), creds));
   grpc_server_credentials_release(creds);
   grpc_server_start(f->server);
 }
index df204d2..9e7a334 100644 (file)
@@ -23,7 +23,7 @@
 #include "src/core/lib/surface/channel.h"
 
 struct grpc_end2end_local_fullstack_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
 };
 
 /* Utility functions shared by h2_local tests. */
index ff6ee12..919d632 100644 (file)
@@ -41,8 +41,8 @@ struct grpc_end2end_proxy {
     memset(&new_call_metadata, 0, sizeof(new_call_metadata));
   }
   grpc_core::Thread thd;
-  grpc_core::UniquePtr<char> proxy_port;
-  grpc_core::UniquePtr<char> server_port;
+  std::string proxy_port;
+  std::string server_port;
   grpc_completion_queue* cq;
   grpc_server* server;
   grpc_channel* client;
@@ -91,15 +91,15 @@ grpc_end2end_proxy* grpc_end2end_proxy_create(const grpc_end2end_proxy_def* def,
 
   grpc_end2end_proxy* proxy = new grpc_end2end_proxy();
 
-  grpc_core::JoinHostPort(&proxy->proxy_port, "localhost", proxy_port);
-  grpc_core::JoinHostPort(&proxy->server_port, "localhost", server_port);
+  proxy->proxy_port = grpc_core::JoinHostPort("localhost", proxy_port);
+  proxy->server_port = grpc_core::JoinHostPort("localhost", server_port);
 
-  gpr_log(GPR_DEBUG, "PROXY ADDR:%s BACKEND:%s", proxy->proxy_port.get(),
-          proxy->server_port.get());
+  gpr_log(GPR_DEBUG, "PROXY ADDR:%s BACKEND:%s", proxy->proxy_port.c_str(),
+          proxy->server_port.c_str());
 
   proxy->cq = grpc_completion_queue_create_for_next(nullptr);
-  proxy->server = def->create_server(proxy->proxy_port.get(), server_args);
-  proxy->client = def->create_client(proxy->server_port.get(), client_args);
+  proxy->server = def->create_server(proxy->proxy_port.c_str(), server_args);
+  proxy->client = def->create_client(proxy->server_port.c_str(), client_args);
 
   grpc_server_register_completion_queue(proxy->server, proxy->cq, nullptr);
   grpc_server_start(proxy->server);
@@ -440,9 +440,9 @@ static void thread_main(void* arg) {
 }
 
 const char* grpc_end2end_proxy_get_client_target(grpc_end2end_proxy* proxy) {
-  return proxy->proxy_port.get();
+  return proxy->proxy_port.c_str();
 }
 
 const char* grpc_end2end_proxy_get_server_port(grpc_end2end_proxy* proxy) {
-  return proxy->server_port.get();
+  return proxy->server_port.c_str();
 }
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/error_refcount b/test/core/end2end/fuzzers/client_fuzzer_corpus/error_refcount
new file mode 100644 (file)
index 0000000..7a91314
Binary files /dev/null and b/test/core/end2end/fuzzers/client_fuzzer_corpus/error_refcount differ
index 9e93745..7eabb25 100755 (executable)
@@ -64,7 +64,6 @@ END2END_FIXTURES = {
         fullstack = False,
         client_channel = False,
         _platforms = ["linux", "mac", "posix"],
-        flaky_tests = ["resource_quota_server"],  # TODO(b/151212019)
     ),
     "h2_full": _fixture_options(),
     "h2_full+pipe": _fixture_options(_platforms = ["linux"]),
@@ -96,7 +95,6 @@ END2END_FIXTURES = {
         secure = True,
         dns_resolver = False,
         _platforms = ["linux", "mac", "posix"],
-        flaky_tests = ["resource_quota_server"],  # TODO(b/151212019)
     ),
     "h2_local_ipv4": _fixture_options(secure = True, dns_resolver = False, _platforms = ["linux", "mac", "posix"]),
     "h2_local_ipv6": _fixture_options(secure = True, dns_resolver = False, _platforms = ["linux", "mac", "posix"]),
@@ -104,7 +102,6 @@ END2END_FIXTURES = {
     "h2_uds": _fixture_options(
         dns_resolver = False,
         _platforms = ["linux", "mac", "posix"],
-        flaky_tests = ["resource_quota_server"],  # TODO(b/151212019)
     ),
     "inproc": _fixture_options(
         secure = True,
@@ -133,7 +130,6 @@ END2END_NOSEC_FIXTURES = {
         secure = False,
         _platforms = ["linux", "mac", "posix"],
         supports_msvc = False,
-        flaky_tests = ["resource_quota_server"],  # TODO(b/151212019)
     ),
     "h2_full": _fixture_options(secure = False),
     "h2_full+pipe": _fixture_options(secure = False, _platforms = ["linux"], supports_msvc = False),
@@ -168,7 +164,6 @@ END2END_NOSEC_FIXTURES = {
         _platforms = ["linux", "mac", "posix"],
         secure = False,
         supports_msvc = False,
-        flaky_tests = ["resource_quota_server"],  # TODO(b/151212019)
     ),
 }
 
@@ -184,7 +179,8 @@ def _test_options(
         needs_proxy_auth = False,
         needs_write_buffering = False,
         needs_client_channel = False,
-        short_name = None):
+        short_name = None,
+        exclude_pollers = []):
     return struct(
         needs_fullstack = needs_fullstack,
         needs_dns = needs_dns,
@@ -198,6 +194,7 @@ def _test_options(
         needs_write_buffering = needs_write_buffering,
         needs_client_channel = needs_client_channel,
         short_name = short_name,
+        exclude_pollers = exclude_pollers,
     )
 
 # maps test names to options
@@ -205,7 +202,11 @@ END2END_TESTS = {
     "bad_hostname": _test_options(needs_names = True),
     "bad_ping": _test_options(needs_fullstack = True, proxyable = False),
     "binary_metadata": _test_options(),
-    "resource_quota_server": _test_options(proxyable = False),
+    "resource_quota_server": _test_options(
+        proxyable = False,
+        # TODO(b/151212019): Test case known to be flaky under epoll1.
+        exclude_pollers = ["epoll1"],
+    ),
     "call_creds": _test_options(secure = True),
     "call_host_override": _test_options(
         needs_fullstack = True,
@@ -219,6 +220,7 @@ END2END_TESTS = {
     "cancel_before_invoke": _test_options(),
     "cancel_in_a_vacuum": _test_options(),
     "cancel_with_status": _test_options(),
+    "client_streaming": _test_options(),
     "compressed_payload": _test_options(proxyable = False, exclude_inproc = True),
     "connectivity": _test_options(
         needs_fullstack = True,
@@ -465,6 +467,8 @@ def grpc_end2end_tests():
             )
 
             for poller in POLLERS:
+                if poller in topt.exclude_pollers:
+                    continue
                 native.sh_test(
                     name = "%s_test@%s@poller=%s" % (f, test_short_name, poller),
                     data = [":%s_test" % f],
@@ -541,6 +545,8 @@ def grpc_end2end_nosec_tests():
             )
 
             for poller in POLLERS:
+                if poller in topt.exclude_pollers:
+                    continue
                 native.sh_test(
                     name = "%s_nosec_test@%s@poller=%s" % (f, test_short_name, poller),
                     data = [":%s_nosec_test" % f],
index 1ad6115..1e32cad 100644 (file)
@@ -50,7 +50,7 @@ static grpc_ares_request* (*iomgr_dns_lookup_ares_locked)(
     std::unique_ptr<grpc_core::ServerAddressList>* addresses,
     std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses,
     char** service_config_json, int query_timeout_ms,
-    grpc_core::Combiner* combiner);
+    std::shared_ptr<grpc_core::WorkSerializer> combiner);
 
 static void (*iomgr_cancel_ares_request_locked)(grpc_ares_request* request);
 
@@ -108,11 +108,12 @@ static grpc_ares_request* my_dns_lookup_ares_locked(
     std::unique_ptr<grpc_core::ServerAddressList>* addresses,
     std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses,
     char** service_config_json, int query_timeout_ms,
-    grpc_core::Combiner* combiner) {
+    std::shared_ptr<grpc_core::WorkSerializer> work_serializer) {
   if (0 != strcmp(addr, "test")) {
     return iomgr_dns_lookup_ares_locked(
         dns_server, addr, default_port, interested_parties, on_done, addresses,
-        balancer_addresses, service_config_json, query_timeout_ms, combiner);
+        balancer_addresses, service_config_json, query_timeout_ms,
+        std::move(work_serializer));
   }
 
   grpc_error* error = GRPC_ERROR_NONE;
index a555c5c..21c3d28 100644 (file)
@@ -48,7 +48,7 @@ namespace grpc {
 namespace testing {
 
 struct fullstack_secure_fixture_data {
-  grpc_core::UniquePtr<char> localaddr;
+  std::string localaddr;
 };
 
 static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
@@ -58,7 +58,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
   fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
   memset(&f, 0, sizeof(f));
 
-  grpc_core::JoinHostPort(&ffd->localaddr, "localhost", port);
+  ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
@@ -79,7 +79,7 @@ static void chttp2_init_client_secure_fullstack(
     grpc_channel_credentials* creds) {
   fullstack_secure_fixture_data* ffd =
       static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
-  f->client = grpc_secure_channel_create(creds, ffd->localaddr.get(),
+  f->client = grpc_secure_channel_create(creds, ffd->localaddr.c_str(),
                                          client_args, nullptr);
   GPR_ASSERT(f->client != nullptr);
   grpc_channel_credentials_release(creds);
@@ -95,8 +95,8 @@ static void chttp2_init_server_secure_fullstack(
   }
   f->server = grpc_server_create(server_args, nullptr);
   grpc_server_register_completion_queue(f->server, f->cq, nullptr);
-  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr.get(),
-                                               server_creds));
+  GPR_ASSERT(grpc_server_add_secure_http2_port(
+      f->server, ffd->localaddr.c_str(), server_creds));
   grpc_server_credentials_release(server_creds);
   grpc_server_start(f->server);
 }
index 2683f3d..a209d8f 100644 (file)
@@ -48,7 +48,7 @@ void* tag(intptr_t t) { return (void*)t; }
 
 gpr_timespec five_seconds_time() { return grpc_timeout_seconds_to_deadline(5); }
 
-grpc_server* server_create(grpc_completion_queue* cq, char* server_addr) {
+grpc_server* server_create(grpc_completion_queue* cq, const char* server_addr) {
   grpc_slice ca_slice, cert_slice, key_slice;
   GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
                                grpc_load_file(CA_CERT_PATH, 1, &ca_slice)));
@@ -80,7 +80,8 @@ grpc_server* server_create(grpc_completion_queue* cq, char* server_addr) {
   return server;
 }
 
-grpc_channel* client_create(char* server_addr, grpc_ssl_session_cache* cache) {
+grpc_channel* client_create(const char* server_addr,
+                            grpc_ssl_session_cache* cache) {
   grpc_slice ca_slice, cert_slice, key_slice;
   GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
                                grpc_load_file(CA_CERT_PATH, 1, &ca_slice)));
@@ -126,7 +127,7 @@ grpc_channel* client_create(char* server_addr, grpc_ssl_session_cache* cache) {
 }
 
 void do_round_trip(grpc_completion_queue* cq, grpc_server* server,
-                   char* server_addr, grpc_ssl_session_cache* cache,
+                   const char* server_addr, grpc_ssl_session_cache* cache,
                    bool expect_session_reuse) {
   grpc_channel* client = client_create(server_addr, cache);
 
@@ -249,17 +250,16 @@ void drain_cq(grpc_completion_queue* cq) {
 TEST(H2SessionReuseTest, SingleReuse) {
   int port = grpc_pick_unused_port_or_die();
 
-  grpc_core::UniquePtr<char> server_addr;
-  grpc_core::JoinHostPort(&server_addr, "localhost", port);
+  std::string server_addr = grpc_core::JoinHostPort("localhost", port);
 
   grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
   grpc_ssl_session_cache* cache = grpc_ssl_session_cache_create_lru(16);
 
-  grpc_server* server = server_create(cq, server_addr.get());
+  grpc_server* server = server_create(cq, server_addr.c_str());
 
-  do_round_trip(cq, server, server_addr.get(), cache, false);
-  do_round_trip(cq, server, server_addr.get(), cache, true);
-  do_round_trip(cq, server, server_addr.get(), cache, true);
+  do_round_trip(cq, server, server_addr.c_str(), cache, false);
+  do_round_trip(cq, server, server_addr.c_str(), cache, true);
+  do_round_trip(cq, server, server_addr.c_str(), cache, true);
 
   grpc_ssl_session_cache_destroy(cache);
 
index 5f920fa..75725a6 100644 (file)
@@ -77,13 +77,13 @@ static void prepare_test(int is_client) {
   } else {
     g_state.server = grpc_server_create(nullptr, nullptr);
     grpc_server_register_completion_queue(g_state.server, g_state.cq, nullptr);
-    grpc_core::UniquePtr<char> server_hostport;
-    grpc_core::JoinHostPort(&server_hostport, "0.0.0.0", port);
-    grpc_server_add_insecure_http2_port(g_state.server, server_hostport.get());
+    std::string server_hostport = grpc_core::JoinHostPort("0.0.0.0", port);
+    grpc_server_add_insecure_http2_port(g_state.server,
+                                        server_hostport.c_str());
     grpc_server_start(g_state.server);
-    grpc_core::JoinHostPort(&server_hostport, "localhost", port);
+    server_hostport = grpc_core::JoinHostPort("localhost", port);
     g_state.chan =
-        grpc_insecure_channel_create(server_hostport.get(), nullptr, nullptr);
+        grpc_insecure_channel_create(server_hostport.c_str(), nullptr, nullptr);
     grpc_slice host = grpc_slice_from_static_string("bar");
     g_state.call = grpc_channel_create_call(
         g_state.chan, nullptr, GRPC_PROPAGATE_DEFAULTS, g_state.cq,
diff --git a/test/core/end2end/tests/client_streaming.cc b/test/core/end2end/tests/client_streaming.cc
new file mode 100644 (file)
index 0000000..e3f8868
--- /dev/null
@@ -0,0 +1,273 @@
+//
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+
+#include "test/core/end2end/end2end_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include "test/core/end2end/cq_verifier.h"
+
+static void* tag(intptr_t t) { return (void*)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+                                            const char* test_name,
+                                            grpc_channel_args* client_args,
+                                            grpc_channel_args* server_args) {
+  grpc_end2end_test_fixture f;
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
+  f = config.create_fixture(client_args, server_args);
+  config.init_server(&f, server_args);
+  config.init_client(&f, client_args);
+  return f;
+}
+
+static gpr_timespec n_seconds_from_now(int n) {
+  return grpc_timeout_seconds_to_deadline(n);
+}
+
+static gpr_timespec five_seconds_from_now(void) {
+  return n_seconds_from_now(5);
+}
+
+static void drain_cq(grpc_completion_queue* cq) {
+  grpc_event ev;
+  do {
+    ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr);
+  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+static void shutdown_server(grpc_end2end_test_fixture* f) {
+  if (!f->server) return;
+  grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
+  GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
+                                         grpc_timeout_seconds_to_deadline(5),
+                                         nullptr)
+                 .type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(f->server);
+  f->server = nullptr;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture* f) {
+  if (!f->client) return;
+  grpc_channel_destroy(f->client);
+  f->client = nullptr;
+}
+
+static void end_test(grpc_end2end_test_fixture* f) {
+  shutdown_server(f);
+  shutdown_client(f);
+
+  grpc_completion_queue_shutdown(f->cq);
+  drain_cq(f->cq);
+  grpc_completion_queue_destroy(f->cq);
+  grpc_completion_queue_destroy(f->shutdown_cq);
+}
+
+// Client streaming test where the client sends a bunch of messages and the
+// server reads them. After reading some messages, the server sends the status.
+// Client writes fail after that due to the end of stream and the client
+// subsequently requests and receives the status.
+static void test_client_streaming(grpc_end2end_test_config config,
+                                  int messages) {
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_client_streaming", nullptr, nullptr);
+  grpc_call* c;
+  grpc_call* s;
+  cq_verifier* cqv = cq_verifier_create(f.cq);
+  grpc_op ops[6];
+  grpc_op* op;
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array request_metadata_recv;
+  grpc_call_details call_details;
+  grpc_status_code status;
+  grpc_call_error error;
+  grpc_slice details;
+  grpc_byte_buffer* request_payload_recv = nullptr;
+  grpc_byte_buffer* request_payload = nullptr;
+  int i;
+  grpc_slice request_payload_slice =
+      grpc_slice_from_copied_string("hello world");
+
+  gpr_timespec deadline = five_seconds_from_now();
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
+  GPR_ASSERT(c);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
+                                nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  error =
+      grpc_server_request_call(f.server, &s, &call_details,
+                               &request_metadata_recv, f.cq, f.cq, tag(100));
+  GPR_ASSERT(GRPC_CALL_OK == error);
+  CQ_EXPECT_COMPLETION(cqv, tag(100), 1);
+  cq_verify(cqv);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(101),
+                                nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
+  CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
+  cq_verify(cqv);
+
+  // Client writes bunch of messages and server reads them
+  for (i = 0; i < messages; i++) {
+    request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+    memset(ops, 0, sizeof(ops));
+    op = ops;
+    op->op = GRPC_OP_SEND_MESSAGE;
+    op->data.send_message.send_message = request_payload;
+    op->flags = 0;
+    op->reserved = nullptr;
+    op++;
+    error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops),
+                                  tag(103), nullptr);
+    GPR_ASSERT(GRPC_CALL_OK == error);
+    grpc_byte_buffer_destroy(request_payload);
+
+    memset(ops, 0, sizeof(ops));
+    op = ops;
+    op->op = GRPC_OP_RECV_MESSAGE;
+    op->data.recv_message.recv_message = &request_payload_recv;
+    op->flags = 0;
+    op->reserved = nullptr;
+    op++;
+    error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops),
+                                  tag(102), nullptr);
+    GPR_ASSERT(GRPC_CALL_OK == error);
+    CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
+    CQ_EXPECT_COMPLETION(cqv, tag(103), 1);
+    cq_verify(cqv);
+    GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
+    grpc_byte_buffer_destroy(request_payload_recv);
+  }
+
+  // Server sends status denoting end of stream
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+  op->data.send_status_from_server.trailing_metadata_count = 0;
+  op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(104),
+                                nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+  CQ_EXPECT_COMPLETION(cqv, tag(104), 1);
+  cq_verify(cqv);
+  // Do an empty verify to make sure that the client receives the status
+  cq_verify_empty(cqv);
+
+  // Client tries sending another message which should fail
+  request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_MESSAGE;
+  op->data.send_message.send_message = request_payload;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(103),
+                                nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+  grpc_byte_buffer_destroy(request_payload);
+  CQ_EXPECT_COMPLETION(cqv, tag(103), 0);
+  cq_verify(cqv);
+
+  // Client sends close and requests status
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(3),
+                                nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+  CQ_EXPECT_COMPLETION(cqv, tag(3), 1);
+  cq_verify(cqv);
+  GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+
+  grpc_slice_unref(request_payload_slice);
+
+  grpc_call_unref(c);
+  grpc_call_unref(s);
+
+  cq_verifier_destroy(cqv);
+
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+  grpc_slice_unref(details);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+void client_streaming(grpc_end2end_test_config config) {
+  for (int i = 0; i < 10; i++) {
+    test_client_streaming(config, i);
+  }
+}
+
+void client_streaming_pre_init(void) {}
index a8c5789..8e0f863 100644 (file)
@@ -21,6 +21,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <string>
+
 #include <grpc/byte_buffer.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
@@ -245,9 +247,7 @@ static void simple_request_body(grpc_end2end_test_config config,
 
   grpc_stats_collect(after);
 
-  char* stats = grpc_stats_data_as_json(after);
-  gpr_log(GPR_DEBUG, "%s", stats);
-  gpr_free(stats);
+  gpr_log(GPR_DEBUG, "%s", grpc_stats_data_as_json(after).c_str());
 
   GPR_ASSERT(after->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] -
                  before->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] ==
index 713975a..ac78361 100644 (file)
@@ -88,7 +88,7 @@ static void end_test(grpc_end2end_test_fixture* f) {
   grpc_completion_queue_destroy(f->shutdown_cq);
 }
 
-/* Client sends a request with payload, server reads then returns status. */
+// Client sends a request with payload, server reads then returns status.
 static void test(grpc_end2end_test_config config, bool request_status_early,
                  bool recv_message_separately) {
   grpc_call* c;
@@ -200,8 +200,12 @@ static void test(grpc_end2end_test_config config, bool request_status_early,
   error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(103),
                                 nullptr);
   GPR_ASSERT(GRPC_CALL_OK == error);
-
-  CQ_EXPECT_COMPLETION(cqv, tag(103), 1);
+  // The success of the op depends on whether the payload is written before the
+  // transport sees the end of stream. If the stream has been write closed
+  // before the write completes, it would fail, otherwise it would succeed.
+  // Since this behavior is dependent on the transport implementation, we allow
+  // any success status with this op.
+  CQ_EXPECT_COMPLETION_ANY_STATUS(cqv, tag(103));
 
   if (!request_status_early) {
     memset(ops, 0, sizeof(ops));
index edd5616..b4565ec 100644 (file)
@@ -46,9 +46,8 @@ int main(int /*argc*/, char** argv) {
   gpr_asprintf(&args[0], "%s/fling_server%s", root,
                gpr_subprocess_binary_extension());
   args[1] = const_cast<char*>("--bind");
-  grpc_core::UniquePtr<char> joined;
-  grpc_core::JoinHostPort(&joined, "::", port);
-  args[2] = joined.get();
+  std::string joined = grpc_core::JoinHostPort("::", port);
+  args[2] = const_cast<char*>(joined.c_str());
   args[3] = const_cast<char*>("--no-secure");
   svr = gpr_subprocess_create(4, (const char**)args);
   gpr_free(args[0]);
@@ -57,8 +56,8 @@ int main(int /*argc*/, char** argv) {
   gpr_asprintf(&args[0], "%s/fling_client%s", root,
                gpr_subprocess_binary_extension());
   args[1] = const_cast<char*>("--target");
-  grpc_core::JoinHostPort(&joined, "127.0.0.1", port);
-  args[2] = joined.get();
+  joined = grpc_core::JoinHostPort("127.0.0.1", port);
+  args[2] = const_cast<char*>(joined.c_str());
   args[3] = const_cast<char*>("--scenario=ping-pong-stream");
   args[4] = const_cast<char*>("--no-secure");
   args[5] = nullptr;
index 00d399c..717bccd 100644 (file)
@@ -47,9 +47,8 @@ int main(int /*argc*/, const char** argv) {
   gpr_asprintf(&args[0], "%s/fling_server%s", root,
                gpr_subprocess_binary_extension());
   args[1] = const_cast<char*>("--bind");
-  grpc_core::UniquePtr<char> joined;
-  grpc_core::JoinHostPort(&joined, "::", port);
-  args[2] = joined.get();
+  std::string joined = grpc_core::JoinHostPort("::", port);
+  args[2] = const_cast<char*>(joined.c_str());
   args[3] = const_cast<char*>("--no-secure");
   svr = gpr_subprocess_create(4, (const char**)args);
   gpr_free(args[0]);
@@ -58,8 +57,8 @@ int main(int /*argc*/, const char** argv) {
   gpr_asprintf(&args[0], "%s/fling_client%s", root,
                gpr_subprocess_binary_extension());
   args[1] = const_cast<char*>("--target");
-  grpc_core::JoinHostPort(&joined, "127.0.0.1", port);
-  args[2] = joined.get();
+  joined = grpc_core::JoinHostPort("127.0.0.1", port);
+  args[2] = const_cast<char*>(joined.c_str());
   args[3] = const_cast<char*>("--scenario=ping-pong-request");
   args[4] = const_cast<char*>("--no-secure");
   args[5] = nullptr;
index 878bff3..4085e28 100644 (file)
@@ -172,7 +172,7 @@ static void sigint_handler(int /*x*/) { _exit(0); }
 int main(int argc, char** argv) {
   grpc_event ev;
   call_state* s;
-  grpc_core::UniquePtr<char> addr_buf;
+  std::string addr_buf;
   gpr_cmdline* cl;
   grpc_completion_queue* shutdown_cq;
   int shutdown_started = 0;
@@ -199,8 +199,8 @@ int main(int argc, char** argv) {
   gpr_cmdline_destroy(cl);
 
   if (addr == nullptr) {
-    grpc_core::JoinHostPort(&addr_buf, "::", grpc_pick_unused_port_or_die());
-    addr = addr_buf.get();
+    addr_buf = grpc_core::JoinHostPort("::", grpc_pick_unused_port_or_die());
+    addr = addr_buf.c_str();
   }
   gpr_log(GPR_INFO, "creating server on: %s", addr);
 
@@ -221,7 +221,7 @@ int main(int argc, char** argv) {
   grpc_server_start(server);
 
   addr = nullptr;
-  addr_buf.reset();
+  addr_buf.clear();
 
   grpc_call_details_init(&call_details);
 
index 1df1052..c7aa63a 100644 (file)
@@ -21,6 +21,9 @@
 #include <inttypes.h>
 #include <string.h>
 
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -37,20 +40,15 @@ static void test_noop(void) { Arena::Create(1)->Destroy(); }
 
 static void test(const char* name, size_t init_size, const size_t* allocs,
                  size_t nallocs) {
-  gpr_strvec v;
-  char* s;
-  gpr_strvec_init(&v);
-  gpr_asprintf(&s, "test '%s': %" PRIdPTR " <- {", name, init_size);
-  gpr_strvec_add(&v, s);
+  std::vector<std::string> parts;
+  parts.push_back(
+      absl::StrFormat("test '%s': %" PRIdPTR " <- {", name, init_size));
   for (size_t i = 0; i < nallocs; i++) {
-    gpr_asprintf(&s, "%" PRIdPTR ",", allocs[i]);
-    gpr_strvec_add(&v, s);
+    parts.push_back(absl::StrFormat("%" PRIdPTR ",", allocs[i]));
   }
-  gpr_strvec_add(&v, gpr_strdup("}"));
-  s = gpr_strvec_flatten(&v, nullptr);
-  gpr_strvec_destroy(&v);
-  gpr_log(GPR_INFO, "%s", s);
-  gpr_free(s);
+  parts.push_back("}");
+  std::string s = absl::StrJoin(parts, "");
+  gpr_log(GPR_INFO, "%s", s.c_str());
 
   Arena* a = Arena::Create(init_size);
   void** ps = static_cast<void**>(gpr_zalloc(sizeof(*ps) * nallocs));
index a9a8f84..4c9e82f 100644 (file)
@@ -96,19 +96,6 @@ grpc_cc_test(
 )
 
 grpc_cc_test(
-    name = "optional_test",
-    srcs = ["optional_test.cc"],
-    external_deps = [
-        "gtest",
-    ],
-    language = "C++",
-    deps = [
-        "//:optional",
-        "//test/core/util:grpc_test_util",
-    ],
-)
-
-grpc_cc_test(
     name = "orphanable_test",
     srcs = ["orphanable_test.cc"],
     external_deps = [
@@ -149,19 +136,6 @@ grpc_cc_test(
 )
 
 grpc_cc_test(
-    name = "string_view_test",
-    srcs = ["string_view_test.cc"],
-    external_deps = [
-        "gtest",
-    ],
-    language = "C++",
-    deps = [
-        "//:gpr_base",
-        "//test/core/util:grpc_test_util",
-    ],
-)
-
-grpc_cc_test(
     name = "thd_test",
     srcs = ["thd_test.cc"],
     language = "C++",
index cfe0edd..0cff997 100644 (file)
 
 static void join_host_port_expect(const char* host, int port,
                                   const char* expected) {
-  grpc_core::UniquePtr<char> buf;
-  int len;
-  len = grpc_core::JoinHostPort(&buf, host, port);
-  GPR_ASSERT(len >= 0);
-  GPR_ASSERT(strlen(expected) == static_cast<size_t>(len));
-  GPR_ASSERT(strcmp(expected, buf.get()) == 0);
+  std::string actual = grpc_core::JoinHostPort(host, port);
+  GPR_ASSERT(actual == expected);
 }
 
 static void test_join_host_port(void) {
@@ -50,21 +46,13 @@ static void test_join_host_port_garbage(void) {
 
 static void split_host_port_expect(const char* name, const char* host,
                                    const char* port, bool ret) {
-  grpc_core::UniquePtr<char> actual_host;
-  grpc_core::UniquePtr<char> actual_port;
+  std::string actual_host;
+  std::string actual_port;
   const bool actual_ret =
       grpc_core::SplitHostPort(name, &actual_host, &actual_port);
   GPR_ASSERT(actual_ret == ret);
-  if (host == nullptr) {
-    GPR_ASSERT(actual_host == nullptr);
-  } else {
-    GPR_ASSERT(strcmp(host, actual_host.get()) == 0);
-  }
-  if (port == nullptr) {
-    GPR_ASSERT(actual_port == nullptr);
-  } else {
-    GPR_ASSERT(strcmp(port, actual_port.get()) == 0);
-  }
+  GPR_ASSERT(actual_host == (host == nullptr ? "" : host));
+  GPR_ASSERT(actual_port == (port == nullptr ? "" : port));
 }
 
 static void test_split_host_port() {
diff --git a/test/core/gprpp/optional_test.cc b/test/core/gprpp/optional_test.cc
deleted file mode 100644 (file)
index 67c7fad..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *
- * Copyright 2019 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "src/core/lib/gprpp/optional.h"
-#include <grpc/support/log.h>
-#include <gtest/gtest.h>
-#include "src/core/lib/gprpp/memory.h"
-#include "test/core/util/test_config.h"
-
-namespace grpc_core {
-namespace testing {
-
-namespace {
-TEST(OptionalTest, BasicTest) {
-  grpc_core::Optional<int> opt_val;
-  EXPECT_FALSE(opt_val.has_value());
-  const int kTestVal = 123;
-
-  opt_val.emplace(kTestVal);
-  EXPECT_TRUE(opt_val.has_value());
-  EXPECT_EQ(opt_val.value(), kTestVal);
-
-  opt_val.reset();
-  EXPECT_EQ(opt_val.has_value(), false);
-}
-}  // namespace
-
-}  // namespace testing
-}  // namespace grpc_core
-
-int main(int argc, char** argv) {
-  grpc::testing::TestEnvironment env(argc, argv);
-  ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}
diff --git a/test/core/gprpp/string_view_test.cc b/test/core/gprpp/string_view_test.cc
deleted file mode 100644 (file)
index a48967e..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- *
- * Copyright 2017 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <grpc/slice.h>
-
-#include "src/core/lib/gprpp/string_view.h"
-
-#include <gtest/gtest.h>
-#include "src/core/lib/gprpp/memory.h"
-#include "test/core/util/test_config.h"
-
-namespace grpc_core {
-namespace testing {
-
-TEST(StringViewTest, Empty) {
-  grpc_core::StringView empty;
-  EXPECT_TRUE(empty.empty());
-  EXPECT_EQ(empty.size(), 0lu);
-
-  grpc_core::StringView empty_buf("");
-  EXPECT_TRUE(empty_buf.empty());
-  EXPECT_EQ(empty_buf.size(), 0lu);
-
-  grpc_core::StringView empty_trimmed("foo", 0);
-  EXPECT_TRUE(empty_trimmed.empty());
-  EXPECT_EQ(empty_trimmed.size(), 0lu);
-
-  grpc_core::StringView empty_slice(
-      grpc_core::StringViewFromSlice(grpc_empty_slice()));
-  EXPECT_TRUE(empty_slice.empty());
-  EXPECT_EQ(empty_slice.size(), 0lu);
-}
-
-TEST(StringViewTest, Size) {
-  constexpr char kStr[] = "foo";
-  grpc_core::StringView str1(kStr);
-  EXPECT_EQ(str1.size(), strlen(kStr));
-  grpc_core::StringView str2(kStr, 2);
-  EXPECT_EQ(str2.size(), 2lu);
-}
-
-TEST(StringViewTest, Data) {
-  constexpr char kStr[] = "foo-bar";
-  grpc_core::StringView str(kStr);
-  EXPECT_EQ(str.size(), strlen(kStr));
-  for (size_t i = 0; i < strlen(kStr); ++i) {
-    EXPECT_EQ(str[i], kStr[i]);
-  }
-}
-
-TEST(StringViewTest, Slice) {
-  constexpr char kStr[] = "foo";
-  grpc_core::StringView slice(
-      grpc_core::StringViewFromSlice(grpc_slice_from_static_string(kStr)));
-  EXPECT_EQ(slice.size(), strlen(kStr));
-}
-
-TEST(StringViewTest, Dup) {
-  constexpr char kStr[] = "foo";
-  grpc_core::StringView slice(
-      grpc_core::StringViewFromSlice(grpc_slice_from_static_string(kStr)));
-  grpc_core::UniquePtr<char> dup = grpc_core::StringViewToCString(slice);
-  EXPECT_EQ(0, strcmp(kStr, dup.get()));
-  EXPECT_EQ(slice.size(), strlen(kStr));
-}
-
-TEST(StringViewTest, Eq) {
-  constexpr char kStr1[] = "foo";
-  constexpr char kStr2[] = "bar";
-  grpc_core::StringView str1(kStr1);
-  EXPECT_EQ(kStr1, str1);
-  EXPECT_EQ(str1, kStr1);
-  grpc_core::StringView slice1(
-      grpc_core::StringViewFromSlice(grpc_slice_from_static_string(kStr1)));
-  EXPECT_EQ(slice1, str1);
-  EXPECT_EQ(str1, slice1);
-  EXPECT_NE(slice1, kStr2);
-  EXPECT_NE(kStr2, slice1);
-  grpc_core::StringView slice2(
-      grpc_core::StringViewFromSlice(grpc_slice_from_static_string(kStr2)));
-  EXPECT_NE(slice2, str1);
-  EXPECT_NE(str1, slice2);
-}
-
-TEST(StringViewTest, Cmp) {
-  constexpr char kStr1[] = "abc";
-  constexpr char kStr2[] = "abd";
-  constexpr char kStr3[] = "abcd";
-  grpc_core::StringView str1(kStr1);
-  grpc_core::StringView str2(kStr2);
-  grpc_core::StringView str3(kStr3);
-  EXPECT_EQ(str1.compare(str1), 0);
-  EXPECT_LT(str1.compare(str2), 0);
-  EXPECT_LT(str1.compare(str3), 0);
-  EXPECT_EQ(str2.compare(str2), 0);
-  EXPECT_GT(str2.compare(str1), 0);
-  EXPECT_GT(str2.compare(str3), 0);
-  EXPECT_EQ(str3.compare(str3), 0);
-  EXPECT_GT(str3.compare(str1), 0);
-  EXPECT_LT(str3.compare(str2), 0);
-}
-
-TEST(StringViewTest, RemovePrefix) {
-  constexpr char kStr[] = "abcd";
-  grpc_core::StringView str(kStr);
-  str.remove_prefix(1);
-  EXPECT_EQ("bcd", str);
-  str.remove_prefix(2);
-  EXPECT_EQ("d", str);
-  str.remove_prefix(1);
-  EXPECT_EQ("", str);
-}
-
-TEST(StringViewTest, RemoveSuffix) {
-  constexpr char kStr[] = "abcd";
-  grpc_core::StringView str(kStr);
-  str.remove_suffix(1);
-  EXPECT_EQ("abc", str);
-  str.remove_suffix(2);
-  EXPECT_EQ("a", str);
-  str.remove_suffix(1);
-  EXPECT_EQ("", str);
-}
-
-TEST(StringViewTest, Substring) {
-  constexpr char kStr[] = "abcd";
-  grpc_core::StringView str(kStr);
-  EXPECT_EQ("bcd", str.substr(1));
-  EXPECT_EQ("bc", str.substr(1, 2));
-}
-
-TEST(StringViewTest, Find) {
-  // Passing StringView::npos directly to GTEST macros result in link errors.
-  // Store the value in a local variable and use it in the test.
-  const size_t npos = grpc_core::StringView::npos;
-  constexpr char kStr[] = "abacad";
-  grpc_core::StringView str(kStr);
-  EXPECT_EQ(0ul, str.find('a'));
-  EXPECT_EQ(2ul, str.find('a', 1));
-  EXPECT_EQ(4ul, str.find('a', 3));
-  EXPECT_EQ(1ul, str.find('b'));
-  EXPECT_EQ(npos, str.find('b', 2));
-  EXPECT_EQ(npos, str.find('z'));
-}
-
-}  // namespace testing
-}  // namespace grpc_core
-
-int main(int argc, char** argv) {
-  grpc::testing::TestEnvironment env(argc, argv);
-  ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}
index 250d36a..bd92426 100644 (file)
@@ -175,15 +175,9 @@ static void test_sockaddr_is_wildcard(void) {
 
 static void expect_sockaddr_str(const char* expected,
                                 grpc_resolved_address* addr, int normalize) {
-  int result;
-  char* str;
   gpr_log(GPR_INFO, "  expect_sockaddr_str(%s)", expected);
-  result = grpc_sockaddr_to_string(&str, addr, normalize);
-  GPR_ASSERT(str != nullptr);
-  GPR_ASSERT(result >= 0);
-  GPR_ASSERT((size_t)result == strlen(str));
-  GPR_ASSERT(strcmp(expected, str) == 0);
-  gpr_free(str);
+  std::string actual = grpc_sockaddr_to_string(addr, normalize);
+  GPR_ASSERT(actual == expected);
 }
 
 static void expect_sockaddr_uri(const char* expected,
index b2d64f4..8594344 100644 (file)
@@ -32,6 +32,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <string>
+
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -133,15 +135,10 @@ static void server_weak_ref_set(server_weak_ref* weak_ref,
 }
 
 static void test_addr_init_str(test_addr* addr) {
-  char* str = nullptr;
-  if (grpc_sockaddr_to_string(&str, &addr->addr, 0) != -1) {
-    size_t str_len;
-    memcpy(addr->str, str, (str_len = strnlen(str, sizeof(addr->str) - 1)));
-    addr->str[str_len] = '\0';
-    gpr_free(str);
-  } else {
-    addr->str[0] = '\0';
-  }
+  std::string str = grpc_sockaddr_to_string(&addr->addr, false);
+  size_t str_len = std::min(str.size(), sizeof(addr->str) - 1);
+  memcpy(addr->str, str.c_str(), str_len);
+  addr->str[str_len] = '\0';
 }
 
 static void on_connect(void* /*arg*/, grpc_endpoint* tcp,
index 6d27ee2..e9eecf2 100644 (file)
@@ -31,7 +31,7 @@ bool leak_check = true;
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   grpc_error* error = GRPC_ERROR_NONE;
   grpc_core::Json::Parse(
-      grpc_core::StringView(reinterpret_cast<const char*>(data), size), &error);
+      absl::string_view(reinterpret_cast<const char*>(data), size), &error);
   GRPC_ERROR_UNREF(error);
   return 0;
 }
index ad698aa..bd94a80 100644 (file)
@@ -47,7 +47,6 @@ grpc_fuzzer(
     deps = [
         "//:gpr",
         "//:grpc",
-        "//test/core/end2end:ssl_test_data",
         "//test/core/util:grpc_test_util",
     ],
 )
@@ -268,7 +267,6 @@ grpc_cc_test(
         "//:grpc_secure",
         "//:tsi",
         "//:tsi_interface",
-        "//test/core/end2end:ssl_test_data",
         "//test/core/util:grpc_test_util",
     ],
 )
@@ -287,7 +285,6 @@ grpc_cc_test(
         "//:gpr",
         "//:grpc",
         "//:grpc_secure",
-        "//test/core/end2end:ssl_test_data",
         "//test/core/util:grpc_test_util",
     ],
 )
index fd0cf6c..75eb00e 100644 (file)
@@ -788,8 +788,8 @@ static void test_valid_sts_creds_options(void) {
       grpc_core::ValidateStsCredentialsOptions(&valid_options, &sts_url);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(sts_url != nullptr);
-  grpc_core::StringView host;
-  grpc_core::StringView port;
+  absl::string_view host;
+  absl::string_view port;
   GPR_ASSERT(grpc_core::SplitHostPort(sts_url->authority, &host, &port));
   GPR_ASSERT(host == "foo.com");
   GPR_ASSERT(port == "5555");
index d93be88..6b032bb 100644 (file)
@@ -216,9 +216,7 @@ static Json parse_json_part_from_jwt(const char* str, size_t len) {
   gpr_free(b64);
   GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(slice));
   grpc_error* error = GRPC_ERROR_NONE;
-  grpc_core::StringView string(
-      reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(slice)),
-      GRPC_SLICE_LENGTH(slice));
+  absl::string_view string = grpc_core::StringViewFromSlice(slice);
   Json json = Json::Parse(string, &error);
   if (error != GRPC_ERROR_NONE) {
     gpr_log(GPR_ERROR, "JSON parse error: %s", grpc_error_string(error));
index 9713178..8f249be 100644 (file)
  *
  */
 
-#include <stdio.h>
-#include <string.h>
+#include "src/core/lib/security/security_connector/security_connector.h"
 
 #include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
+#include <stdio.h>
+#include <string.h>
 
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/tmpfile.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/security/context/security_context.h"
-#include "src/core/lib/security/security_connector/security_connector.h"
 #include "src/core/lib/security/security_connector/ssl_utils.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/tsi/ssl_transport_security.h"
@@ -222,6 +222,35 @@ static int check_x509_pem_cert_chain(const grpc_auth_context* ctx,
   return 1;
 }
 
+static int check_spiffe_id(const grpc_auth_context* ctx,
+                           const char* expected_spiffe_id,
+                           bool expect_spiffe_id) {
+  grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
+      ctx, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME);
+  const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
+  if (prop == nullptr && !expect_spiffe_id) {
+    return 1;
+  }
+  if (prop != nullptr && !expect_spiffe_id) {
+    gpr_log(GPR_ERROR, "SPIFFE ID not expected, but got %s.", prop->value);
+    return 0;
+  }
+  if (prop == nullptr && expect_spiffe_id) {
+    gpr_log(GPR_ERROR, "SPIFFE ID expected, but got nullptr.");
+    return 0;
+  }
+  if (strncmp(prop->value, expected_spiffe_id, prop->value_length) != 0) {
+    gpr_log(GPR_ERROR, "Expected SPIFFE ID %s but got %s.", expected_spiffe_id,
+            prop->value);
+    return 0;
+  }
+  if (grpc_auth_property_iterator_next(&it) != nullptr) {
+    gpr_log(GPR_ERROR, "Expected only one property for SPIFFE ID.");
+    return 0;
+  }
+  return 1;
+}
+
 static void test_cn_only_ssl_peer_to_auth_context(void) {
   tsi_peer peer;
   tsi_peer rpeer;
@@ -415,6 +444,71 @@ static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(
   ctx.reset(DEBUG_LOCATION, "test");
 }
 
+static void test_spiffe_id_peer_to_auth_context(void) {
+  // Invalid SPIFFE IDs should not be plumbed.
+  std::string long_id(2050, 'x');
+  std::string long_domain(256, 'x');
+  tsi_peer invalid_peer;
+  std::vector<std::string> invalid_spiffe_id = {
+      "",
+      "spi://",
+      "sfiffe://domain/wl",
+      "spiffe://domain",
+      "spiffe://domain/",
+      long_id,
+      "spiffe://" + long_domain + "/wl"};
+  size_t i;
+  GPR_ASSERT(tsi_construct_peer(invalid_spiffe_id.size(), &invalid_peer) ==
+             TSI_OK);
+  for (i = 0; i < invalid_spiffe_id.size(); i++) {
+    GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+                   TSI_X509_URI_PEER_PROPERTY, invalid_spiffe_id[i].c_str(),
+                   &invalid_peer.properties[i]) == TSI_OK);
+  }
+  grpc_core::RefCountedPtr<grpc_auth_context> invalid_ctx =
+      grpc_ssl_peer_to_auth_context(&invalid_peer,
+                                    GRPC_SSL_TRANSPORT_SECURITY_TYPE);
+  GPR_ASSERT(invalid_ctx != nullptr);
+  GPR_ASSERT(check_spiffe_id(invalid_ctx.get(), nullptr, false));
+  tsi_peer_destruct(&invalid_peer);
+  invalid_ctx.reset(DEBUG_LOCATION, "test");
+  // A valid SPIFFE ID with other URI fields should be plumbed.
+  tsi_peer valid_peer;
+  std::vector<std::string> valid_spiffe_id = {"spiffe://foo.bar.com/wl",
+                                              "https://xyz"};
+  GPR_ASSERT(tsi_construct_peer(valid_spiffe_id.size(), &valid_peer) == TSI_OK);
+  for (i = 0; i < valid_spiffe_id.size(); i++) {
+    GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+                   TSI_X509_URI_PEER_PROPERTY, valid_spiffe_id[i].c_str(),
+                   &valid_peer.properties[i]) == TSI_OK);
+  }
+  grpc_core::RefCountedPtr<grpc_auth_context> valid_ctx =
+      grpc_ssl_peer_to_auth_context(&valid_peer,
+                                    GRPC_SSL_TRANSPORT_SECURITY_TYPE);
+  GPR_ASSERT(valid_ctx != nullptr);
+  GPR_ASSERT(check_spiffe_id(valid_ctx.get(), "spiffe://foo.bar.com/wl", true));
+  tsi_peer_destruct(&valid_peer);
+  valid_ctx.reset(DEBUG_LOCATION, "test");
+  // Multiple SPIFFE IDs should not be plumbed.
+  tsi_peer multiple_peer;
+  std::vector<std::string> multiple_spiffe_id = {
+      "spiffe://foo.bar.com/wl", "https://xyz", "spiffe://foo.bar.com/wl2"};
+  GPR_ASSERT(tsi_construct_peer(multiple_spiffe_id.size(), &multiple_peer) ==
+             TSI_OK);
+  for (i = 0; i < multiple_spiffe_id.size(); i++) {
+    GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+                   TSI_X509_URI_PEER_PROPERTY, multiple_spiffe_id[i].c_str(),
+                   &multiple_peer.properties[i]) == TSI_OK);
+  }
+  grpc_core::RefCountedPtr<grpc_auth_context> multiple_ctx =
+      grpc_ssl_peer_to_auth_context(&multiple_peer,
+                                    GRPC_SSL_TRANSPORT_SECURITY_TYPE);
+  GPR_ASSERT(multiple_ctx != nullptr);
+  GPR_ASSERT(check_spiffe_id(multiple_ctx.get(), nullptr, false));
+  tsi_peer_destruct(&multiple_peer);
+  multiple_ctx.reset(DEBUG_LOCATION, "test");
+}
+
 static const char* roots_for_override_api = "roots for override api";
 
 static grpc_ssl_roots_override_result override_roots_success(
@@ -562,6 +656,7 @@ int main(int argc, char** argv) {
   test_cn_and_one_san_ssl_peer_to_auth_context();
   test_cn_and_multiple_sans_ssl_peer_to_auth_context();
   test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context();
+  test_spiffe_id_peer_to_auth_context();
   test_ipv6_address_san();
   test_default_ssl_roots();
   test_peer_alpn_check();
index cfe285f..2b480af 100644 (file)
@@ -37,10 +37,9 @@ typedef struct {
 } synchronizer;
 
 static void print_usage_and_exit(gpr_cmdline* cl, const char* argv0) {
-  char* usage = gpr_cmdline_usage_string(cl, argv0);
-  fprintf(stderr, "%s", usage);
+  std::string usage = gpr_cmdline_usage_string(cl, argv0);
+  fprintf(stderr, "%s", usage.c_str());
   fflush(stderr);
-  gpr_free(usage);
   gpr_cmdline_destroy(cl);
   exit(1);
 }
index 83a6db4..975bedf 100644 (file)
@@ -330,6 +330,13 @@ static void test_moved_string_slice(void) {
   grpc_shutdown();
 }
 
+void test_string_view_from_slice() {
+  constexpr char kStr[] = "foo";
+  absl::string_view sv(
+      grpc_core::StringViewFromSlice(grpc_slice_from_static_string(kStr)));
+  GPR_ASSERT(std::string(sv) == kStr);
+}
+
 int main(int argc, char** argv) {
   unsigned length;
   grpc::testing::TestEnvironment env(argc, argv);
@@ -348,6 +355,7 @@ int main(int argc, char** argv) {
   test_static_slice_interning();
   test_static_slice_copy_interning();
   test_moved_string_slice();
+  test_string_view_from_slice();
   grpc_shutdown();
   return 0;
 }
index cce1fd7..7d78939 100644 (file)
@@ -67,6 +67,7 @@ grpc_cc_test(
 grpc_cc_test(
     name = "concurrent_connectivity_test",
     srcs = ["concurrent_connectivity_test.cc"],
+    flaky = True,  # TODO(b/157516542)
     language = "C++",
     deps = [
         "//:gpr",
@@ -148,7 +149,6 @@ grpc_cc_test(
     deps = [
         "//:gpr",
         "//:grpc",
-        "//test/core/end2end:ssl_test_data",
         "//test/core/util:grpc_test_util",
     ],
 )
index 541e9ab..1b2cce8 100644 (file)
@@ -69,11 +69,11 @@ static void channel_idle_poll_for_timeout(grpc_channel* channel,
 static void run_timeouts_test(const test_fixture* fixture) {
   gpr_log(GPR_INFO, "TEST: %s", fixture->name);
 
-  grpc_core::UniquePtr<char> addr;
   grpc_init();
-  grpc_core::JoinHostPort(&addr, "localhost", grpc_pick_unused_port_or_die());
+  std::string addr =
+      grpc_core::JoinHostPort("localhost", grpc_pick_unused_port_or_die());
 
-  grpc_channel* channel = fixture->create_channel(addr.get());
+  grpc_channel* channel = fixture->create_channel(addr.c_str());
   grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
 
   /* start 1 watcher and then let it time out */
@@ -120,11 +120,11 @@ static void run_channel_shutdown_before_timeout_test(
     const test_fixture* fixture) {
   gpr_log(GPR_INFO, "TEST: %s", fixture->name);
 
-  grpc_core::UniquePtr<char> addr;
   grpc_init();
-  grpc_core::JoinHostPort(&addr, "localhost", grpc_pick_unused_port_or_die());
+  std::string addr =
+      grpc_core::JoinHostPort("localhost", grpc_pick_unused_port_or_die());
 
-  grpc_channel* channel = fixture->create_channel(addr.get());
+  grpc_channel* channel = fixture->create_channel(addr.c_str());
   grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
 
   /* start 1 watcher and then shut down the channel before the timer goes off */
index 8f7a46b..401821f 100644 (file)
  *
  */
 
+#include <vector>
+
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
+#include <grpc/impl/codegen/grpc_types.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
 typedef struct test_fixture {
   const char* name;
   void (*add_server_port)(grpc_server* server, const char* addr);
-  grpc_channel* (*create_channel)(const char* addr);
+  // Have the creds here so all the channels will share the same one to enabled
+  // subchannel sharing if needed.
+  grpc_channel_credentials* creds;
 } test_fixture;
 
-/* TODO(yashykt): When our macos testing infrastructure becomes good enough, we
- * wouldn't need to reduce the number of connections on MacOS */
-#ifdef __APPLE__
 #define NUM_CONNECTIONS 100
-#else
-#define NUM_CONNECTIONS 1000
-#endif /* __APPLE__ */
 
 typedef struct {
   grpc_server* server;
@@ -61,16 +60,37 @@ static void server_thread_func(void* args) {
   GPR_ASSERT(ev.success == true);
 }
 
-static void run_test(const test_fixture* fixture) {
-  gpr_log(GPR_INFO, "TEST: %s", fixture->name);
+static grpc_channel* create_test_channel(const char* addr,
+                                         grpc_channel_credentials* creds,
+                                         bool share_subchannel) {
+  grpc_channel* channel = nullptr;
+  std::vector<grpc_arg> args;
+  args.push_back(grpc_channel_arg_integer_create(
+      const_cast<char*>(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL),
+      !share_subchannel));
+  if (creds != nullptr) {
+    args.push_back(grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
+        const_cast<char*>("foo.test.google.fr")));
+  }
+  grpc_channel_args channel_args = {args.size(), args.data()};
+  if (creds != nullptr) {
+    channel = grpc_secure_channel_create(creds, addr, &channel_args, nullptr);
+  } else {
+    channel = grpc_insecure_channel_create(addr, &channel_args, nullptr);
+  }
+  return channel;
+}
 
-  grpc_init();
+static void run_test(const test_fixture* fixture, bool share_subchannel) {
+  gpr_log(GPR_INFO, "TEST: %s sharing subchannel: %d", fixture->name,
+          share_subchannel);
 
-  grpc_core::UniquePtr<char> addr;
-  grpc_core::JoinHostPort(&addr, "localhost", grpc_pick_unused_port_or_die());
+  std::string addr =
+      grpc_core::JoinHostPort("localhost", grpc_pick_unused_port_or_die());
 
   grpc_server* server = grpc_server_create(nullptr, nullptr);
-  fixture->add_server_port(server, addr.get());
+  fixture->add_server_port(server, addr.c_str());
   grpc_completion_queue* server_cq =
       grpc_completion_queue_create_for_next(nullptr);
   grpc_server_register_completion_queue(server, server_cq, nullptr);
@@ -83,7 +103,8 @@ static void run_test(const test_fixture* fixture) {
   grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
   grpc_channel* channels[NUM_CONNECTIONS];
   for (size_t i = 0; i < NUM_CONNECTIONS; i++) {
-    channels[i] = fixture->create_channel(addr.get());
+    channels[i] =
+        create_test_channel(addr.c_str(), fixture->creds, share_subchannel);
 
     gpr_timespec connect_deadline = grpc_timeout_seconds_to_deadline(30);
     grpc_connectivity_state state;
@@ -124,24 +145,12 @@ static void run_test(const test_fixture* fixture) {
   grpc_server_destroy(server);
   grpc_completion_queue_destroy(server_cq);
   grpc_completion_queue_destroy(cq);
-
-  grpc_shutdown();
 }
 
 static void insecure_test_add_port(grpc_server* server, const char* addr) {
   grpc_server_add_insecure_http2_port(server, addr);
 }
 
-static grpc_channel* insecure_test_create_channel(const char* addr) {
-  return grpc_insecure_channel_create(addr, nullptr, nullptr);
-}
-
-static const test_fixture insecure_test = {
-    "insecure",
-    insecure_test_add_port,
-    insecure_test_create_channel,
-};
-
 static void secure_test_add_port(grpc_server* server, const char* addr) {
   grpc_slice cert_slice, key_slice;
   GPR_ASSERT(GRPC_LOG_IF_ERROR(
@@ -161,7 +170,18 @@ static void secure_test_add_port(grpc_server* server, const char* addr) {
   grpc_server_credentials_release(ssl_creds);
 }
 
-static grpc_channel* secure_test_create_channel(const char* addr) {
+int main(int argc, char** argv) {
+  grpc::testing::TestEnvironment env(argc, argv);
+  grpc_init();
+
+  const test_fixture insecure_test = {
+      "insecure",
+      insecure_test_add_port,
+      nullptr,
+  };
+  run_test(&insecure_test, /*share_subchannel=*/true);
+  run_test(&insecure_test, /*share_subchannel=*/false);
+
   grpc_slice ca_slice;
   GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
                                grpc_load_file(CA_CERT_PATH, 1, &ca_slice)));
@@ -170,31 +190,14 @@ static grpc_channel* secure_test_create_channel(const char* addr) {
   grpc_channel_credentials* ssl_creds =
       grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr, nullptr);
   grpc_slice_unref(ca_slice);
-  grpc_arg ssl_name_override = {
-      GRPC_ARG_STRING,
-      const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
-      {const_cast<char*>("foo.test.google.fr")}};
-  grpc_channel_args* new_client_args =
-      grpc_channel_args_copy_and_add(nullptr, &ssl_name_override, 1);
-  grpc_channel* channel =
-      grpc_secure_channel_create(ssl_creds, addr, new_client_args, nullptr);
-  {
-    grpc_core::ExecCtx exec_ctx;
-    grpc_channel_args_destroy(new_client_args);
-  }
+  const test_fixture secure_test = {
+      "secure",
+      secure_test_add_port,
+      ssl_creds,
+  };
+  run_test(&secure_test, /*share_subchannel=*/true);
+  run_test(&secure_test, /*share_subchannel=*/false);
   grpc_channel_credentials_release(ssl_creds);
-  return channel;
-}
-
-static const test_fixture secure_test = {
-    "secure",
-    secure_test_add_port,
-    secure_test_create_channel,
-};
-
-int main(int argc, char** argv) {
-  grpc::testing::TestEnvironment env(argc, argv);
 
-  run_test(&insecure_test);
-  run_test(&secure_test);
+  grpc_shutdown();
 }
index a88362e..3399b07 100644 (file)
@@ -47,15 +47,15 @@ void test_add_same_port_twice() {
   grpc_channel_args args = {1, &a};
 
   int port = grpc_pick_unused_port_or_die();
-  grpc_core::UniquePtr<char> addr;
   grpc_completion_queue* cq = grpc_completion_queue_create_for_pluck(nullptr);
   grpc_server* server = grpc_server_create(&args, nullptr);
   grpc_server_credentials* fake_creds =
       grpc_fake_transport_security_server_credentials_create();
-  grpc_core::JoinHostPort(&addr, "localhost", port);
-  GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr.get(), fake_creds));
+  std::string addr = grpc_core::JoinHostPort("localhost", port);
   GPR_ASSERT(
-      grpc_server_add_secure_http2_port(server, addr.get(), fake_creds) == 0);
+      grpc_server_add_secure_http2_port(server, addr.c_str(), fake_creds));
+  GPR_ASSERT(
+      grpc_server_add_secure_http2_port(server, addr.c_str(), fake_creds) == 0);
 
   grpc_server_credentials_release(fake_creds);
   grpc_server_shutdown_and_notify(server, cq, nullptr);
index 185a675..e53d7eb 100644 (file)
@@ -106,19 +106,18 @@ void test_bind_server_twice(void) {
 
 void test_bind_server_to_addr(const char* host, bool secure) {
   int port = grpc_pick_unused_port_or_die();
-  grpc_core::UniquePtr<char> addr;
-  grpc_core::JoinHostPort(&addr, host, port);
-  gpr_log(GPR_INFO, "Test bind to %s", addr.get());
+  std::string addr = grpc_core::JoinHostPort(host, port);
+  gpr_log(GPR_INFO, "Test bind to %s", addr.c_str());
 
   grpc_server* server = grpc_server_create(nullptr, nullptr);
   if (secure) {
     grpc_server_credentials* fake_creds =
         grpc_fake_transport_security_server_credentials_create();
     GPR_ASSERT(
-        grpc_server_add_secure_http2_port(server, addr.get(), fake_creds));
+        grpc_server_add_secure_http2_port(server, addr.c_str(), fake_creds));
     grpc_server_credentials_release(fake_creds);
   } else {
-    GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr.get()));
+    GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr.c_str()));
   }
   grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
   grpc_server_register_completion_queue(server, cq, nullptr);
index 707091b..8099b4f 100644 (file)
@@ -49,6 +49,102 @@ typedef struct {
   bool only_intern_key;
 } verify_params;
 
+/* verify that the output frames that are generated by encoding the stream
+   have sensible type and flags values */
+static void verify_frames(grpc_slice_buffer& output, bool header_is_eof) {
+  /* per the HTTP/2 spec:
+       All frames begin with a fixed 9-octet header followed by a
+       variable-length payload.
+
+       +-----------------------------------------------+
+       |                 Length (24)                   |
+       +---------------+---------------+---------------+
+       |   Type (8)    |   Flags (8)   |
+       +-+-------------+---------------+-------------------------------+
+       |R|                 Stream Identifier (31)                      |
+       +=+=============================================================+
+       |                   Frame Payload (0...)                      ...
+       +---------------------------------------------------------------+
+   */
+  uint8_t type = 0xff, flags = 0xff;
+  size_t i, merged_length, frame_size;
+  bool first_frame = false;
+  bool in_header = false;
+  bool end_header = false;
+  bool is_closed = false;
+  for (i = 0; i < output.count;) {
+    first_frame = i == 0;
+    grpc_slice* slice = &output.slices[i++];
+
+    // Read gRPC frame header
+    uint8_t* p = GRPC_SLICE_START_PTR(*slice);
+    frame_size = 0;
+    frame_size |= static_cast<uint32_t>(p[0]) << 16;
+    frame_size |= static_cast<uint32_t>(p[1]) << 8;
+    frame_size |= static_cast<uint32_t>(p[2]);
+    type = p[3];
+    flags = p[4];
+
+    // Read remainder of the gRPC frame
+    merged_length = GRPC_SLICE_LENGTH(*slice);
+    while (merged_length < frame_size + 9) {  // including 9 byte frame header
+      grpc_slice* slice = &output.slices[i++];
+      merged_length += GRPC_SLICE_LENGTH(*slice);
+    }
+
+    // Verifications
+    if (first_frame && type != GRPC_CHTTP2_FRAME_HEADER) {
+      gpr_log(GPR_ERROR, "expected first frame to be of type header");
+      gpr_log(GPR_ERROR, "EXPECT: 0x%x", GRPC_CHTTP2_FRAME_HEADER);
+      gpr_log(GPR_ERROR, "GOT:    0x%x", type);
+      g_failure = 1;
+    } else if (first_frame && header_is_eof &&
+               !(flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM)) {
+      gpr_log(GPR_ERROR, "missing END_STREAM flag in HEADER frame");
+      g_failure = 1;
+    }
+    if (is_closed &&
+        (type == GRPC_CHTTP2_FRAME_DATA || type == GRPC_CHTTP2_FRAME_HEADER)) {
+      gpr_log(GPR_ERROR,
+              "stream is closed; new frame headers and data are not allowed");
+      g_failure = 1;
+    }
+    if (end_header && (type == GRPC_CHTTP2_FRAME_HEADER ||
+                       type == GRPC_CHTTP2_FRAME_CONTINUATION)) {
+      gpr_log(GPR_ERROR,
+              "frame header is ended; new headers and continuations are not "
+              "allowed");
+      g_failure = 1;
+    }
+    if (in_header &&
+        (type == GRPC_CHTTP2_FRAME_DATA || type == GRPC_CHTTP2_FRAME_HEADER)) {
+      gpr_log(GPR_ERROR,
+              "parsing frame header; new headers and data are not allowed");
+      g_failure = 1;
+    }
+    if (flags & ~(GRPC_CHTTP2_DATA_FLAG_END_STREAM |
+                  GRPC_CHTTP2_DATA_FLAG_END_HEADERS)) {
+      gpr_log(GPR_ERROR, "unexpected frame flags: 0x%x", flags);
+      g_failure = 1;
+    }
+
+    // Update state
+    if (flags & GRPC_CHTTP2_DATA_FLAG_END_HEADERS) {
+      in_header = false;
+      end_header = true;
+    } else if (type == GRPC_CHTTP2_DATA_FLAG_END_HEADERS) {
+      in_header = true;
+    }
+    if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
+      is_closed = true;
+      if (type == GRPC_CHTTP2_FRAME_CONTINUATION) {
+        gpr_log(GPR_ERROR, "unexpected END_STREAM flag in CONTINUATION frame");
+        g_failure = 1;
+      }
+    }
+  }
+}
+
 /* verify that the output generated by encoding the stream matches the
    hexstring passed in */
 static void verify(const verify_params params, const char* expected,
@@ -106,6 +202,7 @@ static void verify(const verify_params params, const char* expected,
       &stats                           /* stats */
   };
   grpc_chttp2_encode_header(&g_compressor, nullptr, 0, &b, &hopt, &output);
+  verify_frames(output, params.eof);
   merged = grpc_slice_merge(output.slices, output.count);
   grpc_slice_buffer_destroy_internal(&output);
   grpc_metadata_batch_destroy(&b);
@@ -151,6 +248,50 @@ static void test_basic_headers() {
   verify(params, "000004 0104 deadbeef 0f 2f 0176", 1, "a", "v");
 }
 
+static void verify_continuation_headers(const char* key, const char* value,
+                                        bool is_eof) {
+  grpc_slice_buffer output;
+  grpc_mdelem elem = grpc_mdelem_from_slices(
+      grpc_slice_intern(grpc_slice_from_static_string(key)),
+      grpc_slice_intern(grpc_slice_from_static_string(value)));
+  grpc_linked_mdelem* e =
+      static_cast<grpc_linked_mdelem*>(gpr_malloc(sizeof(*e)));
+  grpc_metadata_batch b;
+  grpc_metadata_batch_init(&b);
+  e[0].md = elem;
+  e[0].prev = nullptr;
+  e[0].next = nullptr;
+  b.list.head = &e[0];
+  b.list.tail = &e[0];
+  b.list.count = 1;
+  grpc_slice_buffer_init(&output);
+
+  grpc_transport_one_way_stats stats;
+  stats = {};
+  grpc_encode_header_options hopt = {0xdeadbeef, /* stream_id */
+                                     is_eof,     /* is_eof */
+                                     false,      /* use_true_binary_metadata */
+                                     150,        /* max_frame_size */
+                                     &stats /* stats */};
+  grpc_chttp2_encode_header(&g_compressor, nullptr, 0, &b, &hopt, &output);
+  verify_frames(output, is_eof);
+  grpc_slice_buffer_destroy_internal(&output);
+  grpc_metadata_batch_destroy(&b);
+  gpr_free(e);
+}
+
+static void test_continuation_headers() {
+  char value[200];
+  memset(value, 'a', 200);
+  value[199] = 0;  // null terminator
+  verify_continuation_headers("key", value, true);
+
+  char value2[400];
+  memset(value2, 'b', 400);
+  value2[399] = 0;  // null terminator
+  verify_continuation_headers("key2", value2, true);
+}
+
 static void encode_int_to_str(int i, char* p) {
   p[0] = static_cast<char>('a' + i % 26);
   i /= 26;
@@ -225,6 +366,7 @@ static void verify_table_size_change_match_elem_size(const char* key,
       16384,           /* max_frame_size */
       &stats /* stats */};
   grpc_chttp2_encode_header(&g_compressor, nullptr, 0, &b, &hopt, &output);
+  verify_frames(output, false);
   grpc_slice_buffer_destroy_internal(&output);
   grpc_metadata_batch_destroy(&b);
 
@@ -267,6 +409,7 @@ int main(int argc, char** argv) {
   TEST(test_decode_table_overflow);
   TEST(test_encode_header_size);
   TEST(test_interned_key_indexed);
+  TEST(test_continuation_headers);
   grpc_shutdown();
   for (i = 0; i < num_to_delete; i++) {
     gpr_free(to_delete[i]);
index 949be42..b09358b 100644 (file)
@@ -147,17 +147,18 @@ static void test_http2_error_to_grpc_status() {
 
 static void test_http2_status_to_grpc_status() {
   HTTP2_STATUS_TO_GRPC_STATUS(200, GRPC_STATUS_OK);
-  HTTP2_STATUS_TO_GRPC_STATUS(400, GRPC_STATUS_INVALID_ARGUMENT);
+  HTTP2_STATUS_TO_GRPC_STATUS(400, GRPC_STATUS_INTERNAL);
   HTTP2_STATUS_TO_GRPC_STATUS(401, GRPC_STATUS_UNAUTHENTICATED);
   HTTP2_STATUS_TO_GRPC_STATUS(403, GRPC_STATUS_PERMISSION_DENIED);
-  HTTP2_STATUS_TO_GRPC_STATUS(404, GRPC_STATUS_NOT_FOUND);
-  HTTP2_STATUS_TO_GRPC_STATUS(409, GRPC_STATUS_ABORTED);
-  HTTP2_STATUS_TO_GRPC_STATUS(412, GRPC_STATUS_FAILED_PRECONDITION);
-  HTTP2_STATUS_TO_GRPC_STATUS(429, GRPC_STATUS_RESOURCE_EXHAUSTED);
-  HTTP2_STATUS_TO_GRPC_STATUS(499, GRPC_STATUS_CANCELLED);
+  HTTP2_STATUS_TO_GRPC_STATUS(404, GRPC_STATUS_UNIMPLEMENTED);
+  HTTP2_STATUS_TO_GRPC_STATUS(409, GRPC_STATUS_UNKNOWN);
+  HTTP2_STATUS_TO_GRPC_STATUS(412, GRPC_STATUS_UNKNOWN);
+  HTTP2_STATUS_TO_GRPC_STATUS(429, GRPC_STATUS_UNAVAILABLE);
+  HTTP2_STATUS_TO_GRPC_STATUS(499, GRPC_STATUS_UNKNOWN);
   HTTP2_STATUS_TO_GRPC_STATUS(500, GRPC_STATUS_UNKNOWN);
+  HTTP2_STATUS_TO_GRPC_STATUS(502, GRPC_STATUS_UNAVAILABLE);
   HTTP2_STATUS_TO_GRPC_STATUS(503, GRPC_STATUS_UNAVAILABLE);
-  HTTP2_STATUS_TO_GRPC_STATUS(504, GRPC_STATUS_DEADLINE_EXCEEDED);
+  HTTP2_STATUS_TO_GRPC_STATUS(504, GRPC_STATUS_UNAVAILABLE);
 }
 
 int main(int argc, char** argv) {
index 18cfa0d..521cabd 100644 (file)
@@ -103,7 +103,7 @@ class FakeHandshakeServer {
  public:
   FakeHandshakeServer(bool check_num_concurrent_rpcs) {
     int port = grpc_pick_unused_port_or_die();
-    grpc_core::JoinHostPort(&address_, "localhost", port);
+    address_ = grpc_core::JoinHostPort("localhost", port);
     if (check_num_concurrent_rpcs) {
       service_ = grpc::gcp::
           CreateFakeHandshakerService(kFakeHandshakeServerMaxConcurrentStreams /* expected max concurrent rpcs */);
@@ -112,22 +112,24 @@ class FakeHandshakeServer {
           0 /* expected max concurrent rpcs unset */);
     }
     grpc::ServerBuilder builder;
-    builder.AddListeningPort(address_.get(), grpc::InsecureServerCredentials());
+    builder.AddListeningPort(address_.c_str(),
+                             grpc::InsecureServerCredentials());
     builder.RegisterService(service_.get());
     // TODO(apolcyn): when removing the global concurrent handshake limiting
     // queue, set MAX_CONCURRENT_STREAMS on this server.
     server_ = builder.BuildAndStart();
-    gpr_log(GPR_INFO, "Fake handshaker server listening on %s", address_.get());
+    gpr_log(GPR_INFO, "Fake handshaker server listening on %s",
+            address_.c_str());
   }
 
   ~FakeHandshakeServer() {
     server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0));
   }
 
-  const char* address() { return address_.get(); }
+  const char* address() { return address_.c_str(); }
 
  private:
-  grpc_core::UniquePtr<char> address_;
+  std::string address_;
   std::unique_ptr<grpc::Service> service_;
   std::unique_ptr<grpc::Server> server_;
 };
@@ -147,13 +149,13 @@ class TestServer {
     server_cq_ = grpc_completion_queue_create_for_next(nullptr);
     grpc_server_register_completion_queue(server_, server_cq_, nullptr);
     int port = grpc_pick_unused_port_or_die();
-    GPR_ASSERT(grpc_core::JoinHostPort(&server_addr_, "localhost", port));
-    GPR_ASSERT(grpc_server_add_secure_http2_port(server_, server_addr_.get(),
+    server_addr_ = grpc_core::JoinHostPort("localhost", port);
+    GPR_ASSERT(grpc_server_add_secure_http2_port(server_, server_addr_.c_str(),
                                                  server_creds));
     grpc_server_credentials_release(server_creds);
     grpc_server_start(server_);
     gpr_log(GPR_DEBUG, "Start TestServer %p. listen on %s", this,
-            server_addr_.get());
+            server_addr_.c_str());
     server_thd_ =
         std::unique_ptr<std::thread>(new std::thread(PollUntilShutdown, this));
   }
@@ -168,7 +170,7 @@ class TestServer {
     grpc_completion_queue_destroy(server_cq_);
   }
 
-  const char* address() { return server_addr_.get(); }
+  const char* address() { return server_addr_.c_str(); }
 
   static void PollUntilShutdown(const TestServer* self) {
     grpc_event ev = grpc_completion_queue_next(
@@ -182,7 +184,7 @@ class TestServer {
   grpc_server* server_;
   grpc_completion_queue* server_cq_;
   std::unique_ptr<std::thread> server_thd_;
-  grpc_core::UniquePtr<char> server_addr_;
+  std::string server_addr_;
   // Give this test server its own ALTS handshake server
   // so that we avoid competing for ALTS handshake server resources (e.g.
   // available HTTP2 streams on a globally shared handshaker subchannel)
index 70b8355..1319004 100644 (file)
@@ -259,6 +259,18 @@ static bool check_subject_alt_name(tsi_peer* peer, const char* name) {
   return false;
 }
 
+static bool check_uri(tsi_peer* peer, const char* name) {
+  for (size_t i = 0; i < peer->property_count; i++) {
+    const tsi_peer_property* prop = &peer->properties[i];
+    if (strcmp(prop->name, TSI_X509_URI_PEER_PROPERTY) == 0) {
+      if (memcmp(prop->value.data, name, prop->value.length) == 0) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 void check_server1_peer(tsi_peer* peer) {
   const tsi_peer_property* property =
       check_basic_authenticated_peer_and_get_common_name(peer);
@@ -862,9 +874,9 @@ void ssl_tsi_test_extract_x509_subject_names() {
   tsi_peer peer;
   GPR_ASSERT(tsi_ssl_extract_x509_subject_names_from_pem_cert(cert, &peer) ==
              TSI_OK);
-  // One for common name, one for certificate, one for security level, and six
-  // for SAN fields.
-  size_t expected_property_count = 8;
+  // tsi_peer should include one common name, one certificate, one security
+  // level, six SAN fields, and two URI fields.
+  size_t expected_property_count = 10;
   GPR_ASSERT(peer.property_count == expected_property_count);
   // Check common name
   const char* expected_cn = "xpigors";
@@ -885,6 +897,8 @@ void ssl_tsi_test_extract_x509_subject_names() {
       check_subject_alt_name(&peer, "https://foo.test.domain.com/test") == 1);
   GPR_ASSERT(
       check_subject_alt_name(&peer, "https://bar.test.domain.com/test") == 1);
+  GPR_ASSERT(check_uri(&peer, "https://foo.test.domain.com/test") == 1);
+  GPR_ASSERT(check_uri(&peer, "https://bar.test.domain.com/test") == 1);
   // Check email address
   GPR_ASSERT(check_subject_alt_name(&peer, "foo@test.domain.com") == 1);
   GPR_ASSERT(check_subject_alt_name(&peer, "bar@test.domain.com") == 1);
index e76acb5..c213f84 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
+#include <vector>
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -124,60 +130,42 @@ void gpr_cmdline_on_extra_arg(
 /* recursively descend argument list, adding the last element
    to s first - so that arguments are added in the order they were
    added to the list by api calls */
-static void add_args_to_usage(gpr_strvec* s, arg* a) {
-  char* tmp;
-
-  if (!a) return;
-  add_args_to_usage(s, a->next);
-
+static void add_args_to_usage(arg* a, std::vector<std::string>* s) {
+  if (a == nullptr) return;
+  add_args_to_usage(a->next, s);
   switch (a->type) {
     case ARGTYPE_BOOL:
-      gpr_asprintf(&tmp, " [--%s|--no-%s]", a->name, a->name);
-      gpr_strvec_add(s, tmp);
+      s->push_back(absl::StrFormat(" [--%s|--no-%s]", a->name, a->name));
       break;
     case ARGTYPE_STRING:
-      gpr_asprintf(&tmp, " [--%s=string]", a->name);
-      gpr_strvec_add(s, tmp);
+      s->push_back(absl::StrFormat(" [--%s=string]", a->name));
       break;
     case ARGTYPE_INT:
-      gpr_asprintf(&tmp, " [--%s=int]", a->name);
-      gpr_strvec_add(s, tmp);
+      s->push_back(absl::StrFormat(" [--%s=int]", a->name));
       break;
   }
 }
 
-char* gpr_cmdline_usage_string(gpr_cmdline* cl, const char* argv0) {
-  /* TODO(ctiller): make this prettier */
-  gpr_strvec s;
-  char* tmp;
+std::string gpr_cmdline_usage_string(gpr_cmdline* cl, const char* argv0) {
   const char* name = strrchr(argv0, '/');
-
-  if (name) {
+  if (name != nullptr) {
     name++;
   } else {
     name = argv0;
   }
 
-  gpr_strvec_init(&s);
-
-  gpr_asprintf(&tmp, "Usage: %s", name);
-  gpr_strvec_add(&s, tmp);
-  add_args_to_usage(&s, cl->args);
+  std::vector<std::string> s;
+  s.push_back(absl::StrCat("Usage: ", name));
+  add_args_to_usage(cl->args, &s);
   if (cl->extra_arg) {
-    gpr_asprintf(&tmp, " [%s...]", cl->extra_arg_name);
-    gpr_strvec_add(&s, tmp);
+    s.push_back(absl::StrFormat(" [%s...]", cl->extra_arg_name));
   }
-  gpr_strvec_add(&s, gpr_strdup("\n"));
-
-  tmp = gpr_strvec_flatten(&s, nullptr);
-  gpr_strvec_destroy(&s);
-  return tmp;
+  s.push_back("\n");
+  return absl::StrJoin(s, "");
 }
 
 static int print_usage_and_die(gpr_cmdline* cl) {
-  char* usage = gpr_cmdline_usage_string(cl, cl->argv0);
-  fprintf(stderr, "%s", usage);
-  gpr_free(usage);
+  fprintf(stderr, "%s", gpr_cmdline_usage_string(cl, cl->argv0).c_str());
   if (!cl->survive_failure) {
     exit(1);
   }
index 3ae35d6..773563d 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <grpc/support/port_platform.h>
 
+#include <string>
+
 /** Simple command line parser.
 
    Supports flags that can be specified as -foo, --foo, --no-foo, -no-foo, etc
@@ -75,6 +77,6 @@ int gpr_cmdline_parse(gpr_cmdline* cl, int argc, char** argv);
 /** Destroy the parser */
 void gpr_cmdline_destroy(gpr_cmdline* cl);
 /** Get a string describing usage */
-char* gpr_cmdline_usage_string(gpr_cmdline* cl, const char* argv0);
+std::string gpr_cmdline_usage_string(gpr_cmdline* cl, const char* argv0);
 
 #endif /* GRPC_TEST_CORE_UTIL_CMDLINE_H */
index 59e1bbf..c15e5e3 100644 (file)
@@ -307,7 +307,6 @@ static void test_extra_dashdash(void) {
 
 static void test_usage(void) {
   gpr_cmdline* cl;
-  char* usage;
 
   const char* str = nullptr;
   int x = 0;
@@ -322,17 +321,15 @@ static void test_usage(void) {
   gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb,
                            nullptr);
 
-  usage = gpr_cmdline_usage_string(cl, "test");
-  GPR_ASSERT(0 == strcmp(usage,
-                         "Usage: test [--str=string] [--x=int] "
-                         "[--flag|--no-flag] [file...]\n"));
-  gpr_free(usage);
+  std::string usage = gpr_cmdline_usage_string(cl, "test");
+  GPR_ASSERT(usage ==
+             "Usage: test [--str=string] [--x=int] "
+             "[--flag|--no-flag] [file...]\n");
 
   usage = gpr_cmdline_usage_string(cl, "/foo/test");
-  GPR_ASSERT(0 == strcmp(usage,
-                         "Usage: test [--str=string] [--x=int] "
-                         "[--flag|--no-flag] [file...]\n"));
-  gpr_free(usage);
+  GPR_ASSERT(usage ==
+             "Usage: test [--str=string] [--x=int] "
+             "[--flag|--no-flag] [file...]\n");
 
   gpr_cmdline_destroy(cl);
 }
index 115a983..c6ee9fc 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "test/core/util/test_config.h"
 
+#include <grpc/impl/codegen/gpr_types.h>
 #include <inttypes.h>
 #include <signal.h>
 #include <stdbool.h>
@@ -402,13 +403,12 @@ TestEnvironment::TestEnvironment(int argc, char** argv) {
 TestEnvironment::~TestEnvironment() {
   // This will wait until gRPC shutdown has actually happened to make sure
   // no gRPC resources (such as thread) are active. (timeout = 10s)
-  gpr_timespec timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                                      gpr_time_from_seconds(10, GPR_TIMESPAN));
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10);
   while (grpc_is_initialized()) {
     grpc_maybe_wait_for_async_shutdown();
     gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                  gpr_time_from_millis(1, GPR_TIMESPAN)));
-    if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), timeout) > 0) {
+    if (gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), deadline) > 0) {
       gpr_log(GPR_ERROR, "Timeout in waiting for gRPC shutdown");
       break;
     }
index 1c73c78..eae25bc 100644 (file)
@@ -55,7 +55,7 @@ class ForwardingLoadBalancingPolicy : public LoadBalancingPolicy {
       const std::string& delegate_policy_name, intptr_t initial_refcount = 1)
       : LoadBalancingPolicy(std::move(args), initial_refcount) {
     Args delegate_args;
-    delegate_args.combiner = combiner();
+    delegate_args.work_serializer = work_serializer();
     delegate_args.channel_control_helper = std::move(delegating_helper);
     delegate_args.args = args.args;
     delegate_ = LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
@@ -161,7 +161,8 @@ class InterceptRecvTrailingMetadataLoadBalancingPolicy
       parent_->channel_control_helper()->RequestReresolution();
     }
 
-    void AddTraceEvent(TraceSeverity severity, StringView message) override {
+    void AddTraceEvent(TraceSeverity severity,
+                       absl::string_view message) override {
       parent_->channel_control_helper()->AddTraceEvent(severity, message);
     }
 
index a1a0633..c8d2713 100644 (file)
  *
  */
 
+#include <gmock/gmock.h>
+#include <grpc/grpc.h>
 #include <grpcpp/security/credentials.h>
 #include <grpcpp/security/server_credentials.h>
 #include <grpcpp/security/tls_credentials_options.h>
 #include <grpcpp/server_builder.h>
-#include <memory>
-
-#include <gmock/gmock.h>
-#include <grpc/grpc.h>
 #include <gtest/gtest.h>
 
+#include <memory>
+
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/tmpfile.h"
 #include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h"
@@ -399,8 +399,7 @@ TEST_F(CredentialsTest, TlsCredentialReloadConfigCppToC) {
   ssl_pair->cert_chain = gpr_strdup(test_cert_chain.c_str());
   ::grpc_core::PemKeyCertPair pem_key_cert_pair =
       ::grpc_core::PemKeyCertPair(ssl_pair);
-  ::grpc_core::InlinedVector<::grpc_core::PemKeyCertPair, 1>
-      pem_key_cert_pair_list;
+  ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1> pem_key_cert_pair_list;
   pem_key_cert_pair_list.push_back(pem_key_cert_pair);
   grpc::string test_pem_root_certs = "pem_root_certs";
   c_key_materials.set_key_materials(test_pem_root_certs.c_str(),
@@ -417,7 +416,7 @@ TEST_F(CredentialsTest, TlsCredentialReloadConfigCppToC) {
   EXPECT_EQ(c_arg.cb_user_data, nullptr);
   EXPECT_STREQ(c_arg.key_materials_config->pem_root_certs(),
                "new_pem_root_certs");
-  ::grpc_core::InlinedVector<::grpc_core::PemKeyCertPair, 1> pair_list =
+  ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1> pair_list =
       c_arg.key_materials_config->pem_key_cert_pair_list();
   EXPECT_EQ(static_cast<int>(pair_list.size()), 2);
   EXPECT_STREQ(pair_list[0].private_key(), "private_key");
@@ -574,12 +573,13 @@ TEST_F(CredentialsTest, TlsCredentialsOptionsCppToC) {
           test_server_authorization_check));
 
   TlsCredentialsOptions options = TlsCredentialsOptions(
-      GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY,
       GRPC_TLS_SERVER_VERIFICATION, key_materials_config,
       credential_reload_config, server_authorization_check_config);
   grpc_tls_credentials_options* c_options = options.c_credentials_options();
   EXPECT_EQ(c_options->cert_request_type(),
-            GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY);
+            GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
+  EXPECT_EQ(c_options->server_verification_option(),
+            GRPC_TLS_SERVER_VERIFICATION);
   grpc_tls_key_materials_config* c_key_materials_config =
       c_options->key_materials_config();
   grpc_tls_credential_reload_config* c_credential_reload_config =
@@ -625,7 +625,7 @@ TEST_F(CredentialsTest, TlsCredentialsOptionsCppToC) {
   EXPECT_EQ(c_credential_reload_arg.cb_user_data, nullptr);
   EXPECT_STREQ(c_credential_reload_arg.key_materials_config->pem_root_certs(),
                "new_pem_root_certs");
-  ::grpc_core::InlinedVector<::grpc_core::PemKeyCertPair, 1> c_pair_list =
+  ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1> c_pair_list =
       c_credential_reload_arg.key_materials_config->pem_key_cert_pair_list();
   EXPECT_EQ(static_cast<int>(c_pair_list.size()), 2);
   EXPECT_STREQ(c_pair_list[0].private_key(), "private_key");
@@ -679,7 +679,6 @@ TEST_F(CredentialsTest, LoadTlsChannelCredentials) {
           test_server_authorization_check));
 
   TlsCredentialsOptions options = TlsCredentialsOptions(
-      GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY,
       GRPC_TLS_SERVER_VERIFICATION, nullptr, credential_reload_config,
       server_authorization_check_config);
   std::shared_ptr<grpc_impl::ChannelCredentials> channel_credentials =
@@ -687,22 +686,6 @@ TEST_F(CredentialsTest, LoadTlsChannelCredentials) {
   GPR_ASSERT(channel_credentials.get() != nullptr);
 }
 
-// This test demonstrates how the TLS credentials will be used to create
-// server credentials.
-TEST_F(CredentialsTest, LoadTlsServerCredentials) {
-  std::shared_ptr<TestTlsCredentialReload> test_credential_reload(
-      new TestTlsCredentialReload());
-  std::shared_ptr<TlsCredentialReloadConfig> credential_reload_config(
-      new TlsCredentialReloadConfig(test_credential_reload));
-
-  TlsCredentialsOptions options = TlsCredentialsOptions(
-      GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY,
-      GRPC_TLS_SERVER_VERIFICATION, nullptr, credential_reload_config, nullptr);
-  std::shared_ptr<::grpc_impl::ServerCredentials> server_credentials =
-      grpc::experimental::TlsServerCredentials(options);
-  GPR_ASSERT(server_credentials.get() != nullptr);
-}
-
 TEST_F(CredentialsTest, TlsCredentialReloadConfigErrorMessages) {
   std::shared_ptr<TlsCredentialReloadConfig> config(
       new TlsCredentialReloadConfig(nullptr));
index 8d8cdaa..7300a6e 100644 (file)
@@ -14,7 +14,7 @@ GRPC_LOCAL_SRC = '../../..'
     pod 'gRPC-Core',      :path => GRPC_LOCAL_SRC
     pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC
     pod 'gRPC-C++',       :path => GRPC_LOCAL_SRC
-    pod 'BoringSSL',      :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
+    pod 'BoringSSL-GRPC',      :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
   end
 end
 
index c428cab..4f8bfeb 100644 (file)
@@ -299,7 +299,7 @@ class ClientCallbackEnd2endTest
     }
   }
 
-  void SendGenericEchoAsBidi(int num_rpcs, int reuses) {
+  void SendGenericEchoAsBidi(int num_rpcs, int reuses, bool do_writes_done) {
     const grpc::string kMethodName("/grpc.testing.EchoTestService/Echo");
     grpc::string test_string("");
     for (int i = 0; i < num_rpcs; i++) {
@@ -308,8 +308,8 @@ class ClientCallbackEnd2endTest
                                                                   ByteBuffer> {
        public:
         Client(ClientCallbackEnd2endTest* test, const grpc::string& method_name,
-               const grpc::string& test_str, int reuses)
-            : reuses_remaining_(reuses) {
+               const grpc::string& test_str, int reuses, bool do_writes_done)
+            : reuses_remaining_(reuses), do_writes_done_(do_writes_done) {
           activate_ = [this, test, method_name, test_str] {
             if (reuses_remaining_ > 0) {
               cli_ctx_.reset(new ClientContext);
@@ -329,7 +329,11 @@ class ClientCallbackEnd2endTest
           };
           activate_();
         }
-        void OnWriteDone(bool /*ok*/) override { StartWritesDone(); }
+        void OnWriteDone(bool /*ok*/) override {
+          if (do_writes_done_) {
+            StartWritesDone();
+          }
+        }
         void OnReadDone(bool /*ok*/) override {
           EchoResponse response;
           EXPECT_TRUE(ParseFromByteBuffer(&recv_buf_, &response));
@@ -355,7 +359,10 @@ class ClientCallbackEnd2endTest
         std::mutex mu_;
         std::condition_variable cv_;
         bool done_ = false;
-      } rpc{this, kMethodName, test_string, reuses};
+        const bool do_writes_done_;
+      };
+
+      Client rpc(this, kMethodName, test_string, reuses, do_writes_done);
 
       rpc.Await();
     }
@@ -517,13 +524,19 @@ TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcs) {
 TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidi) {
   MAYBE_SKIP_TEST;
   ResetStub();
-  SendGenericEchoAsBidi(10, 1);
+  SendGenericEchoAsBidi(10, 1, /*do_writes_done=*/true);
 }
 
 TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidiWithReactorReuse) {
   MAYBE_SKIP_TEST;
   ResetStub();
-  SendGenericEchoAsBidi(10, 10);
+  SendGenericEchoAsBidi(10, 10, /*do_writes_done=*/true);
+}
+
+TEST_P(ClientCallbackEnd2endTest, GenericRpcNoWritesDone) {
+  MAYBE_SKIP_TEST;
+  ResetStub();
+  SendGenericEchoAsBidi(1, 1, /*do_writes_done=*/false);
 }
 
 #if GRPC_ALLOW_EXCEPTIONS
index 7ee95a6..86012a3 100644 (file)
@@ -43,6 +43,17 @@ namespace grpc {
 namespace testing {
 namespace {
 
+enum class RPCType {
+  kSyncUnary,
+  kSyncClientStreaming,
+  kSyncServerStreaming,
+  kSyncBidiStreaming,
+  kAsyncCQUnary,
+  kAsyncCQClientStreaming,
+  kAsyncCQServerStreaming,
+  kAsyncCQBidiStreaming,
+};
+
 /* Hijacks Echo RPC and fills in the expected values */
 class HijackingInterceptor : public experimental::Interceptor {
  public:
@@ -400,6 +411,7 @@ class ServerStreamingRpcHijackingInterceptor
  public:
   ServerStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) {
     info_ = info;
+    got_failed_message_ = false;
   }
 
   virtual void Intercept(experimental::InterceptorBatchMethods* methods) {
@@ -531,10 +543,22 @@ class LoggingInterceptor : public experimental::Interceptor {
     if (methods->QueryInterceptionHookPoint(
             experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) {
       EchoRequest req;
-      EXPECT_EQ(static_cast<const EchoRequest*>(methods->GetSendMessage())
-                    ->message()
-                    .find("Hello"),
-                0u);
+      auto* send_msg = methods->GetSendMessage();
+      if (send_msg == nullptr) {
+        // We did not get the non-serialized form of the message. Get the
+        // serialized form.
+        auto* buffer = methods->GetSerializedSendMessage();
+        auto copied_buffer = *buffer;
+        EchoRequest req;
+        EXPECT_TRUE(
+            SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req)
+                .ok());
+        EXPECT_EQ(req.message(), "Hello");
+      } else {
+        EXPECT_EQ(
+            static_cast<const EchoRequest*>(send_msg)->message().find("Hello"),
+            0u);
+      }
       auto* buffer = methods->GetSerializedSendMessage();
       auto copied_buffer = *buffer;
       EXPECT_TRUE(
@@ -582,6 +606,27 @@ class LoggingInterceptor : public experimental::Interceptor {
     methods->Proceed();
   }
 
+  static void VerifyCall(RPCType type) {
+    switch (type) {
+      case RPCType::kSyncUnary:
+      case RPCType::kAsyncCQUnary:
+        VerifyUnaryCall();
+        break;
+      case RPCType::kSyncClientStreaming:
+      case RPCType::kAsyncCQClientStreaming:
+        VerifyClientStreamingCall();
+        break;
+      case RPCType::kSyncServerStreaming:
+      case RPCType::kAsyncCQServerStreaming:
+        VerifyServerStreamingCall();
+        break;
+      case RPCType::kSyncBidiStreaming:
+      case RPCType::kAsyncCQBidiStreaming:
+        VerifyBidiStreamingCall();
+        break;
+    }
+  }
+
   static void VerifyCallCommon() {
     EXPECT_TRUE(pre_send_initial_metadata_);
     EXPECT_TRUE(pre_send_close_);
@@ -638,9 +683,31 @@ class LoggingInterceptorFactory
   }
 };
 
-class ClientInterceptorsEnd2endTest : public ::testing::Test {
+class TestScenario {
+ public:
+  explicit TestScenario(const RPCType& type) : type_(type) {}
+
+  RPCType type() const { return type_; }
+
+ private:
+  RPCType type_;
+};
+
+std::vector<TestScenario> CreateTestScenarios() {
+  std::vector<TestScenario> scenarios;
+  scenarios.emplace_back(RPCType::kSyncUnary);
+  scenarios.emplace_back(RPCType::kSyncClientStreaming);
+  scenarios.emplace_back(RPCType::kSyncServerStreaming);
+  scenarios.emplace_back(RPCType::kSyncBidiStreaming);
+  scenarios.emplace_back(RPCType::kAsyncCQUnary);
+  scenarios.emplace_back(RPCType::kAsyncCQServerStreaming);
+  return scenarios;
+}
+
+class ParameterizedClientInterceptorsEnd2endTest
+    : public ::testing::TestWithParam<TestScenario> {
  protected:
-  ClientInterceptorsEnd2endTest() {
+  ParameterizedClientInterceptorsEnd2endTest() {
     int port = grpc_pick_unused_port_or_die();
 
     ServerBuilder builder;
@@ -650,14 +717,44 @@ class ClientInterceptorsEnd2endTest : public ::testing::Test {
     server_ = builder.BuildAndStart();
   }
 
-  ~ClientInterceptorsEnd2endTest() { server_->Shutdown(); }
+  ~ParameterizedClientInterceptorsEnd2endTest() { server_->Shutdown(); }
+
+  void SendRPC(const std::shared_ptr<Channel>& channel) {
+    switch (GetParam().type()) {
+      case RPCType::kSyncUnary:
+        MakeCall(channel);
+        break;
+      case RPCType::kSyncClientStreaming:
+        MakeClientStreamingCall(channel);
+        break;
+      case RPCType::kSyncServerStreaming:
+        MakeServerStreamingCall(channel);
+        break;
+      case RPCType::kSyncBidiStreaming:
+        MakeBidiStreamingCall(channel);
+        break;
+      case RPCType::kAsyncCQUnary:
+        MakeAsyncCQCall(channel);
+        break;
+      case RPCType::kAsyncCQClientStreaming:
+        // TODO(yashykt) : Fill this out
+        break;
+      case RPCType::kAsyncCQServerStreaming:
+        MakeAsyncCQServerStreamingCall(channel);
+        break;
+      case RPCType::kAsyncCQBidiStreaming:
+        // TODO(yashykt) : Fill this out
+        break;
+    }
+  }
 
   std::string server_address_;
-  TestServiceImpl service_;
+  EchoTestServiceStreamingImpl service_;
   std::unique_ptr<Server> server_;
 };
 
-TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorLoggingTest) {
+TEST_P(ParameterizedClientInterceptorsEnd2endTest,
+       ClientInterceptorLoggingTest) {
   ChannelArguments args;
   DummyInterceptor::Reset();
   std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
@@ -671,12 +768,36 @@ TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorLoggingTest) {
   }
   auto channel = experimental::CreateCustomChannelWithInterceptors(
       server_address_, InsecureChannelCredentials(), args, std::move(creators));
-  MakeCall(channel);
-  LoggingInterceptor::VerifyUnaryCall();
+  SendRPC(channel);
+  LoggingInterceptor::VerifyCall(GetParam().type());
   // Make sure all 20 dummy interceptors were run
   EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20);
 }
 
+INSTANTIATE_TEST_SUITE_P(ParameterizedClientInterceptorsEnd2end,
+                         ParameterizedClientInterceptorsEnd2endTest,
+                         ::testing::ValuesIn(CreateTestScenarios()));
+
+class ClientInterceptorsEnd2endTest
+    : public ::testing::TestWithParam<TestScenario> {
+ protected:
+  ClientInterceptorsEnd2endTest() {
+    int port = grpc_pick_unused_port_or_die();
+
+    ServerBuilder builder;
+    server_address_ = "localhost:" + std::to_string(port);
+    builder.AddListeningPort(server_address_, InsecureServerCredentials());
+    builder.RegisterService(&service_);
+    server_ = builder.BuildAndStart();
+  }
+
+  ~ClientInterceptorsEnd2endTest() { server_->Shutdown(); }
+
+  std::string server_address_;
+  TestServiceImpl service_;
+  std::unique_ptr<Server> server_;
+};
+
 TEST_F(ClientInterceptorsEnd2endTest,
        LameChannelClientInterceptorHijackingTest) {
   ChannelArguments args;
@@ -757,7 +878,26 @@ TEST_F(ClientInterceptorsEnd2endTest,
   EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 12);
 }
 
-TEST_F(ClientInterceptorsEnd2endTest,
+class ClientInterceptorsCallbackEnd2endTest : public ::testing::Test {
+ protected:
+  ClientInterceptorsCallbackEnd2endTest() {
+    int port = grpc_pick_unused_port_or_die();
+
+    ServerBuilder builder;
+    server_address_ = "localhost:" + std::to_string(port);
+    builder.AddListeningPort(server_address_, InsecureServerCredentials());
+    builder.RegisterService(&service_);
+    server_ = builder.BuildAndStart();
+  }
+
+  ~ClientInterceptorsCallbackEnd2endTest() { server_->Shutdown(); }
+
+  std::string server_address_;
+  TestServiceImpl service_;
+  std::unique_ptr<Server> server_;
+};
+
+TEST_F(ClientInterceptorsCallbackEnd2endTest,
        ClientInterceptorLoggingTestWithCallback) {
   ChannelArguments args;
   DummyInterceptor::Reset();
@@ -778,7 +918,7 @@ TEST_F(ClientInterceptorsEnd2endTest,
   EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20);
 }
 
-TEST_F(ClientInterceptorsEnd2endTest,
+TEST_F(ClientInterceptorsCallbackEnd2endTest,
        ClientInterceptorFactoryAllowsNullptrReturn) {
   ChannelArguments args;
   DummyInterceptor::Reset();
@@ -903,6 +1043,21 @@ TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingHijackingTest) {
   EXPECT_TRUE(ServerStreamingRpcHijackingInterceptor::GotFailedMessage());
 }
 
+TEST_F(ClientInterceptorsStreamingEnd2endTest,
+       AsyncCQServerStreamingHijackingTest) {
+  ChannelArguments args;
+  DummyInterceptor::Reset();
+  std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+      creators;
+  creators.push_back(
+      std::unique_ptr<ServerStreamingRpcHijackingInterceptorFactory>(
+          new ServerStreamingRpcHijackingInterceptorFactory()));
+  auto channel = experimental::CreateCustomChannelWithInterceptors(
+      server_address_, InsecureChannelCredentials(), args, std::move(creators));
+  MakeAsyncCQServerStreamingCall(channel);
+  EXPECT_TRUE(ServerStreamingRpcHijackingInterceptor::GotFailedMessage());
+}
+
 TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingHijackingTest) {
   ChannelArguments args;
   DummyInterceptor::Reset();
index d066a00..e6c2880 100644 (file)
@@ -233,9 +233,6 @@ class ClientLbEnd2endTest : public ::testing::Test {
     for (size_t i = 0; i < servers_.size(); ++i) {
       servers_[i]->Shutdown();
     }
-    // Explicitly destroy all the members so that we can make sure grpc_shutdown
-    // has finished by the end of this function, and thus all the registered
-    // LB policy factories are removed.
     servers_.clear();
     creds_.reset();
     grpc_shutdown_blocking();
@@ -1639,12 +1636,19 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest {
  protected:
   void SetUp() override {
     ClientLbEnd2endTest::SetUp();
-    grpc_core::RegisterInterceptRecvTrailingMetadataLoadBalancingPolicy(
-        ReportTrailerIntercepted, this);
+    current_test_instance_ = this;
   }
 
   void TearDown() override { ClientLbEnd2endTest::TearDown(); }
 
+  static void SetUpTestCase() {
+    grpc_init();
+    grpc_core::RegisterInterceptRecvTrailingMetadataLoadBalancingPolicy(
+        ReportTrailerIntercepted, nullptr);
+  }
+
+  static void TearDownTestCase() { grpc_shutdown_blocking(); }
+
   int trailers_intercepted() {
     grpc::internal::MutexLock lock(&mu_);
     return trailers_intercepted_;
@@ -1659,8 +1663,7 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest {
   static void ReportTrailerIntercepted(
       void* arg, const grpc_core::LoadBalancingPolicy::BackendMetricData*
                      backend_metric_data) {
-    ClientLbInterceptTrailingMetadataTest* self =
-        static_cast<ClientLbInterceptTrailingMetadataTest*>(arg);
+    ClientLbInterceptTrailingMetadataTest* self = current_test_instance_;
     grpc::internal::MutexLock lock(&self->mu_);
     self->trailers_intercepted_++;
     if (backend_metric_data != nullptr) {
@@ -1671,23 +1674,27 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest {
           backend_metric_data->mem_utilization);
       self->load_report_->set_rps(backend_metric_data->requests_per_second);
       for (const auto& p : backend_metric_data->request_cost) {
-        grpc_core::UniquePtr<char> name =
-            grpc_core::StringViewToCString(p.first);
-        (*self->load_report_->mutable_request_cost())[name.get()] = p.second;
+        std::string name = std::string(p.first);
+        (*self->load_report_->mutable_request_cost())[std::move(name)] =
+            p.second;
       }
       for (const auto& p : backend_metric_data->utilization) {
-        grpc_core::UniquePtr<char> name =
-            grpc_core::StringViewToCString(p.first);
-        (*self->load_report_->mutable_utilization())[name.get()] = p.second;
+        std::string name = std::string(p.first);
+        (*self->load_report_->mutable_utilization())[std::move(name)] =
+            p.second;
       }
     }
   }
 
+  static ClientLbInterceptTrailingMetadataTest* current_test_instance_;
   grpc::internal::Mutex mu_;
   int trailers_intercepted_ = 0;
   std::unique_ptr<udpa::data::orca::v1::OrcaLoadReport> load_report_;
 };
 
+ClientLbInterceptTrailingMetadataTest*
+    ClientLbInterceptTrailingMetadataTest::current_test_instance_ = nullptr;
+
 TEST_F(ClientLbInterceptTrailingMetadataTest, InterceptsRetriesDisabled) {
   const int kNumServers = 1;
   const int kNumRpcs = 10;
index 3d5b6f8..ac72768 100644 (file)
@@ -618,11 +618,17 @@ class GrpclbEnd2endTest : public ::testing::Test {
   }
 
   Status SendRpc(EchoResponse* response = nullptr, int timeout_ms = 1000,
-                 bool wait_for_ready = false) {
+                 bool wait_for_ready = false,
+                 const Status& expected_status = Status::OK) {
     const bool local_response = (response == nullptr);
     if (local_response) response = new EchoResponse;
     EchoRequest request;
     request.set_message(kRequestMessage_);
+    if (!expected_status.ok()) {
+      auto* error = request.mutable_param()->mutable_expected_error();
+      error->set_code(expected_status.error_code());
+      error->set_error_message(expected_status.error_message());
+    }
     ClientContext context;
     context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms));
     if (wait_for_ready) context.set_wait_for_ready(true);
@@ -751,6 +757,22 @@ TEST_F(SingleBalancerTest, Vanilla) {
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
 }
 
+TEST_F(SingleBalancerTest, ReturnServerStatus) {
+  SetNextResolutionAllBalancers();
+  ScheduleResponseForBalancer(
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
+      0);
+  // We need to wait for all backends to come online.
+  WaitForAllBackends();
+  // Send a request that the backend will fail, and make sure we get
+  // back the right status.
+  Status expected(StatusCode::INVALID_ARGUMENT, "He's dead, Jim!");
+  Status actual = SendRpc(/*response=*/nullptr, /*timeout_ms=*/1000,
+                          /*wait_for_ready=*/false, expected);
+  EXPECT_EQ(actual.error_code(), expected.error_code());
+  EXPECT_EQ(actual.error_message(), expected.error_message());
+}
+
 TEST_F(SingleBalancerTest, SelectGrpclbWithMigrationServiceConfig) {
   SetNextResolutionAllBalancers(
       "{\n"
@@ -868,84 +890,6 @@ TEST_F(SingleBalancerTest, SwapChildPolicy) {
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
 }
 
-TEST_F(SingleBalancerTest, UpdatesGoToMostRecentChildPolicy) {
-  const int kFallbackTimeoutMs = 200 * grpc_test_slowdown_factor();
-  ResetStub(kFallbackTimeoutMs);
-  int unreachable_balancer_port = grpc_pick_unused_port_or_die();
-  int unreachable_backend_port = grpc_pick_unused_port_or_die();
-  // Phase 1: Start with RR pointing to first backend.
-  gpr_log(GPR_INFO, "PHASE 1: Initial setup with RR with first backend");
-  SetNextResolution(
-      {
-          // Unreachable balancer.
-          {unreachable_balancer_port, ""},
-      },
-      {
-          // Fallback address: first backend.
-          {backends_[0]->port_, ""},
-      },
-      "{\n"
-      "  \"loadBalancingConfig\":[\n"
-      "    { \"grpclb\":{\n"
-      "      \"childPolicy\":[\n"
-      "        { \"round_robin\":{} }\n"
-      "      ]\n"
-      "    } }\n"
-      "  ]\n"
-      "}");
-  // RPCs should go to first backend.
-  WaitForBackend(0);
-  // Phase 2: Switch to PF pointing to unreachable backend.
-  gpr_log(GPR_INFO, "PHASE 2: Update to use PF with unreachable backend");
-  SetNextResolution(
-      {
-          // Unreachable balancer.
-          {unreachable_balancer_port, ""},
-      },
-      {
-          // Fallback address: unreachable backend.
-          {unreachable_backend_port, ""},
-      },
-      "{\n"
-      "  \"loadBalancingConfig\":[\n"
-      "    { \"grpclb\":{\n"
-      "      \"childPolicy\":[\n"
-      "        { \"pick_first\":{} }\n"
-      "      ]\n"
-      "    } }\n"
-      "  ]\n"
-      "}");
-  // RPCs should continue to go to the first backend, because the new
-  // PF child policy will never go into state READY.
-  WaitForBackend(0);
-  // Phase 3: Switch back to RR pointing to second and third backends.
-  // This ensures that we create a new policy rather than updating the
-  // pending PF policy.
-  gpr_log(GPR_INFO, "PHASE 3: Update to use RR again with two backends");
-  SetNextResolution(
-      {
-          // Unreachable balancer.
-          {unreachable_balancer_port, ""},
-      },
-      {
-          // Fallback address: second and third backends.
-          {backends_[1]->port_, ""},
-          {backends_[2]->port_, ""},
-      },
-      "{\n"
-      "  \"loadBalancingConfig\":[\n"
-      "    { \"grpclb\":{\n"
-      "      \"childPolicy\":[\n"
-      "        { \"round_robin\":{} }\n"
-      "      ]\n"
-      "    } }\n"
-      "  ]\n"
-      "}");
-  // RPCs should go to the second and third backends.
-  WaitForBackend(1);
-  WaitForBackend(2);
-}
-
 TEST_F(SingleBalancerTest, SameBackendListedMultipleTimes) {
   SetNextResolutionAllBalancers();
   // Same backend listed twice.
index 6321c35..7d74a48 100644 (file)
@@ -66,7 +66,6 @@ void MakeServerStreamingCall(const std::shared_ptr<Channel>& channel) {
   ctx.AddMetadata("testkey", "testvalue");
   req.set_message("Hello");
   EchoResponse resp;
-  string expected_resp = "";
   auto reader = stub->ResponseStream(&ctx, req);
   int count = 0;
   while (reader->Read(&resp)) {
@@ -84,6 +83,7 @@ void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel) {
   EchoRequest req;
   EchoResponse resp;
   ctx.AddMetadata("testkey", "testvalue");
+  req.mutable_param()->set_echo_metadata(true);
   auto stream = stub->BidiStream(&ctx);
   for (auto i = 0; i < kNumStreamingMessages; i++) {
     req.set_message("Hello" + std::to_string(i));
@@ -96,6 +96,60 @@ void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel) {
   EXPECT_EQ(s.ok(), true);
 }
 
+void MakeAsyncCQCall(const std::shared_ptr<Channel>& channel) {
+  auto stub = grpc::testing::EchoTestService::NewStub(channel);
+  CompletionQueue cq;
+  EchoRequest send_request;
+  EchoResponse recv_response;
+  Status recv_status;
+  ClientContext cli_ctx;
+
+  send_request.set_message("Hello");
+  cli_ctx.AddMetadata("testkey", "testvalue");
+  std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
+      stub->AsyncEcho(&cli_ctx, send_request, &cq));
+  response_reader->Finish(&recv_response, &recv_status, tag(1));
+  Verifier().Expect(1, true).Verify(&cq);
+  EXPECT_EQ(send_request.message(), recv_response.message());
+  EXPECT_TRUE(recv_status.ok());
+}
+
+void MakeAsyncCQClientStreamingCall(const std::shared_ptr<Channel>& channel) {
+  // TODO(yashykt) : Fill this out
+}
+
+void MakeAsyncCQServerStreamingCall(const std::shared_ptr<Channel>& channel) {
+  auto stub = grpc::testing::EchoTestService::NewStub(channel);
+  CompletionQueue cq;
+  EchoRequest send_request;
+  EchoResponse recv_response;
+  Status recv_status;
+  ClientContext cli_ctx;
+
+  cli_ctx.AddMetadata("testkey", "testvalue");
+  send_request.set_message("Hello");
+  std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream(
+      stub->AsyncResponseStream(&cli_ctx, send_request, &cq, tag(1)));
+  Verifier().Expect(1, true).Verify(&cq);
+  // Read the expected number of messages
+  for (int i = 0; i < kNumStreamingMessages; i++) {
+    cli_stream->Read(&recv_response, tag(2));
+    Verifier().Expect(2, true).Verify(&cq);
+    ASSERT_EQ(recv_response.message(), send_request.message());
+  }
+  // The next read should fail
+  cli_stream->Read(&recv_response, tag(3));
+  Verifier().Expect(3, false).Verify(&cq);
+  // Get the status
+  cli_stream->Finish(&recv_status, tag(4));
+  Verifier().Expect(4, true).Verify(&cq);
+  EXPECT_TRUE(recv_status.ok());
+}
+
+void MakeAsyncCQBidiStreamingCall(const std::shared_ptr<Channel>& channel) {
+  // TODO(yashykt) : Fill this out
+}
+
 void MakeCallbackCall(const std::shared_ptr<Channel>& channel) {
   auto stub = grpc::testing::EchoTestService::NewStub(channel);
   ClientContext ctx;
@@ -109,7 +163,6 @@ void MakeCallbackCall(const std::shared_ptr<Channel>& channel) {
   EchoResponse resp;
   stub->experimental_async()->Echo(&ctx, &req, &resp,
                                    [&resp, &mu, &done, &cv](Status s) {
-                                     // gpr_log(GPR_ERROR, "got the callback");
                                      EXPECT_EQ(s.ok(), true);
                                      EXPECT_EQ(resp.message(), "Hello");
                                      std::lock_guard<std::mutex> l(mu);
index 6027c9b..2aafea2 100644 (file)
@@ -102,6 +102,16 @@ class EchoTestServiceStreamingImpl : public EchoTestService::Service {
  public:
   ~EchoTestServiceStreamingImpl() override {}
 
+  Status Echo(ServerContext* context, const EchoRequest* request,
+              EchoResponse* response) override {
+    auto client_metadata = context->client_metadata();
+    for (const auto& pair : client_metadata) {
+      context->AddTrailingMetadata(ToString(pair.first), ToString(pair.second));
+    }
+    response->set_message(request->message());
+    return Status::OK;
+  }
+
   Status BidiStream(
       ServerContext* context,
       grpc::ServerReaderWriter<EchoResponse, EchoRequest>* stream) override {
@@ -162,6 +172,14 @@ void MakeServerStreamingCall(const std::shared_ptr<Channel>& channel);
 
 void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel);
 
+void MakeAsyncCQCall(const std::shared_ptr<Channel>& channel);
+
+void MakeAsyncCQClientStreamingCall(const std::shared_ptr<Channel>& channel);
+
+void MakeAsyncCQServerStreamingCall(const std::shared_ptr<Channel>& channel);
+
+void MakeAsyncCQBidiStreamingCall(const std::shared_ptr<Channel>& channel);
+
 void MakeCallbackCall(const std::shared_ptr<Channel>& channel);
 
 bool CheckMetadata(const std::multimap<grpc::string_ref, grpc::string_ref>& map,
index 29e3eb8..a163c49 100644 (file)
@@ -225,10 +225,8 @@ class CountedService : public ServiceType {
     response_count_ = 0;
   }
 
- protected:
-  grpc_core::Mutex mu_;
-
  private:
+  grpc_core::Mutex mu_;
   size_t request_count_ = 0;
   size_t response_count_ = 0;
 };
@@ -286,7 +284,6 @@ class BackendServiceImpl
     clients_.insert(client);
   }
 
-  grpc_core::Mutex mu_;
   grpc_core::Mutex clients_mu_;
   std::set<grpc::string> clients_;
 };
@@ -378,11 +375,10 @@ class ClientStats {
 class AdsServiceImpl : public AggregatedDiscoveryService::Service,
                        public std::enable_shared_from_this<AdsServiceImpl> {
  public:
-  enum ResponseState {
-    NOT_SENT,
-    SENT,
-    ACKED,
-    NACKED,
+  struct ResponseState {
+    enum State { NOT_SENT, SENT, ACKED, NACKED };
+    State state = NOT_SENT;
+    std::string error_message;
   };
 
   struct EdsResourceArgs {
@@ -424,10 +420,10 @@ class AdsServiceImpl : public AggregatedDiscoveryService::Service,
     auto* route = virtual_host->add_routes();
     route->mutable_match()->set_prefix("");
     route->mutable_route()->set_cluster(kDefaultResourceName);
-    SetRdsResource(default_route_config_, kDefaultResourceName);
+    SetRdsResource(default_route_config_);
     // Construct LDS response data (with inlined RDS result).
     default_listener_ = BuildListener(default_route_config_);
-    SetLdsResource(default_listener_, kDefaultResourceName);
+    SetLdsResource(default_listener_);
     // Construct CDS response data.
     default_cluster_.set_name(kDefaultResourceName);
     default_cluster_.set_type(envoy::api::v2::Cluster::EDS);
@@ -438,7 +434,7 @@ class AdsServiceImpl : public AggregatedDiscoveryService::Service,
     if (enable_load_reporting) {
       default_cluster_.mutable_lrs_server()->mutable_self();
     }
-    SetCdsResource(default_cluster_, kDefaultResourceName);
+    SetCdsResource(default_cluster_);
   }
 
   Status StreamAggregatedResources(ServerContext* context,
@@ -490,11 +486,15 @@ class AdsServiceImpl : public AggregatedDiscoveryService::Service,
             // comparing it to nonce (this server ensures they are always set to
             // the same in a response.)
             if (!request.response_nonce().empty()) {
-              resource_type_response_state_[request.type_url()] =
+              resource_type_response_state_[request.type_url()].state =
                   (!request.version_info().empty() &&
                    request.version_info() == request.response_nonce())
-                      ? ACKED
-                      : NACKED;
+                      ? ResponseState::ACKED
+                      : ResponseState::NACKED;
+            }
+            if (request.has_error_detail()) {
+              resource_type_response_state_[request.type_url()].error_message =
+                  request.error_detail().message();
             }
             // As long as the test did not tell us to ignore this type of
             // request, we will loop through all resources to:
@@ -684,40 +684,39 @@ class AdsServiceImpl : public AggregatedDiscoveryService::Service,
     }
   }
 
-  void SetLdsResource(const Listener& listener, const std::string& name) {
+  void SetLdsResource(const Listener& listener) {
     google::protobuf::Any resource;
     resource.PackFrom(listener);
-    SetResource(std::move(resource), kLdsTypeUrl, name);
+    SetResource(std::move(resource), kLdsTypeUrl, listener.name());
   }
 
-  void SetRdsResource(const RouteConfiguration& route,
-                      const std::string& name) {
+  void SetRdsResource(const RouteConfiguration& route) {
     google::protobuf::Any resource;
     resource.PackFrom(route);
-    SetResource(std::move(resource), kRdsTypeUrl, name);
+    SetResource(std::move(resource), kRdsTypeUrl, route.name());
   }
 
-  void SetCdsResource(const Cluster& cluster, const std::string& name) {
+  void SetCdsResource(const Cluster& cluster) {
     google::protobuf::Any resource;
     resource.PackFrom(cluster);
-    SetResource(std::move(resource), kCdsTypeUrl, name);
+    SetResource(std::move(resource), kCdsTypeUrl, cluster.name());
   }
 
-  void SetEdsResource(const ClusterLoadAssignment& assignment,
-                      const std::string& name) {
+  void SetEdsResource(const ClusterLoadAssignment& assignment) {
     google::protobuf::Any resource;
     resource.PackFrom(assignment);
-    SetResource(std::move(resource), kEdsTypeUrl, name);
+    SetResource(std::move(resource), kEdsTypeUrl, assignment.cluster_name());
   }
 
   void SetLdsToUseDynamicRds() {
     auto listener = default_listener_;
     HttpConnectionManager http_connection_manager;
-    http_connection_manager.mutable_rds()->set_route_config_name(
-        kDefaultResourceName);
+    auto* rds = http_connection_manager.mutable_rds();
+    rds->set_route_config_name(kDefaultResourceName);
+    rds->mutable_config_source()->mutable_ads();
     listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
         http_connection_manager);
-    SetLdsResource(listener, kDefaultResourceName);
+    SetLdsResource(listener);
   }
 
   static Listener BuildListener(const RouteConfiguration& route_config) {
@@ -923,7 +922,10 @@ class AdsServiceImpl : public AggregatedDiscoveryService::Service,
       const SubscriptionNameMap& subscription_name_map,
       const std::set<std::string>& resources_added_to_response,
       DiscoveryResponse* response) {
-    resource_type_response_state_[resource_type] = SENT;
+    auto& response_state = resource_type_response_state_[resource_type];
+    if (response_state.state == ResponseState::NOT_SENT) {
+      response_state.state = ResponseState::SENT;
+    }
     response->set_type_url(resource_type);
     response->set_version_info(absl::StrCat(version));
     response->set_nonce(absl::StrCat(version));
@@ -952,7 +954,7 @@ class AdsServiceImpl : public AggregatedDiscoveryService::Service,
   Listener default_listener_;
   RouteConfiguration default_route_config_;
   Cluster default_cluster_;
-  std::map<std::string /*resource type*/, ResponseState>
+  std::map<std::string /* type_url */, ResponseState>
       resource_type_response_state_;
   std::set<std::string /*resource_type*/> resource_types_to_ignore_;
   // An instance data member containing the current state of all resources.
@@ -988,10 +990,17 @@ class LrsServiceImpl : public LrsService,
           request.node().metadata().fields().find("PROXYLESS_CLIENT_HOSTNAME");
       GPR_ASSERT(it != request.node().metadata().fields().end());
       EXPECT_EQ(it->second.string_value(), kDefaultResourceName);
+      // Verify client features.
+      EXPECT_THAT(request.node().client_features(),
+                  ::testing::Contains("envoy.lrs.supports_send_all_clusters"));
       // Send initial response.
       LoadStatsResponse response;
-      for (const std::string& cluster_name : cluster_names_) {
-        response.add_clusters(cluster_name);
+      if (send_all_clusters_) {
+        response.set_send_all_clusters(true);
+      } else {
+        for (const std::string& cluster_name : cluster_names_) {
+          response.add_clusters(cluster_name);
+        }
       }
       response.mutable_load_reporting_interval()->set_seconds(
           client_load_reporting_interval_seconds_);
@@ -1019,6 +1028,9 @@ class LrsServiceImpl : public LrsService,
   }
 
   // Must be called before the LRS call is started.
+  void set_send_all_clusters(bool send_all_clusters) {
+    send_all_clusters_ = send_all_clusters;
+  }
   void set_cluster_names(const std::set<std::string>& cluster_names) {
     cluster_names_ = cluster_names;
   }
@@ -1064,6 +1076,7 @@ class LrsServiceImpl : public LrsService,
   }
 
   const int client_load_reporting_interval_seconds_;
+  bool send_all_clusters_ = false;
   std::set<std::string> cluster_names_;
 
   grpc_core::CondVar lrs_cv_;
@@ -1077,22 +1090,27 @@ class LrsServiceImpl : public LrsService,
 
 class TestType {
  public:
-  TestType(bool use_xds_resolver, bool enable_load_reporting)
+  TestType(bool use_xds_resolver, bool enable_load_reporting,
+           bool enable_rds_testing = false)
       : use_xds_resolver_(use_xds_resolver),
-        enable_load_reporting_(enable_load_reporting) {}
+        enable_load_reporting_(enable_load_reporting),
+        enable_rds_testing_(enable_rds_testing) {}
 
   bool use_xds_resolver() const { return use_xds_resolver_; }
   bool enable_load_reporting() const { return enable_load_reporting_; }
+  bool enable_rds_testing() const { return enable_rds_testing_; }
 
   grpc::string AsString() const {
     grpc::string retval = (use_xds_resolver_ ? "XdsResolver" : "FakeResolver");
     if (enable_load_reporting_) retval += "WithLoadReporting";
+    if (enable_rds_testing_) retval += "Rds";
     return retval;
   }
 
  private:
   const bool use_xds_resolver_;
   const bool enable_load_reporting_;
+  const bool enable_rds_testing_;
 };
 
 class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
@@ -1136,6 +1154,9 @@ class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
                                        ? client_load_reporting_interval_seconds_
                                        : 0));
       balancers_.back()->Start();
+      if (GetParam().enable_rds_testing()) {
+        balancers_[i]->ads_service()->SetLdsToUseDynamicRds();
+      }
     }
     ResetStub();
   }
@@ -1159,8 +1180,7 @@ class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
 
   void ResetStub(int failover_timeout = 0,
                  const grpc::string& expected_targets = "",
-                 int xds_resource_does_not_exist_timeout = 0,
-                 bool xds_routing_enabled = false) {
+                 int xds_resource_does_not_exist_timeout = 0) {
     ChannelArguments args;
     if (failover_timeout > 0) {
       args.SetInt(GRPC_ARG_PRIORITY_FAILOVER_TIMEOUT_MS, failover_timeout);
@@ -1169,9 +1189,6 @@ class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
       args.SetInt(GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS,
                   xds_resource_does_not_exist_timeout);
     }
-    if (xds_routing_enabled) {
-      args.SetInt(GRPC_ARG_XDS_ROUTING_ENABLED, 1);
-    }
     // If the parent channel is using the fake resolver, we inject the
     // response generator for the parent here, and then SetNextResolution()
     // will inject the xds channel's response generator via the parent's
@@ -1187,8 +1204,7 @@ class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
     if (!expected_targets.empty()) {
       args.SetString(GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS, expected_targets);
     }
-    grpc::string scheme =
-        GetParam().use_xds_resolver() ? "xds-experimental" : "fake";
+    grpc::string scheme = GetParam().use_xds_resolver() ? "xds" : "fake";
     std::ostringstream uri;
     uri << scheme << ":///" << kApplicationTargetName_;
     // TODO(dgq): templatize tests to run everything using both secure and
@@ -1208,21 +1224,102 @@ class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
     stub2_ = grpc::testing::EchoTest2Service::NewStub(channel_);
   }
 
-  void ResetBackendCounters() {
-    for (auto& backend : backends_) backend->backend_service()->ResetCounters();
+  enum RpcService {
+    SERVICE_ECHO,
+    SERVICE_ECHO1,
+    SERVICE_ECHO2,
+  };
+
+  enum RpcMethod {
+    METHOD_ECHO,
+    METHOD_ECHO1,
+    METHOD_ECHO2,
+  };
+
+  struct RpcOptions {
+    RpcService service = SERVICE_ECHO;
+    RpcMethod method = METHOD_ECHO;
+    int timeout_ms = 1000;
+    bool wait_for_ready = false;
+    bool server_fail = false;
+
+    RpcOptions() {}
+
+    RpcOptions& set_rpc_service(RpcService rpc_service) {
+      service = rpc_service;
+      return *this;
+    }
+
+    RpcOptions& set_rpc_method(RpcMethod rpc_method) {
+      method = rpc_method;
+      return *this;
+    }
+
+    RpcOptions& set_timeout_ms(int rpc_timeout_ms) {
+      timeout_ms = rpc_timeout_ms;
+      return *this;
+    }
+
+    RpcOptions& set_wait_for_ready(bool rpc_wait_for_ready) {
+      wait_for_ready = rpc_wait_for_ready;
+      return *this;
+    }
+
+    RpcOptions& set_server_fail(bool rpc_server_fail) {
+      server_fail = rpc_server_fail;
+      return *this;
+    }
+  };
+
+  template <typename Stub>
+  Status SendRpcMethod(Stub* stub, const RpcOptions& rpc_options,
+                       ClientContext* context, EchoRequest& request,
+                       EchoResponse* response) {
+    switch (rpc_options.method) {
+      case METHOD_ECHO:
+        return (*stub)->Echo(context, request, response);
+      case METHOD_ECHO1:
+        return (*stub)->Echo1(context, request, response);
+      case METHOD_ECHO2:
+        return (*stub)->Echo2(context, request, response);
+    }
+  }
+
+  void ResetBackendCounters(size_t start_index = 0, size_t stop_index = 0) {
+    if (stop_index == 0) stop_index = backends_.size();
+    for (size_t i = start_index; i < stop_index; ++i) {
+      backends_[i]->backend_service()->ResetCounters();
+      backends_[i]->backend_service1()->ResetCounters();
+      backends_[i]->backend_service2()->ResetCounters();
+    }
   }
 
-  bool SeenAllBackends(size_t start_index = 0, size_t stop_index = 0) {
+  bool SeenAllBackends(size_t start_index = 0, size_t stop_index = 0,
+                       const RpcOptions& rpc_options = RpcOptions()) {
     if (stop_index == 0) stop_index = backends_.size();
     for (size_t i = start_index; i < stop_index; ++i) {
-      if (backends_[i]->backend_service()->request_count() == 0) return false;
+      switch (rpc_options.service) {
+        case SERVICE_ECHO:
+          if (backends_[i]->backend_service()->request_count() == 0)
+            return false;
+          break;
+        case SERVICE_ECHO1:
+          if (backends_[i]->backend_service1()->request_count() == 0)
+            return false;
+          break;
+        case SERVICE_ECHO2:
+          if (backends_[i]->backend_service2()->request_count() == 0)
+            return false;
+          break;
+      }
     }
     return true;
   }
 
   void SendRpcAndCount(int* num_total, int* num_ok, int* num_failure,
-                       int* num_drops) {
-    const Status status = SendRpc();
+                       int* num_drops,
+                       const RpcOptions& rpc_options = RpcOptions()) {
+    const Status status = SendRpc(rpc_options);
     if (status.ok()) {
       ++*num_ok;
     } else {
@@ -1235,15 +1332,16 @@ class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
     ++*num_total;
   }
 
-  std::tuple<int, int, int> WaitForAllBackends(size_t start_index = 0,
-                                               size_t stop_index = 0,
-                                               bool reset_counters = true) {
+  std::tuple<int, int, int> WaitForAllBackends(
+      size_t start_index = 0, size_t stop_index = 0, bool reset_counters = true,
+      const RpcOptions& rpc_options = RpcOptions()) {
     int num_ok = 0;
     int num_failure = 0;
     int num_drops = 0;
     int num_total = 0;
-    while (!SeenAllBackends(start_index, stop_index)) {
-      SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_drops);
+    while (!SeenAllBackends(start_index, stop_index, rpc_options)) {
+      SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_drops,
+                      rpc_options);
     }
     if (reset_counters) ResetBackendCounters();
     gpr_log(GPR_INFO,
@@ -1359,67 +1457,6 @@ class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
     return backend_ports;
   }
 
-  enum RpcService {
-    SERVICE_ECHO,
-    SERVICE_ECHO1,
-    SERVICE_ECHO2,
-  };
-
-  enum RpcMethod {
-    METHOD_ECHO,
-    METHOD_ECHO1,
-    METHOD_ECHO2,
-  };
-
-  struct RpcOptions {
-    RpcService service = SERVICE_ECHO;
-    RpcMethod method = METHOD_ECHO;
-    int timeout_ms = 1000;
-    bool wait_for_ready = false;
-    bool server_fail = false;
-
-    RpcOptions() {}
-
-    RpcOptions& set_rpc_service(RpcService rpc_service) {
-      service = rpc_service;
-      return *this;
-    }
-
-    RpcOptions& set_rpc_method(RpcMethod rpc_method) {
-      method = rpc_method;
-      return *this;
-    }
-
-    RpcOptions& set_timeout_ms(int rpc_timeout_ms) {
-      timeout_ms = rpc_timeout_ms;
-      return *this;
-    }
-
-    RpcOptions& set_wait_for_ready(bool rpc_wait_for_ready) {
-      wait_for_ready = rpc_wait_for_ready;
-      return *this;
-    }
-
-    RpcOptions& set_server_fail(bool rpc_server_fail) {
-      server_fail = rpc_server_fail;
-      return *this;
-    }
-  };
-
-  template <typename Stub>
-  Status SendRpcMethod(Stub* stub, const RpcOptions& rpc_options,
-                       ClientContext* context, EchoRequest& request,
-                       EchoResponse* response) {
-    switch (rpc_options.method) {
-      case METHOD_ECHO:
-        return (*stub)->Echo(context, request, response);
-      case METHOD_ECHO1:
-        return (*stub)->Echo1(context, request, response);
-      case METHOD_ECHO2:
-        return (*stub)->Echo2(context, request, response);
-    }
-  }
-
   Status SendRpc(const RpcOptions& rpc_options = RpcOptions(),
                  EchoResponse* response = nullptr) {
     const bool local_response = (response == nullptr);
@@ -1471,15 +1508,32 @@ class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
     }
   }
 
+  void SetRouteConfiguration(int idx, const RouteConfiguration& route_config) {
+    if (GetParam().enable_rds_testing()) {
+      balancers_[idx]->ads_service()->SetRdsResource(route_config);
+    } else {
+      balancers_[idx]->ads_service()->SetLdsResource(
+          AdsServiceImpl::BuildListener(route_config));
+    }
+  }
+
+  AdsServiceImpl::ResponseState RouteConfigurationResponseState(int idx) const {
+    AdsServiceImpl* ads_service = balancers_[idx]->ads_service();
+    if (GetParam().enable_rds_testing()) {
+      return ads_service->rds_response_state();
+    }
+    return ads_service->lds_response_state();
+  }
+
  public:
   // This method could benefit test subclasses; to make it accessible
   // via bind with a qualified name, it needs to be public.
   void SetEdsResourceWithDelay(size_t i,
                                const ClusterLoadAssignment& assignment,
-                               int delay_ms, const std::string& name) {
+                               int delay_ms) {
     GPR_ASSERT(delay_ms > 0);
     gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(delay_ms));
-    balancers_[i]->ads_service()->SetEdsResource(assignment, name);
+    balancers_[i]->ads_service()->SetEdsResource(assignment);
   }
 
  protected:
@@ -1670,7 +1724,7 @@ TEST_P(BasicTest, Vanilla) {
       {"locality0", GetBackendPorts()},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Make sure that trying to connect works without a call.
   channel_->GetState(true /* try_to_connect */);
   // We need to wait for all backends to come online.
@@ -1700,7 +1754,7 @@ TEST_P(BasicTest, IgnoresUnhealthyEndpoints) {
        {envoy::api::v2::HealthStatus::DRAINING}},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Make sure that trying to connect works without a call.
   channel_->GetState(true /* try_to_connect */);
   // We need to wait for all backends to come online.
@@ -1726,7 +1780,7 @@ TEST_P(BasicTest, SameBackendListedMultipleTimes) {
   });
   const size_t kNumRpcsPerAddress = 10;
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // We need to wait for the backend to come online.
   WaitForBackend(0);
   // Send kNumRpcsPerAddress RPCs per server.
@@ -1751,15 +1805,14 @@ TEST_P(BasicTest, InitiallyEmptyServerlist) {
       empty_locality,
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Send non-empty serverlist only after kServerlistDelayMs.
   args = AdsServiceImpl::EdsResourceArgs({
       {"locality0", GetBackendPorts()},
   });
   std::thread delayed_resource_setter(
       std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
-                AdsServiceImpl::BuildEdsResource(args), kServerlistDelayMs,
-                kDefaultResourceName));
+                AdsServiceImpl::BuildEdsResource(args), kServerlistDelayMs));
   const auto t0 = system_clock::now();
   // Client will block: LB will initially send empty serverlist.
   CheckRpcSendOk(
@@ -1789,7 +1842,7 @@ TEST_P(BasicTest, AllServersUnreachableFailFast) {
       {"locality0", ports},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   const Status status = SendRpc();
   // The error shouldn't be DEADLINE_EXCEEDED.
   EXPECT_EQ(StatusCode::UNAVAILABLE, status.error_code());
@@ -1804,11 +1857,20 @@ TEST_P(BasicTest, BackendsRestart) {
       {"locality0", GetBackendPorts()},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   WaitForAllBackends();
   // Stop backends.  RPCs should fail.
   ShutdownAllBackends();
-  CheckRpcSendFailure();
+  // Sending multiple failed requests instead of just one to ensure that the
+  // client notices that all backends are down before we restart them. If we
+  // didn't do this, then a single RPC could fail here due to the race condition
+  // between the LB pick and the GOAWAY from the chosen backend being shut down,
+  // which would not actually prove that the client noticed that all of the
+  // backends are down. Then, when we send another request below (which we
+  // expect to succeed), if the callbacks happen in the wrong order, the same
+  // race condition could happen again due to the client not yet having noticed
+  // that the backends were all down.
+  CheckRpcSendFailure(num_backends_);
   // Restart all backends.  RPCs should start succeeding again.
   StartAllBackends();
   CheckRpcSendOk(1, RpcOptions().set_timeout_ms(2000).set_wait_for_ready(true));
@@ -1825,7 +1887,7 @@ TEST_P(XdsResolverOnlyTest, ChangeClusters) {
       {"locality0", GetBackendPorts(0, 2)},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // We need to wait for all backends to come online.
   WaitForAllBackends(0, 2);
   // Populate new EDS resource.
@@ -1833,12 +1895,11 @@ TEST_P(XdsResolverOnlyTest, ChangeClusters) {
       {"locality0", GetBackendPorts(2, 4)},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args2, kNewClusterName),
-      kNewClusterName);
+      AdsServiceImpl::BuildEdsResource(args2, kNewClusterName));
   // Populate new CDS resource.
   Cluster new_cluster = balancers_[0]->ads_service()->default_cluster();
   new_cluster.set_name(kNewClusterName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster, kNewClusterName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
   // Change RDS resource to point to new cluster.
   RouteConfiguration new_route_config =
       balancers_[0]->ads_service()->default_route_config();
@@ -1848,14 +1909,14 @@ TEST_P(XdsResolverOnlyTest, ChangeClusters) {
       ->set_cluster(kNewClusterName);
   Listener listener =
       balancers_[0]->ads_service()->BuildListener(new_route_config);
-  balancers_[0]->ads_service()->SetLdsResource(listener, kDefaultResourceName);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
   // Wait for all new backends to be used.
   std::tuple<int, int, int> counts = WaitForAllBackends(2, 4);
   // Make sure no RPCs failed in the transition.
   EXPECT_EQ(0, std::get<1>(counts));
 }
 
-// Tests that things keep workng if the cluster resource disappears.
+// Tests that we go into TRANSIENT_FAILURE if the Cluster disappears.
 TEST_P(XdsResolverOnlyTest, ClusterRemoved) {
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
@@ -1863,17 +1924,20 @@ TEST_P(XdsResolverOnlyTest, ClusterRemoved) {
       {"locality0", GetBackendPorts()},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // We need to wait for all backends to come online.
   WaitForAllBackends();
   // Unset CDS resource.
   balancers_[0]->ads_service()->UnsetResource(kCdsTypeUrl,
                                               kDefaultResourceName);
-  // Make sure RPCs are still succeeding.
-  CheckRpcSendOk(100 * num_backends_);
+  // Wait for RPCs to start failing.
+  do {
+  } while (SendRpc(RpcOptions(), nullptr).ok());
+  // Make sure RPCs are still failing.
+  CheckRpcSendFailure(1000);
   // Make sure we ACK'ed the update.
-  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state(),
-            AdsServiceImpl::ACKED);
+  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
 }
 
 // Tests that we restart all xDS requests when we reestablish the ADS call.
@@ -1886,7 +1950,7 @@ TEST_P(XdsResolverOnlyTest, RestartsRequestsUponReconnection) {
       {"locality0", GetBackendPorts(0, 2)},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // We need to wait for all backends to come online.
   WaitForAllBackends(0, 2);
   // Now shut down and restart the balancer.  When the client
@@ -1901,12 +1965,11 @@ TEST_P(XdsResolverOnlyTest, RestartsRequestsUponReconnection) {
       {"locality0", GetBackendPorts(2, 4)},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args2, kNewClusterName),
-      kNewClusterName);
+      AdsServiceImpl::BuildEdsResource(args2, kNewClusterName));
   // Populate new CDS resource.
   Cluster new_cluster = balancers_[0]->ads_service()->default_cluster();
   new_cluster.set_name(kNewClusterName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster, kNewClusterName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
   // Change RDS resource to point to new cluster.
   RouteConfiguration new_route_config =
       balancers_[0]->ads_service()->default_route_config();
@@ -1914,8 +1977,7 @@ TEST_P(XdsResolverOnlyTest, RestartsRequestsUponReconnection) {
       ->mutable_routes(0)
       ->mutable_route()
       ->set_cluster(kNewClusterName);
-  balancers_[0]->ads_service()->SetRdsResource(new_route_config,
-                                               kDefaultResourceName);
+  balancers_[0]->ads_service()->SetRdsResource(new_route_config);
   // Wait for all new backends to be used.
   std::tuple<int, int, int> counts = WaitForAllBackends(2, 4);
   // Make sure no RPCs failed in the transition.
@@ -1930,14 +1992,14 @@ TEST_P(XdsResolverOnlyTest, DefaultRouteSpecifiesSlashPrefix) {
       ->mutable_match()
       ->set_prefix("/");
   balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+      AdsServiceImpl::BuildListener(route_config));
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   AdsServiceImpl::EdsResourceArgs args({
       {"locality0", GetBackendPorts()},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // We need to wait for all backends to come online.
   WaitForAllBackends();
 }
@@ -1959,18 +2021,17 @@ TEST_P(XdsResolverLoadReportingOnlyTest, ChangeClusters) {
       {"locality0", GetBackendPorts(0, 2)},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // cluster kNewClusterName -> locality1 -> backends 2 and 3
   AdsServiceImpl::EdsResourceArgs args2({
       {"locality1", GetBackendPorts(2, 4)},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args2, kNewClusterName),
-      kNewClusterName);
+      AdsServiceImpl::BuildEdsResource(args2, kNewClusterName));
   // CDS resource for kNewClusterName.
   Cluster new_cluster = balancers_[0]->ads_service()->default_cluster();
   new_cluster.set_name(kNewClusterName);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster, kNewClusterName);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster);
   // Wait for all backends to come online.
   int num_ok = 0;
   int num_failure = 0;
@@ -2011,7 +2072,7 @@ TEST_P(XdsResolverLoadReportingOnlyTest, ChangeClusters) {
       ->set_cluster(kNewClusterName);
   Listener listener =
       balancers_[0]->ads_service()->BuildListener(new_route_config);
-  balancers_[0]->ads_service()->SetLdsResource(listener, kDefaultResourceName);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
   // Wait for all new backends to be used.
   std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends(2, 4);
   // The load report received at the balancer should be correct.
@@ -2090,7 +2151,7 @@ TEST_P(SecureNamingTest, TargetNameIsExpected) {
       {"locality0", GetBackendPorts()},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Make sure that trying to connect works without a call.
   channel_->GetState(true /* try_to_connect */);
   // We need to wait for all backends to come online.
@@ -2122,27 +2183,19 @@ TEST_P(SecureNamingTest, TargetNameIsUnexpected) {
 
 using LdsTest = BasicTest;
 
-// Tests that LDS client should send an ACK upon correct LDS response (with
-// inlined RDS result).
-TEST_P(LdsTest, Vanilla) {
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  (void)SendRpc();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::ACKED);
-}
-
 // Tests that LDS client should send a NACK if there is no API listener in the
 // Listener in the LDS response.
 TEST_P(LdsTest, NoApiListener) {
   auto listener = balancers_[0]->ads_service()->default_listener();
   listener.clear_api_listener();
-  balancers_[0]->ads_service()->SetLdsResource(listener, kDefaultResourceName);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "Listener has no ApiListener.");
 }
 
 // Tests that LDS client should send a NACK if the route_specifier in the
@@ -2153,33 +2206,114 @@ TEST_P(LdsTest, WrongRouteSpecifier) {
   http_connection_manager.mutable_scoped_routes();
   listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
       http_connection_manager);
-  balancers_[0]->ads_service()->SetLdsResource(listener, kDefaultResourceName);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+  const auto& response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "HttpConnectionManager neither has inlined route_config nor RDS.");
+}
+
+// Tests that LDS client should send a NACK if the rds message in the
+// http_connection_manager is missing the config_source field.
+TEST_P(LdsTest, RdsMissingConfigSource) {
+  auto listener = balancers_[0]->ads_service()->default_listener();
+  HttpConnectionManager http_connection_manager;
+  http_connection_manager.mutable_rds()->set_route_config_name(
+      kDefaultResourceName);
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+  const auto& response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "HttpConnectionManager missing config_source for RDS.");
+}
+
+// Tests that LDS client should send a NACK if the rds message in the
+// http_connection_manager has a config_source field that does not specify ADS.
+TEST_P(LdsTest, RdsConfigSourceDoesNotSpecifyAds) {
+  auto listener = balancers_[0]->ads_service()->default_listener();
+  HttpConnectionManager http_connection_manager;
+  auto* rds = http_connection_manager.mutable_rds();
+  rds->set_route_config_name(kDefaultResourceName);
+  rds->mutable_config_source()->mutable_self();
+  listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+      http_connection_manager);
+  balancers_[0]->ads_service()->SetLdsResource(listener);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state =
+      balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "HttpConnectionManager ConfigSource for RDS does not specify ADS.");
+}
+
+using LdsRdsTest = BasicTest;
+
+// Tests that LDS client should send an ACK upon correct LDS response (with
+// inlined RDS result).
+TEST_P(LdsRdsTest, Vanilla) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  (void)SendRpc();
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
+}
+
+// Tests that we go into TRANSIENT_FAILURE if the Listener is removed.
+TEST_P(LdsRdsTest, ListenerRemoved) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  AdsServiceImpl::EdsResourceArgs args({
+      {"locality0", GetBackendPorts()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args));
+  // We need to wait for all backends to come online.
+  WaitForAllBackends();
+  // Unset LDS resource.
+  balancers_[0]->ads_service()->UnsetResource(kLdsTypeUrl,
+                                              kDefaultResourceName);
+  // Wait for RPCs to start failing.
+  do {
+  } while (SendRpc(RpcOptions(), nullptr).ok());
+  // Make sure RPCs are still failing.
+  CheckRpcSendFailure(1000);
+  // Make sure we ACK'ed the update.
+  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
 }
 
 // Tests that LDS client should send a NACK if matching domain can't be found in
 // the LDS response.
-TEST_P(LdsTest, NoMatchedDomain) {
+TEST_P(LdsRdsTest, NoMatchedDomain) {
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   route_config.mutable_virtual_hosts(0)->clear_domains();
   route_config.mutable_virtual_hosts(0)->add_domains("unmatched_domain");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "No matched virtual host found in the route config.");
 }
 
 // Tests that LDS client should choose the virtual host with matching domain if
 // multiple virtual hosts exist in the LDS response.
-TEST_P(LdsTest, ChooseMatchedDomain) {
+TEST_P(LdsRdsTest, ChooseMatchedDomain) {
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   *(route_config.add_virtual_hosts()) = route_config.virtual_hosts(0);
@@ -2189,18 +2323,17 @@ TEST_P(LdsTest, ChooseMatchedDomain) {
       ->mutable_routes(0)
       ->mutable_route()
       ->mutable_cluster_header();
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   (void)SendRpc();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::ACKED);
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
 }
 
 // Tests that LDS client should choose the last route in the virtual host if
 // multiple routes exist in the LDS response.
-TEST_P(LdsTest, ChooseLastRoute) {
+TEST_P(LdsRdsTest, ChooseLastRoute) {
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   *(route_config.mutable_virtual_hosts(0)->add_routes()) =
@@ -2209,40 +2342,58 @@ TEST_P(LdsTest, ChooseLastRoute) {
       ->mutable_routes(0)
       ->mutable_route()
       ->mutable_cluster_header();
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   (void)SendRpc();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::ACKED);
+  EXPECT_EQ(RouteConfigurationResponseState(0).state,
+            AdsServiceImpl::ResponseState::ACKED);
 }
 
 // Tests that LDS client should send a NACK if route match has non-empty prefix
 // as the only route (default) in the LDS response.
-TEST_P(LdsTest, RouteMatchHasNonemptyPrefix) {
+TEST_P(LdsRdsTest, RouteMatchHasNonemptyPrefix) {
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   route_config.mutable_virtual_hosts(0)
       ->mutable_routes(0)
       ->mutable_match()
-      ->set_prefix("nonempty_prefix");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+      ->set_prefix("/nonempty_prefix/");
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+  const auto& response_state = RouteConfigurationResponseState(0);
+  balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "Default route must have empty prefix.");
+}
+
+// Tests that LDS client should send a NACK if route match has path specifier
+// besides prefix as the only route (default) in the LDS response.
+TEST_P(LdsRdsTest, RouteMatchHasUnsupportedSpecifier) {
+  RouteConfiguration route_config =
+      balancers_[0]->ads_service()->default_route_config();
+  route_config.mutable_virtual_hosts(0)
+      ->mutable_routes(0)
+      ->mutable_match()
+      ->set_path("");
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  balancers_[0]->ads_service()->lds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "No prefix field found in Default RouteMatch.");
 }
 
 // Tests that LDS client should send a NACK if route match has a prefix
 // string with no "/".
-TEST_P(LdsTest, RouteMatchHasInvalidPrefixNonEmptyNoSlash) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixNonEmptyNoSlash) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
@@ -2250,102 +2401,93 @@ TEST_P(LdsTest, RouteMatchHasInvalidPrefixNonEmptyNoSlash) {
   auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
   default_route->mutable_match()->set_prefix("");
   default_route->mutable_route()->set_cluster(kDefaultResourceName);
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "Prefix does not start with a /");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 // Tests that LDS client should send a NACK if route match has a prefix
 // string does not end with "/".
-TEST_P(LdsTest, RouteMatchHasInvalidPrefixNoEndingSlash) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixNoEndingSlash) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
   route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "Prefix not in the required format of /service/");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 // Tests that LDS client should send a NACK if route match has a prefix
 // string does not start with "/".
-TEST_P(LdsTest, RouteMatchHasInvalidPrefixNoLeadingSlash) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixNoLeadingSlash) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
   route1->mutable_match()->set_prefix("grpc.testing.EchoTest1Service/");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "Prefix does not start with a /");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 // Tests that LDS client should send a NACK if route match has a prefix
 // string with extra content outside of "/service/".
-TEST_P(LdsTest, RouteMatchHasInvalidPrefixExtraContent) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixExtraContent) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
   route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/Echo1");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "Prefix does not end with a /");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 // Tests that LDS client should send a NACK if route match has a prefix
 // string "//".
-TEST_P(LdsTest, RouteMatchHasInvalidPrefixNoContent) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixNoContent) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
   route1->mutable_match()->set_prefix("//");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "Prefix contains empty service name");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 // Tests that LDS client should send a NACK if route match has path
 // but it's empty.
-TEST_P(LdsTest, RouteMatchHasInvalidPathEmptyPath) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathEmptyPath) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
@@ -2353,22 +2495,20 @@ TEST_P(LdsTest, RouteMatchHasInvalidPathEmptyPath) {
   default_route->mutable_match()->set_prefix("");
   default_route->mutable_route()->set_cluster(kDefaultResourceName);
   route1->mutable_match()->set_path("");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "Path if set cannot be empty");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 // Tests that LDS client should send a NACK if route match has path
 // string does not start with "/".
-TEST_P(LdsTest, RouteMatchHasInvalidPathNoLeadingSlash) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathNoLeadingSlash) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
@@ -2376,22 +2516,20 @@ TEST_P(LdsTest, RouteMatchHasInvalidPathNoLeadingSlash) {
   default_route->mutable_match()->set_prefix("");
   default_route->mutable_route()->set_cluster(kDefaultResourceName);
   route1->mutable_match()->set_path("grpc.testing.EchoTest1Service/Echo1");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "Path does not start with a /");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 // Tests that LDS client should send a NACK if route match has path
 // string that ends with "/".
-TEST_P(LdsTest, RouteMatchHasInvalidPathEndsWithSlash) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathEndsWithSlash) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
@@ -2399,22 +2537,21 @@ TEST_P(LdsTest, RouteMatchHasInvalidPathEndsWithSlash) {
   default_route->mutable_match()->set_prefix("");
   default_route->mutable_route()->set_cluster(kDefaultResourceName);
   route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/Echo1/");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "Path not in the required format of /service/method");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 // Tests that LDS client should send a NACK if route match has path
 // string that misses "/" between service and method.
-TEST_P(LdsTest, RouteMatchHasInvalidPathMissingMiddleSlash) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathMissingMiddleSlash) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
@@ -2422,22 +2559,21 @@ TEST_P(LdsTest, RouteMatchHasInvalidPathMissingMiddleSlash) {
   default_route->mutable_match()->set_prefix("");
   default_route->mutable_route()->set_cluster(kDefaultResourceName);
   route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service.Echo1");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "Path not in the required format of /service/method");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 // Tests that LDS client should send a NACK if route match has path
 // string that is missing service.
-TEST_P(LdsTest, RouteMatchHasInvalidPathMissingService) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathMissingService) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
@@ -2445,22 +2581,20 @@ TEST_P(LdsTest, RouteMatchHasInvalidPathMissingService) {
   default_route->mutable_match()->set_prefix("");
   default_route->mutable_route()->set_cluster(kDefaultResourceName);
   route1->mutable_match()->set_path("//Echo1");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "Path contains empty service name");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 // Tests that LDS client should send a NACK if route match has path
 // string that is missing method.
-TEST_P(LdsTest, RouteMatchHasInvalidPathMissingMethod) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteMatchHasInvalidPathMissingMethod) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
@@ -2468,99 +2602,208 @@ TEST_P(LdsTest, RouteMatchHasInvalidPathMissingMethod) {
   default_route->mutable_match()->set_prefix("");
   default_route->mutable_route()->set_cluster(kDefaultResourceName);
   route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/");
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "Path contains empty method name");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 // Tests that LDS client should send a NACK if route has an action other than
 // RouteAction in the LDS response.
-TEST_P(LdsTest, RouteHasNoRouteAction) {
+TEST_P(LdsRdsTest, RouteHasNoRouteAction) {
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   route_config.mutable_virtual_hosts(0)->mutable_routes(0)->mutable_redirect();
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "No RouteAction found in route.");
 }
 
-// TODO@donnadionne: Add more invalid config tests to cover all errors in
-// xds_api.cc
-
-// Tests that LDS client should send a NACK if RouteAction has a
-// cluster_specifier other than cluster in the LDS response.
-TEST_P(LdsTest, RouteActionHasNoCluster) {
+// Tests that LDS client should send a NACK if route has a
+// cluster_specifier other than cluster or weighted_clusters in the LDS
+// response.
+TEST_P(LdsRdsTest, RouteActionUnsupportedClusterSpecifier) {
   RouteConfiguration route_config =
       balancers_[0]->ads_service()->default_route_config();
   route_config.mutable_virtual_hosts(0)
       ->mutable_routes(0)
       ->mutable_route()
       ->mutable_cluster_header();
-  balancers_[0]->ads_service()->SetLdsResource(
-      AdsServiceImpl::BuildListener(route_config), kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "No cluster or weighted_clusters found in RouteAction.");
 }
 
-// Tests that LDS client times out when no response received.
-TEST_P(LdsTest, Timeout) {
-  ResetStub(0, "", 500);
-  balancers_[0]->ads_service()->SetResourceIgnore(kLdsTypeUrl);
+TEST_P(LdsRdsTest, RouteActionClusterHasEmptyClusterName) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
+  RouteConfiguration route_config =
+      balancers_[0]->ads_service()->default_route_config();
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  route1->mutable_route()->set_cluster("");
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "RouteAction cluster contains empty cluster name.");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
-// Tests that LDS client should choose the default route (with no matching
-// specified) after unable to find a match with previous routes.
-TEST_P(LdsTest, XdsRoutingPathMatching) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, RouteActionWeightedTargetHasIncorrectTotalWeightSet) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
+  const size_t kWeight75 = 75;
   const char* kNewCluster1Name = "new_cluster_1";
-  const char* kNewCluster2Name = "new_cluster_2";
-  const size_t kNumEcho1Rpcs = 10;
-  const size_t kNumEcho2Rpcs = 20;
-  const size_t kNumEchoRpcs = 30;
+  RouteConfiguration route_config =
+      balancers_[0]->ads_service()->default_route_config();
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75 + 1);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
-  // Populate new EDS resources.
-  AdsServiceImpl::EdsResourceArgs args({
-      {"locality0", GetBackendPorts(0, 2)},
-  });
-  AdsServiceImpl::EdsResourceArgs args1({
-      {"locality0", GetBackendPorts(2, 3)},
-  });
-  AdsServiceImpl::EdsResourceArgs args2({
-      {"locality0", GetBackendPorts(3, 4)},
-  });
-  balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
-  balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name),
-      kNewCluster1Name);
+  CheckRpcSendFailure();
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "RouteAction weighted_cluster has incorrect total weight");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
+}
+
+TEST_P(LdsRdsTest, RouteActionWeightedTargetClusterHasEmptyClusterName) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
+  const size_t kWeight75 = 75;
+  RouteConfiguration route_config =
+      balancers_[0]->ads_service()->default_route_config();
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name("");
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(
+      response_state.error_message,
+      "RouteAction weighted_cluster cluster contains empty cluster name.");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
+}
+
+TEST_P(LdsRdsTest, RouteActionWeightedTargetClusterHasNoWeight) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
+  const size_t kWeight75 = 75;
+  const char* kNewCluster1Name = "new_cluster_1";
+  RouteConfiguration route_config =
+      balancers_[0]->ads_service()->default_route_config();
+  auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75);
+  auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultResourceName);
+  SetRouteConfiguration(0, route_config);
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+  const auto& response_state = RouteConfigurationResponseState(0);
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "RouteAction weighted_cluster cluster missing weight");
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
+}
+
+// Tests that LDS client times out when no response received.
+TEST_P(LdsRdsTest, Timeout) {
+  ResetStub(0, "", 500);
+  if (GetParam().enable_rds_testing()) {
+    balancers_[0]->ads_service()->SetResourceIgnore(kRdsTypeUrl);
+  } else {
+    balancers_[0]->ads_service()->SetResourceIgnore(kLdsTypeUrl);
+  }
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  CheckRpcSendFailure();
+}
+
+// Tests that LDS client should choose the default route (with no matching
+// specified) after unable to find a match with previous routes.
+TEST_P(LdsRdsTest, XdsRoutingPathMatching) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const size_t kNumEcho1Rpcs = 10;
+  const size_t kNumEcho2Rpcs = 20;
+  const size_t kNumEchoRpcs = 30;
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  // Populate new EDS resources.
+  AdsServiceImpl::EdsResourceArgs args({
+      {"locality0", GetBackendPorts(0, 2)},
+  });
+  AdsServiceImpl::EdsResourceArgs args1({
+      {"locality0", GetBackendPorts(2, 3)},
+  });
+  AdsServiceImpl::EdsResourceArgs args2({
+      {"locality0", GetBackendPorts(3, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args2, kNewCluster2Name),
-      kNewCluster2Name);
+      AdsServiceImpl::BuildEdsResource(args2, kNewCluster2Name));
   // Populate new CDS resources.
   Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
   new_cluster1.set_name(kNewCluster1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1, kNewCluster1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
   Cluster new_cluster2 = balancers_[0]->ads_service()->default_cluster();
   new_cluster2.set_name(kNewCluster2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2, kNewCluster2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
   // Populating Route Configurations for LDS.
   RouteConfiguration new_route_config =
       balancers_[0]->ads_service()->default_route_config();
@@ -2570,12 +2813,13 @@ TEST_P(LdsTest, XdsRoutingPathMatching) {
   auto* route2 = new_route_config.mutable_virtual_hosts(0)->add_routes();
   route2->mutable_match()->set_path("/grpc.testing.EchoTest2Service/Echo2");
   route2->mutable_route()->set_cluster(kNewCluster2Name);
+  auto* route3 = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  route3->mutable_match()->set_path("/grpc.testing.EchoTest3Service/Echo3");
+  route3->mutable_route()->set_cluster(kDefaultResourceName);
   auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
   default_route->mutable_match()->set_prefix("");
   default_route->mutable_route()->set_cluster(kDefaultResourceName);
-  Listener listener =
-      balancers_[0]->ads_service()->BuildListener(new_route_config);
-  balancers_[0]->ads_service()->SetLdsResource(listener, kDefaultResourceName);
+  SetRouteConfiguration(0, new_route_config);
   WaitForAllBackends(0, 2);
   CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
   CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions()
@@ -2599,13 +2843,11 @@ TEST_P(LdsTest, XdsRoutingPathMatching) {
   EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
   EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
   EXPECT_EQ(kNumEcho2Rpcs, backends_[3]->backend_service2()->request_count());
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
-TEST_P(LdsTest, XdsRoutingPrefixMatching) {
-  ResetStub(/*failover_timeout=*/0,
-            /*expected_targets=*/"",
-            /*xds_resource_does_not_exist_timeout*/ 0,
-            /*xds_routing_enabled=*/true);
+TEST_P(LdsRdsTest, XdsRoutingPrefixMatching) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
   const char* kNewCluster1Name = "new_cluster_1";
   const char* kNewCluster2Name = "new_cluster_2";
   const size_t kNumEcho1Rpcs = 10;
@@ -2624,20 +2866,18 @@ TEST_P(LdsTest, XdsRoutingPrefixMatching) {
       {"locality0", GetBackendPorts(3, 4)},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name),
-      kNewCluster1Name);
+      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args2, kNewCluster2Name),
-      kNewCluster2Name);
+      AdsServiceImpl::BuildEdsResource(args2, kNewCluster2Name));
   // Populate new CDS resources.
   Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
   new_cluster1.set_name(kNewCluster1Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster1, kNewCluster1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
   Cluster new_cluster2 = balancers_[0]->ads_service()->default_cluster();
   new_cluster2.set_name(kNewCluster2Name);
-  balancers_[0]->ads_service()->SetCdsResource(new_cluster2, kNewCluster2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
   // Populating Route Configurations for LDS.
   RouteConfiguration new_route_config =
       balancers_[0]->ads_service()->default_route_config();
@@ -2650,9 +2890,7 @@ TEST_P(LdsTest, XdsRoutingPrefixMatching) {
   auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
   default_route->mutable_match()->set_prefix("");
   default_route->mutable_route()->set_cluster(kDefaultResourceName);
-  Listener listener =
-      balancers_[0]->ads_service()->BuildListener(new_route_config);
-  balancers_[0]->ads_service()->SetLdsResource(listener, kDefaultResourceName);
+  SetRouteConfiguration(0, new_route_config);
   WaitForAllBackends(0, 2);
   CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_wait_for_ready(true));
   CheckRpcSendOk(
@@ -2674,142 +2912,459 @@ TEST_P(LdsTest, XdsRoutingPrefixMatching) {
   EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
   EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
   EXPECT_EQ(kNumEcho2Rpcs, backends_[3]->backend_service2()->request_count());
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
-using RdsTest = BasicTest;
-
-// Tests that RDS client should send an ACK upon correct RDS response.
-TEST_P(RdsTest, Vanilla) {
-  balancers_[0]->ads_service()->SetLdsToUseDynamicRds();
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  (void)SendRpc();
-  EXPECT_EQ(balancers_[0]->ads_service()->rds_response_state(),
-            AdsServiceImpl::ACKED);
-}
-
-// Tests that RDS client should send a NACK if matching domain can't be found in
-// the RDS response.
-TEST_P(RdsTest, NoMatchedDomain) {
-  balancers_[0]->ads_service()->SetLdsToUseDynamicRds();
-  RouteConfiguration route_config =
-      balancers_[0]->ads_service()->default_route_config();
-  route_config.mutable_virtual_hosts(0)->clear_domains();
-  route_config.mutable_virtual_hosts(0)->add_domains("unmatched_domain");
-  balancers_[0]->ads_service()->SetRdsResource(route_config,
-                                               kDefaultResourceName);
+TEST_P(LdsRdsTest, XdsRoutingWeightedCluster) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const size_t kNumEcho1Rpcs = 1000;
+  const size_t kNumEchoRpcs = 10;
+  const size_t kWeight75 = 75;
+  const size_t kWeight25 = 25;
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->rds_response_state(),
-            AdsServiceImpl::NACKED);
-}
-
-// Tests that RDS client should choose the virtual host with matching domain if
-// multiple virtual hosts exist in the RDS response.
-TEST_P(RdsTest, ChooseMatchedDomain) {
-  balancers_[0]->ads_service()->SetLdsToUseDynamicRds();
-  RouteConfiguration route_config =
+  // Populate new EDS resources.
+  AdsServiceImpl::EdsResourceArgs args({
+      {"locality0", GetBackendPorts(0, 1)},
+  });
+  AdsServiceImpl::EdsResourceArgs args1({
+      {"locality0", GetBackendPorts(1, 2)},
+  });
+  AdsServiceImpl::EdsResourceArgs args2({
+      {"locality0", GetBackendPorts(2, 3)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args2, kNewCluster2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
+  new_cluster1.set_name(kNewCluster1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = balancers_[0]->ads_service()->default_cluster();
+  new_cluster2.set_name(kNewCluster2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration new_route_config =
       balancers_[0]->ads_service()->default_route_config();
-  *(route_config.add_virtual_hosts()) = route_config.virtual_hosts(0);
-  route_config.mutable_virtual_hosts(0)->clear_domains();
-  route_config.mutable_virtual_hosts(0)->add_domains("unmatched_domain");
-  route_config.mutable_virtual_hosts(0)
-      ->mutable_routes(0)
-      ->mutable_route()
-      ->mutable_cluster_header();
-  balancers_[0]->ads_service()->SetRdsResource(route_config,
-                                               kDefaultResourceName);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  (void)SendRpc();
-  EXPECT_EQ(balancers_[0]->ads_service()->rds_response_state(),
-            AdsServiceImpl::ACKED);
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  auto* weighted_cluster2 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster2->set_name(kNewCluster2Name);
+  weighted_cluster2->mutable_weight()->set_value(kWeight25);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75 + kWeight25);
+  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultResourceName);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(0, 1);
+  WaitForAllBackends(1, 3, true, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  const int weight_75_request_count =
+      backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  const int weight_25_request_count =
+      backends_[2]->backend_service1()->request_count();
+  const double kErrorTolerance = 0.2;
+  EXPECT_THAT(weight_75_request_count,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight75 / 100 *
+                                             (1 - kErrorTolerance)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight75 / 100 *
+                                             (1 + kErrorTolerance))));
+  // TODO: (@donnadionne) Reduce tolerance: increased the tolerance to keep the
+  // test from flaking while debugging potential root cause.
+  const double kErrorToleranceSmallLoad = 0.3;
+  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
+          weight_75_request_count, weight_25_request_count);
+  EXPECT_THAT(weight_25_request_count,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight25 / 100 *
+                                             (1 - kErrorToleranceSmallLoad)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight25 / 100 *
+                                             (1 + kErrorToleranceSmallLoad))));
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
-// Tests that RDS client should choose the last route in the virtual host if
-// multiple routes exist in the RDS response.
-TEST_P(RdsTest, ChooseLastRoute) {
-  balancers_[0]->ads_service()->SetLdsToUseDynamicRds();
-  RouteConfiguration route_config =
-      balancers_[0]->ads_service()->default_route_config();
-  *(route_config.mutable_virtual_hosts(0)->add_routes()) =
-      route_config.virtual_hosts(0).routes(0);
-  route_config.mutable_virtual_hosts(0)
-      ->mutable_routes(0)
-      ->mutable_route()
-      ->mutable_cluster_header();
-  balancers_[0]->ads_service()->SetRdsResource(route_config,
-                                               kDefaultResourceName);
+TEST_P(LdsRdsTest, RouteActionWeightedTargetDefaultRoute) {
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewCluster2Name = "new_cluster_2";
+  const size_t kNumEchoRpcs = 1000;
+  const size_t kWeight75 = 75;
+  const size_t kWeight25 = 25;
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
-  (void)SendRpc();
-  EXPECT_EQ(balancers_[0]->ads_service()->rds_response_state(),
-            AdsServiceImpl::ACKED);
-}
-
-// Tests that RDS client should send a NACK if route match has non-empty prefix
-// as the only route (default) in the RDS response.
-TEST_P(RdsTest, RouteMatchHasNonemptyPrefix) {
-  balancers_[0]->ads_service()->SetLdsToUseDynamicRds();
-  RouteConfiguration route_config =
+  // Populate new EDS resources.
+  AdsServiceImpl::EdsResourceArgs args({
+      {"locality0", GetBackendPorts(0, 1)},
+  });
+  AdsServiceImpl::EdsResourceArgs args1({
+      {"locality0", GetBackendPorts(1, 2)},
+  });
+  AdsServiceImpl::EdsResourceArgs args2({
+      {"locality0", GetBackendPorts(2, 3)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args2, kNewCluster2Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
+  new_cluster1.set_name(kNewCluster1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = balancers_[0]->ads_service()->default_cluster();
+  new_cluster2.set_name(kNewCluster2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  // Populating Route Configurations for LDS.
+  RouteConfiguration new_route_config =
       balancers_[0]->ads_service()->default_route_config();
-  route_config.mutable_virtual_hosts(0)
-      ->mutable_routes(0)
-      ->mutable_match()
-      ->set_prefix("/nonempty_prefix/");
-  balancers_[0]->ads_service()->SetRdsResource(route_config,
-                                               kDefaultResourceName);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->rds_response_state(),
-            AdsServiceImpl::NACKED);
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  auto* weighted_cluster2 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster2->set_name(kNewCluster2Name);
+  weighted_cluster2->mutable_weight()->set_value(kWeight25);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75 + kWeight25);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(1, 3);
+  CheckRpcSendOk(kNumEchoRpcs);
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(0, backends_[0]->backend_service()->request_count());
+  const int weight_75_request_count =
+      backends_[1]->backend_service()->request_count();
+  const int weight_25_request_count =
+      backends_[2]->backend_service()->request_count();
+  const double kErrorTolerance = 0.2;
+  EXPECT_THAT(weight_75_request_count,
+              ::testing::AllOf(::testing::Ge(kNumEchoRpcs * kWeight75 / 100 *
+                                             (1 - kErrorTolerance)),
+                               ::testing::Le(kNumEchoRpcs * kWeight75 / 100 *
+                                             (1 + kErrorTolerance))));
+  // TODO: (@donnadionne) Reduce tolerance: increased the tolerance to keep the
+  // test from flaking while debugging potential root cause.
+  const double kErrorToleranceSmallLoad = 0.3;
+  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
+          weight_75_request_count, weight_25_request_count);
+  EXPECT_THAT(weight_25_request_count,
+              ::testing::AllOf(::testing::Ge(kNumEchoRpcs * kWeight25 / 100 *
+                                             (1 - kErrorToleranceSmallLoad)),
+                               ::testing::Le(kNumEchoRpcs * kWeight25 / 100 *
+                                             (1 + kErrorToleranceSmallLoad))));
 }
 
-// Tests that RDS client should send a NACK if route has an action other than
-// RouteAction in the RDS response.
-TEST_P(RdsTest, RouteHasNoRouteAction) {
-  balancers_[0]->ads_service()->SetLdsToUseDynamicRds();
-  RouteConfiguration route_config =
-      balancers_[0]->ads_service()->default_route_config();
-  route_config.mutable_virtual_hosts(0)->mutable_routes(0)->mutable_redirect();
-  balancers_[0]->ads_service()->SetRdsResource(route_config,
-                                               kDefaultResourceName);
+TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateWeights) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewCluster2Name = "anew_cluster_2";
+  const char* kNewCluster3Name = "new_cluster_3";
+  const size_t kNumEcho1Rpcs = 1000;
+  const size_t kNumEchoRpcs = 10;
+  const size_t kWeight75 = 75;
+  const size_t kWeight25 = 25;
+  const size_t kWeight50 = 50;
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->rds_response_state(),
-            AdsServiceImpl::NACKED);
-}
-
-// Tests that RDS client should send a NACK if RouteAction has a
-// cluster_specifier other than cluster in the RDS response.
-TEST_P(RdsTest, RouteActionHasNoCluster) {
-  balancers_[0]->ads_service()->SetLdsToUseDynamicRds();
-  RouteConfiguration route_config =
+  // Populate new EDS resources.
+  AdsServiceImpl::EdsResourceArgs args({
+      {"locality0", GetBackendPorts(0, 1)},
+  });
+  AdsServiceImpl::EdsResourceArgs args1({
+      {"locality0", GetBackendPorts(1, 2)},
+  });
+  AdsServiceImpl::EdsResourceArgs args2({
+      {"locality0", GetBackendPorts(2, 3)},
+  });
+  AdsServiceImpl::EdsResourceArgs args3({
+      {"locality0", GetBackendPorts(3, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args2, kNewCluster2Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args3, kNewCluster3Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
+  new_cluster1.set_name(kNewCluster1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = balancers_[0]->ads_service()->default_cluster();
+  new_cluster2.set_name(kNewCluster2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  Cluster new_cluster3 = balancers_[0]->ads_service()->default_cluster();
+  new_cluster3.set_name(kNewCluster3Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster3);
+  // Populating Route Configurations.
+  RouteConfiguration new_route_config =
       balancers_[0]->ads_service()->default_route_config();
-  route_config.mutable_virtual_hosts(0)
-      ->mutable_routes(0)
-      ->mutable_route()
-      ->mutable_cluster_header();
-  balancers_[0]->ads_service()->SetRdsResource(route_config,
-                                               kDefaultResourceName);
-  SetNextResolution({});
-  SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->rds_response_state(),
-            AdsServiceImpl::NACKED);
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  auto* weighted_cluster2 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster2->set_name(kNewCluster2Name);
+  weighted_cluster2->mutable_weight()->set_value(kWeight25);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75 + kWeight25);
+  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultResourceName);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(0, 1);
+  WaitForAllBackends(1, 3, true, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  const int weight_75_request_count =
+      backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[1]->backend_service2()->request_count());
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  const int weight_25_request_count =
+      backends_[2]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
+  const double kErrorTolerance = 0.2;
+  EXPECT_THAT(weight_75_request_count,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight75 / 100 *
+                                             (1 - kErrorTolerance)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight75 / 100 *
+                                             (1 + kErrorTolerance))));
+  // TODO: (@donnadionne) Reduce tolerance: increased the tolerance to keep the
+  // test from flaking while debugging potential root cause.
+  const double kErrorToleranceSmallLoad = 0.3;
+  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
+          weight_75_request_count, weight_25_request_count);
+  EXPECT_THAT(weight_25_request_count,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight25 / 100 *
+                                             (1 - kErrorToleranceSmallLoad)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight25 / 100 *
+                                             (1 + kErrorToleranceSmallLoad))));
+  // Change Route Configurations: same clusters different weights.
+  weighted_cluster1->mutable_weight()->set_value(kWeight50);
+  weighted_cluster2->mutable_weight()->set_value(kWeight50);
+  // Change default route to a new cluster to help to identify when new polices
+  // are seen by the client.
+  default_route->mutable_route()->set_cluster(kNewCluster3Name);
+  SetRouteConfiguration(0, new_route_config);
+  ResetBackendCounters();
+  WaitForAllBackends(3, 4);
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(0, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  const int weight_50_request_count_1 =
+      backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  const int weight_50_request_count_2 =
+      backends_[2]->backend_service1()->request_count();
+  EXPECT_EQ(kNumEchoRpcs, backends_[3]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
+  EXPECT_THAT(weight_50_request_count_1,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight50 / 100 *
+                                             (1 - kErrorTolerance)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight50 / 100 *
+                                             (1 + kErrorTolerance))));
+  EXPECT_THAT(weight_50_request_count_2,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight50 / 100 *
+                                             (1 - kErrorTolerance)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight50 / 100 *
+                                             (1 + kErrorTolerance))));
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
-// Tests that RDS client times out when no response received.
-TEST_P(RdsTest, Timeout) {
-  ResetStub(0, "", 500);
-  balancers_[0]->ads_service()->SetResourceIgnore(kRdsTypeUrl);
-  balancers_[0]->ads_service()->SetLdsToUseDynamicRds();
+TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateClusters) {
+  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
+  const char* kNewCluster1Name = "new_cluster_1";
+  const char* kNewCluster2Name = "anew_cluster_2";
+  const char* kNewCluster3Name = "new_cluster_3";
+  const size_t kNumEcho1Rpcs = 1000;
+  const size_t kNumEchoRpcs = 10;
+  const size_t kWeight75 = 75;
+  const size_t kWeight25 = 25;
+  const size_t kWeight50 = 50;
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
-  CheckRpcSendFailure();
+  // Populate new EDS resources.
+  AdsServiceImpl::EdsResourceArgs args({
+      {"locality0", GetBackendPorts(0, 1)},
+  });
+  AdsServiceImpl::EdsResourceArgs args1({
+      {"locality0", GetBackendPorts(1, 2)},
+  });
+  AdsServiceImpl::EdsResourceArgs args2({
+      {"locality0", GetBackendPorts(2, 3)},
+  });
+  AdsServiceImpl::EdsResourceArgs args3({
+      {"locality0", GetBackendPorts(3, 4)},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args));
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args2, kNewCluster2Name));
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args3, kNewCluster3Name));
+  // Populate new CDS resources.
+  Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
+  new_cluster1.set_name(kNewCluster1Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
+  Cluster new_cluster2 = balancers_[0]->ads_service()->default_cluster();
+  new_cluster2.set_name(kNewCluster2Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
+  Cluster new_cluster3 = balancers_[0]->ads_service()->default_cluster();
+  new_cluster3.set_name(kNewCluster3Name);
+  balancers_[0]->ads_service()->SetCdsResource(new_cluster3);
+  // Populating Route Configurations.
+  RouteConfiguration new_route_config =
+      balancers_[0]->ads_service()->default_route_config();
+  auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
+  route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/");
+  auto* weighted_cluster1 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster1->set_name(kNewCluster1Name);
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  auto* weighted_cluster2 =
+      route1->mutable_route()->mutable_weighted_clusters()->add_clusters();
+  weighted_cluster2->set_name(kDefaultResourceName);
+  weighted_cluster2->mutable_weight()->set_value(kWeight25);
+  route1->mutable_route()
+      ->mutable_weighted_clusters()
+      ->mutable_total_weight()
+      ->set_value(kWeight75 + kWeight25);
+  auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
+  default_route->mutable_match()->set_prefix("");
+  default_route->mutable_route()->set_cluster(kDefaultResourceName);
+  SetRouteConfiguration(0, new_route_config);
+  WaitForAllBackends(0, 1);
+  WaitForAllBackends(1, 2, true, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  int weight_25_request_count =
+      backends_[0]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  int weight_75_request_count =
+      backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[2]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
+  const double kErrorTolerance = 0.2;
+  EXPECT_THAT(weight_75_request_count,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight75 / 100 *
+                                             (1 - kErrorTolerance)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight75 / 100 *
+                                             (1 + kErrorTolerance))));
+  // TODO: (@donnadionne) Reduce tolerance: increased the tolerance to keep the
+  // test from flaking while debugging potential root cause.
+  const double kErrorToleranceSmallLoad = 0.3;
+  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
+          weight_75_request_count, weight_25_request_count);
+  EXPECT_THAT(weight_25_request_count,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight25 / 100 *
+                                             (1 - kErrorToleranceSmallLoad)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight25 / 100 *
+                                             (1 + kErrorToleranceSmallLoad))));
+  // Change Route Configurations: new set of clusters with different weights.
+  weighted_cluster1->mutable_weight()->set_value(kWeight50);
+  weighted_cluster2->set_name(kNewCluster2Name);
+  weighted_cluster2->mutable_weight()->set_value(kWeight50);
+  SetRouteConfiguration(0, new_route_config);
+  ResetBackendCounters();
+  WaitForAllBackends(2, 3, true, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  const int weight_50_request_count_1 =
+      backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  const int weight_50_request_count_2 =
+      backends_[2]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service1()->request_count());
+  EXPECT_THAT(weight_50_request_count_1,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight50 / 100 *
+                                             (1 - kErrorTolerance)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight50 / 100 *
+                                             (1 + kErrorTolerance))));
+  EXPECT_THAT(weight_50_request_count_2,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight50 / 100 *
+                                             (1 - kErrorTolerance)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight50 / 100 *
+                                             (1 + kErrorTolerance))));
+  // Change Route Configurations.
+  weighted_cluster1->mutable_weight()->set_value(kWeight75);
+  weighted_cluster2->set_name(kNewCluster3Name);
+  weighted_cluster2->mutable_weight()->set_value(kWeight25);
+  SetRouteConfiguration(0, new_route_config);
+  ResetBackendCounters();
+  WaitForAllBackends(3, 4, true, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  CheckRpcSendOk(kNumEchoRpcs);
+  CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1));
+  // Make sure RPCs all go to the correct backend.
+  EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[0]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
+  weight_75_request_count = backends_[1]->backend_service1()->request_count();
+  EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
+  EXPECT_EQ(0, backends_[2]->backend_service1()->request_count());
+  EXPECT_EQ(0, backends_[3]->backend_service()->request_count());
+  weight_25_request_count = backends_[3]->backend_service1()->request_count();
+  EXPECT_THAT(weight_75_request_count,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight75 / 100 *
+                                             (1 - kErrorTolerance)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight75 / 100 *
+                                             (1 + kErrorTolerance))));
+  // TODO: (@donnadionne) Reduce tolerance: increased the tolerance to keep the
+  // test from flaking while debugging potential root cause.
+  gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs",
+          weight_75_request_count, weight_25_request_count);
+  EXPECT_THAT(weight_25_request_count,
+              ::testing::AllOf(::testing::Ge(kNumEcho1Rpcs * kWeight25 / 100 *
+                                             (1 - kErrorToleranceSmallLoad)),
+                               ::testing::Le(kNumEcho1Rpcs * kWeight25 / 100 *
+                                             (1 + kErrorToleranceSmallLoad))));
+  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 }
 
 using CdsTest = BasicTest;
@@ -2819,8 +3374,8 @@ TEST_P(CdsTest, Vanilla) {
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   (void)SendRpc();
-  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state(),
-            AdsServiceImpl::ACKED);
+  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state,
+            AdsServiceImpl::ResponseState::ACKED);
 }
 
 // Tests that CDS client should send a NACK if the cluster type in CDS response
@@ -2828,12 +3383,14 @@ TEST_P(CdsTest, Vanilla) {
 TEST_P(CdsTest, WrongClusterType) {
   auto cluster = balancers_[0]->ads_service()->default_cluster();
   cluster.set_type(envoy::api::v2::Cluster::STATIC);
-  balancers_[0]->ads_service()->SetCdsResource(cluster, kDefaultResourceName);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "DiscoveryType is not EDS.");
 }
 
 // Tests that CDS client should send a NACK if the eds_config in CDS response is
@@ -2841,12 +3398,14 @@ TEST_P(CdsTest, WrongClusterType) {
 TEST_P(CdsTest, WrongEdsConfig) {
   auto cluster = balancers_[0]->ads_service()->default_cluster();
   cluster.mutable_eds_cluster_config()->mutable_eds_config()->mutable_self();
-  balancers_[0]->ads_service()->SetCdsResource(cluster, kDefaultResourceName);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "EDS ConfigSource is not ADS.");
 }
 
 // Tests that CDS client should send a NACK if the lb_policy in CDS response is
@@ -2854,12 +3413,14 @@ TEST_P(CdsTest, WrongEdsConfig) {
 TEST_P(CdsTest, WrongLbPolicy) {
   auto cluster = balancers_[0]->ads_service()->default_cluster();
   cluster.set_lb_policy(envoy::api::v2::Cluster::LEAST_REQUEST);
-  balancers_[0]->ads_service()->SetCdsResource(cluster, kDefaultResourceName);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "LB policy is not ROUND_ROBIN.");
 }
 
 // Tests that CDS client should send a NACK if the lrs_server in CDS response is
@@ -2867,12 +3428,14 @@ TEST_P(CdsTest, WrongLbPolicy) {
 TEST_P(CdsTest, WrongLrsServer) {
   auto cluster = balancers_[0]->ads_service()->default_cluster();
   cluster.mutable_lrs_server()->mutable_ads();
-  balancers_[0]->ads_service()->SetCdsResource(cluster, kDefaultResourceName);
+  balancers_[0]->ads_service()->SetCdsResource(cluster);
   SetNextResolution({});
   SetNextResolutionForLbChannelAllBalancers();
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state =
+      balancers_[0]->ads_service()->cds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message, "LRS ConfigSource is not self.");
 }
 
 // Tests that CDS client times out when no response received.
@@ -2903,10 +3466,13 @@ TEST_P(EdsTest, NacksSparsePriorityList) {
       {"locality0", GetBackendPorts(), kDefaultLocalityWeight, 1},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   CheckRpcSendFailure();
-  EXPECT_EQ(balancers_[0]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NACKED);
+  const auto& response_state =
+      balancers_[0]->ads_service()->eds_response_state();
+  EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+  EXPECT_EQ(response_state.error_message,
+            "EDS update includes sparse priority list");
 }
 
 using LocalityMapTest = BasicTest;
@@ -2930,7 +3496,7 @@ TEST_P(LocalityMapTest, WeightedRoundRobin) {
       {"locality1", GetBackendPorts(1, 2), kLocalityWeight1},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Wait for both backends to be ready.
   WaitForAllBackends(0, 2);
   // Send kNumRpcs RPCs.
@@ -2964,7 +3530,7 @@ TEST_P(LocalityMapTest, LocalityContainingNoEndpoints) {
       {"locality1", {}},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Wait for both backends to be ready.
   WaitForAllBackends();
   // Send kNumRpcs RPCs.
@@ -2986,7 +3552,7 @@ TEST_P(LocalityMapTest, NoLocalities) {
   SetNextResolutionForLbChannelAllBalancers();
   // EDS response contains 2 localities, one with no endpoints.
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource({}), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource({}));
   Status status = SendRpc();
   EXPECT_FALSE(status.ok());
   EXPECT_EQ(status.error_code(), StatusCode::UNAVAILABLE);
@@ -3008,14 +3574,14 @@ TEST_P(LocalityMapTest, StressTest) {
     args.locality_list.emplace_back(std::move(locality));
   }
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // The second ADS response contains 1 locality, which contains backend 1.
   args = AdsServiceImpl::EdsResourceArgs({
       {"locality0", GetBackendPorts(1, 2)},
   });
-  std::thread delayed_resource_setter(std::bind(
-      &BasicTest::SetEdsResourceWithDelay, this, 0,
-      AdsServiceImpl::BuildEdsResource(args), 60 * 1000, kDefaultResourceName));
+  std::thread delayed_resource_setter(
+      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
+                AdsServiceImpl::BuildEdsResource(args), 60 * 1000));
   // Wait until backend 0 is ready, before which kNumLocalities localities are
   // received and handled by the xds policy.
   WaitForBackend(0, /*reset_counters=*/false);
@@ -3056,7 +3622,7 @@ TEST_P(LocalityMapTest, UpdateMap) {
       {"locality2", GetBackendPorts(2, 3), 4},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Wait for the first 3 backends to be ready.
   WaitForAllBackends(0, 3);
   gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
@@ -3087,7 +3653,7 @@ TEST_P(LocalityMapTest, UpdateMap) {
       {"locality3", GetBackendPorts(3, 4), 6},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Backend 3 hasn't received any request.
   EXPECT_EQ(0U, backends_[3]->backend_service()->request_count());
   // Wait until the locality update has been processed, as signaled by backend 3
@@ -3127,13 +3693,13 @@ TEST_P(LocalityMapTest, ReplaceAllLocalitiesInPriority) {
       {"locality0", GetBackendPorts(0, 1)},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   args = AdsServiceImpl::EdsResourceArgs({
       {"locality1", GetBackendPorts(1, 2)},
   });
-  std::thread delayed_resource_setter(std::bind(
-      &BasicTest::SetEdsResourceWithDelay, this, 0,
-      AdsServiceImpl::BuildEdsResource(args), 5000, kDefaultResourceName));
+  std::thread delayed_resource_setter(
+      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
+                AdsServiceImpl::BuildEdsResource(args), 5000));
   // Wait for the first backend to be ready.
   WaitForBackend(0);
   // Keep sending RPCs until we switch over to backend 1, which tells us
@@ -3162,7 +3728,7 @@ TEST_P(FailoverTest, ChooseHighestPriority) {
       {"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 0},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   WaitForBackend(3, false);
   for (size_t i = 0; i < 3; ++i) {
     EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
@@ -3180,13 +3746,29 @@ TEST_P(FailoverTest, DoesNotUsePriorityWithNoEndpoints) {
       {"locality3", {}, kDefaultLocalityWeight, 0},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   WaitForBackend(0, false);
   for (size_t i = 1; i < 3; ++i) {
     EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
   }
 }
 
+// Does not choose locality with no endpoints.
+TEST_P(FailoverTest, DoesNotUseLocalityWithNoEndpoints) {
+  SetNextResolution({});
+  SetNextResolutionForLbChannelAllBalancers();
+  AdsServiceImpl::EdsResourceArgs args({
+      {"locality0", {}, kDefaultLocalityWeight, 0},
+      {"locality1", GetBackendPorts(), kDefaultLocalityWeight, 0},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args));
+  // Wait for all backends to be used.
+  std::tuple<int, int, int> counts = WaitForAllBackends();
+  // Make sure no RPCs failed in the transition.
+  EXPECT_EQ(0, std::get<1>(counts));
+}
+
 // If the higher priority localities are not reachable, failover to the highest
 // priority among the rest.
 TEST_P(FailoverTest, Failover) {
@@ -3201,7 +3783,7 @@ TEST_P(FailoverTest, Failover) {
   ShutdownBackend(3);
   ShutdownBackend(0);
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   WaitForBackend(1, false);
   for (size_t i = 0; i < 4; ++i) {
     if (i == 1) continue;
@@ -3224,7 +3806,7 @@ TEST_P(FailoverTest, SwitchBackToHigherPriority) {
   ShutdownBackend(3);
   ShutdownBackend(0);
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   WaitForBackend(1, false);
   for (size_t i = 0; i < 4; ++i) {
     if (i == 1) continue;
@@ -3246,7 +3828,7 @@ TEST_P(FailoverTest, UpdateInitialUnavailable) {
       {"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 1},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   args = AdsServiceImpl::EdsResourceArgs({
       {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 0},
       {"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 1},
@@ -3255,9 +3837,9 @@ TEST_P(FailoverTest, UpdateInitialUnavailable) {
   });
   ShutdownBackend(0);
   ShutdownBackend(1);
-  std::thread delayed_resource_setter(std::bind(
-      &BasicTest::SetEdsResourceWithDelay, this, 0,
-      AdsServiceImpl::BuildEdsResource(args), 1000, kDefaultResourceName));
+  std::thread delayed_resource_setter(
+      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
+                AdsServiceImpl::BuildEdsResource(args), 1000));
   gpr_timespec deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                        gpr_time_from_millis(500, GPR_TIMESPAN));
   // Send 0.5 second worth of RPCs.
@@ -3285,16 +3867,16 @@ TEST_P(FailoverTest, UpdatePriority) {
       {"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 0},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   args = AdsServiceImpl::EdsResourceArgs({
       {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 2},
       {"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 0},
       {"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 1},
       {"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 3},
   });
-  std::thread delayed_resource_setter(std::bind(
-      &BasicTest::SetEdsResourceWithDelay, this, 0,
-      AdsServiceImpl::BuildEdsResource(args), 1000, kDefaultResourceName));
+  std::thread delayed_resource_setter(
+      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
+                AdsServiceImpl::BuildEdsResource(args), 1000));
   WaitForBackend(3, false);
   for (size_t i = 0; i < 3; ++i) {
     EXPECT_EQ(0U, backends_[i]->backend_service()->request_count());
@@ -3318,7 +3900,7 @@ TEST_P(FailoverTest, MoveAllLocalitiesInCurrentPriorityToHigherPriority) {
       {"locality1", GetBackendPorts(1, 3), kDefaultLocalityWeight, 1},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Second update:
   // - Priority 0 contains both localities 0 and 1.
   // - Priority 1 is not present.
@@ -3328,9 +3910,9 @@ TEST_P(FailoverTest, MoveAllLocalitiesInCurrentPriorityToHigherPriority) {
       {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 0},
       {"locality1", GetBackendPorts(1, 4), kDefaultLocalityWeight, 0},
   });
-  std::thread delayed_resource_setter(std::bind(
-      &BasicTest::SetEdsResourceWithDelay, this, 0,
-      AdsServiceImpl::BuildEdsResource(args), 1000, kDefaultResourceName));
+  std::thread delayed_resource_setter(
+      std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0,
+                AdsServiceImpl::BuildEdsResource(args), 1000));
   // When we get the first update, all backends in priority 0 are down,
   // so we will create priority 1.  Backends 1 and 2 should have traffic,
   // but backend 3 should not.
@@ -3339,8 +3921,8 @@ TEST_P(FailoverTest, MoveAllLocalitiesInCurrentPriorityToHigherPriority) {
   // When backend 3 gets traffic, we know the second update has been seen.
   WaitForBackend(3);
   // The ADS service of balancer 0 got at least 1 response.
-  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
+  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
   delayed_resource_setter.join();
 }
 
@@ -3364,7 +3946,7 @@ TEST_P(DropTest, Vanilla) {
   args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
                           {kThrottleDropType, kDropPerMillionForThrottle}};
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   WaitForAllBackends();
   // Send kNumRpcs RPCs and count the drops.
   size_t num_drops = 0;
@@ -3404,7 +3986,7 @@ TEST_P(DropTest, DropPerHundred) {
   args.drop_categories = {{kLbDropType, kDropPerHundredForLb}};
   args.drop_denominator = FractionalPercent::HUNDRED;
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   WaitForAllBackends();
   // Send kNumRpcs RPCs and count the drops.
   size_t num_drops = 0;
@@ -3443,7 +4025,7 @@ TEST_P(DropTest, DropPerTenThousand) {
   args.drop_categories = {{kLbDropType, kDropPerTenThousandForLb}};
   args.drop_denominator = FractionalPercent::TEN_THOUSAND;
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   WaitForAllBackends();
   // Send kNumRpcs RPCs and count the drops.
   size_t num_drops = 0;
@@ -3485,7 +4067,7 @@ TEST_P(DropTest, Update) {
   });
   args.drop_categories = {{kLbDropType, kDropPerMillionForLb}};
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   WaitForAllBackends();
   // Send kNumRpcs RPCs and count the drops.
   size_t num_drops = 0;
@@ -3516,7 +4098,7 @@ TEST_P(DropTest, Update) {
   args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
                           {kThrottleDropType, kDropPerMillionForThrottle}};
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Wait until the drop rate increases to the middle of the two configs, which
   // implies that the update has been in effect.
   const double kDropRateThreshold =
@@ -3574,7 +4156,7 @@ TEST_P(DropTest, DropAll) {
   args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
                           {kThrottleDropType, kDropPerMillionForThrottle}};
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Send kNumRpcs RPCs and all of them are dropped.
   for (size_t i = 0; i < kNumRpcs; ++i) {
     EchoResponse response;
@@ -3598,12 +4180,12 @@ TEST_P(BalancerUpdateTest, UpdateBalancersButKeepUsingOriginalBalancer) {
       {"locality0", {backends_[0]->port()}},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   args = AdsServiceImpl::EdsResourceArgs({
       {"locality0", {backends_[1]->port()}},
   });
   balancers_[1]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Wait until the first backend is ready.
   WaitForBackend(0);
   // Send 10 requests.
@@ -3613,12 +4195,12 @@ TEST_P(BalancerUpdateTest, UpdateBalancersButKeepUsingOriginalBalancer) {
   // All 10 requests should have gone to the first backend.
   EXPECT_EQ(10U, backends_[0]->backend_service()->request_count());
   // The ADS service of balancer 0 sent at least 1 response.
-  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
+  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
   gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 ==========");
   SetNextResolutionForLbChannel({balancers_[1]->port()});
   gpr_log(GPR_INFO, "========= UPDATE 1 DONE ==========");
@@ -3633,12 +4215,12 @@ TEST_P(BalancerUpdateTest, UpdateBalancersButKeepUsingOriginalBalancer) {
   // first balancer, which doesn't assign the second backend.
   EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
   // The ADS service of balancer 0 sent at least 1 response.
-  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
+  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
 }
 
 // Tests that the old LB call is still used after multiple balancer address
@@ -3653,12 +4235,12 @@ TEST_P(BalancerUpdateTest, Repeated) {
       {"locality0", {backends_[0]->port()}},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   args = AdsServiceImpl::EdsResourceArgs({
       {"locality0", {backends_[1]->port()}},
   });
   balancers_[1]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Wait until the first backend is ready.
   WaitForBackend(0);
   // Send 10 requests.
@@ -3668,12 +4250,12 @@ TEST_P(BalancerUpdateTest, Repeated) {
   // All 10 requests should have gone to the first backend.
   EXPECT_EQ(10U, backends_[0]->backend_service()->request_count());
   // The ADS service of balancer 0 sent at least 1 response.
-  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
+  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
   std::vector<int> ports;
   ports.emplace_back(balancers_[0]->port());
   ports.emplace_back(balancers_[1]->port());
@@ -3719,12 +4301,12 @@ TEST_P(BalancerUpdateTest, DeadUpdate) {
       {"locality0", {backends_[0]->port()}},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   args = AdsServiceImpl::EdsResourceArgs({
       {"locality0", {backends_[1]->port()}},
   });
   balancers_[1]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Start servers and send 10 RPCs per server.
   gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
   CheckRpcSendOk(10);
@@ -3732,12 +4314,12 @@ TEST_P(BalancerUpdateTest, DeadUpdate) {
   // All 10 requests should have gone to the first backend.
   EXPECT_EQ(10U, backends_[0]->backend_service()->request_count());
   // The ADS service of balancer 0 sent at least 1 response.
-  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
+  EXPECT_GT(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
   // Kill balancer 0
   gpr_log(GPR_INFO, "********** ABOUT TO KILL BALANCER 0 *************");
   balancers_[0]->Shutdown();
@@ -3750,12 +4332,12 @@ TEST_P(BalancerUpdateTest, DeadUpdate) {
   EXPECT_EQ(20U, backends_[0]->backend_service()->request_count());
   EXPECT_EQ(0U, backends_[1]->backend_service()->request_count());
   // The ADS service of no balancers sent anything
-  EXPECT_EQ(balancers_[0]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
+  EXPECT_EQ(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
   gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 ==========");
   SetNextResolutionForLbChannel({balancers_[1]->port()});
   gpr_log(GPR_INFO, "========= UPDATE 1 DONE ==========");
@@ -3772,12 +4354,12 @@ TEST_P(BalancerUpdateTest, DeadUpdate) {
   // All 10 requests should have gone to the second backend.
   EXPECT_EQ(10U, backends_[1]->backend_service()->request_count());
   // The ADS service of balancer 1 sent at least 1 response.
-  EXPECT_EQ(balancers_[0]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_GT(balancers_[1]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
-  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state(),
-            AdsServiceImpl::NOT_SENT);
+  EXPECT_EQ(balancers_[0]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_GT(balancers_[1]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
+  EXPECT_EQ(balancers_[2]->ads_service()->eds_response_state().state,
+            AdsServiceImpl::ResponseState::NOT_SENT);
 }
 
 // The re-resolution tests are deferred because they rely on the fallback mode,
@@ -3805,7 +4387,7 @@ TEST_P(ClientLoadReportingTest, Vanilla) {
       {"locality0", GetBackendPorts()},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Wait until all backends are ready.
   int num_ok = 0;
   int num_failure = 0;
@@ -3820,9 +4402,53 @@ TEST_P(ClientLoadReportingTest, Vanilla) {
     EXPECT_EQ(kNumRpcsPerAddress + kNumFailuresPerAddress,
               backends_[i]->backend_service()->request_count());
   }
+  // The load report received at the balancer should be correct.
+  std::vector<ClientStats> load_report =
+      balancers_[0]->lrs_service()->WaitForLoadReport();
+  ASSERT_EQ(load_report.size(), 1UL);
+  ClientStats& client_stats = load_report.front();
+  EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + num_ok,
+            client_stats.total_successful_requests());
+  EXPECT_EQ(0U, client_stats.total_requests_in_progress());
+  EXPECT_EQ((kNumRpcsPerAddress + kNumFailuresPerAddress) * num_backends_ +
+                num_ok + num_failure,
+            client_stats.total_issued_requests());
+  EXPECT_EQ(kNumFailuresPerAddress * num_backends_ + num_failure,
+            client_stats.total_error_requests());
+  EXPECT_EQ(0U, client_stats.total_dropped_requests());
   // The LRS service got a single request, and sent a single response.
   EXPECT_EQ(1U, balancers_[0]->lrs_service()->request_count());
   EXPECT_EQ(1U, balancers_[0]->lrs_service()->response_count());
+}
+
+// Tests send_all_clusters.
+TEST_P(ClientLoadReportingTest, SendAllClusters) {
+  balancers_[0]->lrs_service()->set_send_all_clusters(true);
+  SetNextResolution({});
+  SetNextResolutionForLbChannel({balancers_[0]->port()});
+  const size_t kNumRpcsPerAddress = 10;
+  const size_t kNumFailuresPerAddress = 3;
+  // TODO(juanlishen): Partition the backends after multiple localities is
+  // tested.
+  AdsServiceImpl::EdsResourceArgs args({
+      {"locality0", GetBackendPorts()},
+  });
+  balancers_[0]->ads_service()->SetEdsResource(
+      AdsServiceImpl::BuildEdsResource(args));
+  // Wait until all backends are ready.
+  int num_ok = 0;
+  int num_failure = 0;
+  int num_drops = 0;
+  std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends();
+  // Send kNumRpcsPerAddress RPCs per server.
+  CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
+  CheckRpcSendFailure(kNumFailuresPerAddress * num_backends_,
+                      /*server_fail=*/true);
+  // Check that each backend got the right number of requests.
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    EXPECT_EQ(kNumRpcsPerAddress + kNumFailuresPerAddress,
+              backends_[i]->backend_service()->request_count());
+  }
   // The load report received at the balancer should be correct.
   std::vector<ClientStats> load_report =
       balancers_[0]->lrs_service()->WaitForLoadReport();
@@ -3837,6 +4463,9 @@ TEST_P(ClientLoadReportingTest, Vanilla) {
   EXPECT_EQ(kNumFailuresPerAddress * num_backends_ + num_failure,
             client_stats.total_error_requests());
   EXPECT_EQ(0U, client_stats.total_dropped_requests());
+  // The LRS service got a single request, and sent a single response.
+  EXPECT_EQ(1U, balancers_[0]->lrs_service()->request_count());
+  EXPECT_EQ(1U, balancers_[0]->lrs_service()->response_count());
 }
 
 // Tests that we don't include stats for clusters that are not requested
@@ -3850,7 +4479,7 @@ TEST_P(ClientLoadReportingTest, HonorsClustersRequestedByLrsServer) {
       {"locality0", GetBackendPorts()},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Wait until all backends are ready.
   int num_ok = 0;
   int num_failure = 0;
@@ -3884,7 +4513,7 @@ TEST_P(ClientLoadReportingTest, BalancerRestart) {
       {"locality0", GetBackendPorts(0, kNumBackendsFirstPass)},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Wait until all backends returned by the balancer are ready.
   int num_ok = 0;
   int num_failure = 0;
@@ -3922,7 +4551,7 @@ TEST_P(ClientLoadReportingTest, BalancerRestart) {
       {"locality0", GetBackendPorts(kNumBackendsFirstPass)},
   });
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   // Wait for queries to start going to one of the new backends.
   // This tells us that we're now using the new serverlist.
   std::tie(num_ok, num_failure, num_drops) =
@@ -3964,7 +4593,7 @@ TEST_P(ClientLoadReportingWithDropTest, Vanilla) {
   args.drop_categories = {{kLbDropType, kDropPerMillionForLb},
                           {kThrottleDropType, kDropPerMillionForThrottle}};
   balancers_[0]->ads_service()->SetEdsResource(
-      AdsServiceImpl::BuildEdsResource(args), kDefaultResourceName);
+      AdsServiceImpl::BuildEdsResource(args));
   int num_ok = 0;
   int num_failure = 0;
   int num_drops = 0;
@@ -4035,10 +4664,12 @@ INSTANTIATE_TEST_SUITE_P(XdsTest, LdsTest,
                                            TestType(true, true)),
                          &TestTypeName);
 
-// RDS depends on XdsResolver.
-INSTANTIATE_TEST_SUITE_P(XdsTest, RdsTest,
+// LDS RDS Commmon tests  depends on XdsResolver.
+INSTANTIATE_TEST_SUITE_P(XdsTest, LdsRdsTest,
                          ::testing::Values(TestType(true, false),
-                                           TestType(true, true)),
+                                           TestType(true, true),
+                                           TestType(true, false, true),
+                                           TestType(true, true, true)),
                          &TestTypeName);
 
 // CDS depends on XdsResolver.
index 45fb68d..a23c5dd 100644 (file)
@@ -88,8 +88,15 @@ DEFINE_bool(do_not_abort_on_transient_failures, false,
             "test is retried in case of transient failures (and currently the "
             "interop tests are not retried even if this flag is set to true)");
 DEFINE_int32(soak_iterations, 1000,
-             "number of iterations to use for the two soak tests; rpc_soak and "
-             "channel_soak");
+             "The number of iterations to use for the two soak tests; rpc_soak "
+             "and channel_soak.");
+DEFINE_int32(soak_max_failures, 0,
+             "The number of iterations in soak tests that are allowed to fail "
+             "(either due to non-OK status code or exceeding the "
+             "per-iteration max acceptable latency).");
+DEFINE_int32(soak_per_iteration_max_acceptable_latency_ms, 0,
+             "The number of milliseconds a single iteration in the two soak "
+             "tests (rpc_soak and channel_soak) is allowed to take.");
 DEFINE_int32(iteration_interval, 10,
              "The interval in seconds between rpcs. This is used by "
              "long_connection test");
@@ -257,9 +264,12 @@ int main(int argc, char** argv) {
       std::bind(&grpc::testing::InteropClient::DoCacheableUnary, &client);
   actions["channel_soak"] =
       std::bind(&grpc::testing::InteropClient::DoChannelSoakTest, &client,
-                FLAGS_soak_iterations);
-  actions["rpc_soak"] = std::bind(&grpc::testing::InteropClient::DoRpcSoakTest,
-                                  &client, FLAGS_soak_iterations);
+                FLAGS_soak_iterations, FLAGS_soak_max_failures,
+                FLAGS_soak_per_iteration_max_acceptable_latency_ms);
+  actions["rpc_soak"] =
+      std::bind(&grpc::testing::InteropClient::DoRpcSoakTest, &client,
+                FLAGS_soak_iterations, FLAGS_soak_max_failures,
+                FLAGS_soak_per_iteration_max_acceptable_latency_ms);
   actions["long_lived_channel"] =
       std::bind(&grpc::testing::InteropClient::DoLongLivedChannelTest, &client,
                 FLAGS_soak_iterations, FLAGS_iteration_interval);
index 71ee79a..e889d24 100644 (file)
@@ -19,6 +19,7 @@
 #include <cinttypes>
 #include <fstream>
 #include <memory>
+#include <type_traits>
 #include <utility>
 
 #include <grpc/grpc.h>
@@ -33,6 +34,7 @@
 #include "src/proto/grpc/testing/empty.pb.h"
 #include "src/proto/grpc/testing/messages.pb.h"
 #include "src/proto/grpc/testing/test.grpc.pb.h"
+#include "test/core/util/histogram.h"
 #include "test/cpp/interop/client_helper.h"
 #include "test/cpp/interop/interop_client.h"
 
@@ -1065,36 +1067,121 @@ bool InteropClient::DoCustomMetadata() {
   return true;
 }
 
-bool InteropClient::DoRpcSoakTest(int32_t soak_iterations) {
-  gpr_log(GPR_DEBUG, "Sending %d RPCs...", soak_iterations);
-  GPR_ASSERT(soak_iterations > 0);
+std::tuple<bool, int32_t, std::string>
+InteropClient::PerformOneSoakTestIteration(
+    const bool reset_channel,
+    const int32_t max_acceptable_per_iteration_latency_ms) {
+  gpr_timespec start = gpr_now(GPR_CLOCK_MONOTONIC);
   SimpleRequest request;
   SimpleResponse response;
+  // Don't set the deadline on the RPC, and instead just
+  // record how long the RPC took and compare. This makes
+  // debugging easier when looking at failure results.
+  ClientContext context;
+  InteropClientContextInspector inspector(context);
+  request.set_response_size(kLargeResponseSize);
+  grpc::string payload(kLargeRequestSize, '\0');
+  request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
+  if (reset_channel) {
+    serviceStub_.ResetChannel();
+  }
+  Status s = serviceStub_.Get()->UnaryCall(&context, request, &response);
+  gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
+  int32_t elapsed_ms = gpr_time_to_millis(gpr_time_sub(now, start));
+  if (!s.ok()) {
+    return std::make_tuple(false, elapsed_ms, context.debug_error_string());
+  } else if (elapsed_ms > max_acceptable_per_iteration_latency_ms) {
+    char* out;
+    GPR_ASSERT(gpr_asprintf(
+                   &out, "%d ms exceeds max acceptable latency: %d ms.",
+                   elapsed_ms, max_acceptable_per_iteration_latency_ms) != -1);
+    std::string debug_string(out);
+    gpr_free(out);
+    return std::make_tuple(false, elapsed_ms, debug_string);
+  } else {
+    return std::make_tuple(true, elapsed_ms, "");
+  }
+}
+
+void InteropClient::PerformSoakTest(
+    const bool reset_channel_per_iteration, const int32_t soak_iterations,
+    const int32_t max_failures,
+    const int32_t max_acceptable_per_iteration_latency_ms) {
+  std::vector<std::tuple<bool, int32_t, std::string>> results;
+  grpc_histogram* latencies_ms_histogram = grpc_histogram_create(
+      1 /* resolution */,
+      500 * 1e3 /* largest bucket; 500 seconds is unlikely */);
   for (int i = 0; i < soak_iterations; ++i) {
-    if (!PerformLargeUnary(&request, &response)) {
-      gpr_log(GPR_ERROR, "rpc_soak test failed on iteration %d", i);
-      return false;
+    auto result = PerformOneSoakTestIteration(
+        reset_channel_per_iteration, max_acceptable_per_iteration_latency_ms);
+    results.push_back(result);
+    grpc_histogram_add(latencies_ms_histogram, std::get<1>(result));
+  }
+  int total_failures = 0;
+  for (size_t i = 0; i < results.size(); i++) {
+    bool success = std::get<0>(results[i]);
+    int32_t elapsed_ms = std::get<1>(results[i]);
+    std::string debug_string = std::get<2>(results[i]);
+    if (!success) {
+      gpr_log(GPR_DEBUG, "soak iteration: %ld elapsed_ms: %d failed: %s", i,
+              elapsed_ms, debug_string.c_str());
+      total_failures++;
+    } else {
+      gpr_log(GPR_DEBUG, "soak iteration: %ld elapsed_ms: %d succeeded", i,
+              elapsed_ms);
     }
   }
+  double latency_ms_median =
+      grpc_histogram_percentile(latencies_ms_histogram, 50);
+  double latency_ms_90th =
+      grpc_histogram_percentile(latencies_ms_histogram, 90);
+  double latency_ms_worst = grpc_histogram_maximum(latencies_ms_histogram);
+  grpc_histogram_destroy(latencies_ms_histogram);
+  if (total_failures > max_failures) {
+    gpr_log(GPR_ERROR,
+            "soak test ran: %d iterations. total_failures: %d exceeds "
+            "max_failures_threshold: %d. "
+            "median_soak_iteration_latency: %lf ms. "
+            "90th_soak_iteration_latency: %lf ms. "
+            "worst_soak_iteration_latency: %lf ms. "
+            "See breakdown above for which iterations succeeded, failed, and "
+            "why for more info.",
+            soak_iterations, total_failures, max_failures, latency_ms_median,
+            latency_ms_90th, latency_ms_worst);
+    GPR_ASSERT(0);
+  } else {
+    gpr_log(GPR_INFO,
+            "soak test ran: %d iterations. total_failures: %d is within "
+            "max_failures_threshold: %d. "
+            "median_soak_iteration_latency: %lf ms. "
+            "90th_soak_iteration_latency: %lf ms. "
+            "worst_soak_iteration_latency: %lf ms. "
+            "See breakdown above for which iterations succeeded, failed, and "
+            "why for more info.",
+            soak_iterations, total_failures, max_failures, latency_ms_median,
+            latency_ms_90th, latency_ms_worst);
+  }
+}
+
+bool InteropClient::DoRpcSoakTest(
+    int32_t soak_iterations, int32_t max_failures,
+    int64_t max_acceptable_per_iteration_latency_ms) {
+  gpr_log(GPR_DEBUG, "Sending %d RPCs...", soak_iterations);
+  GPR_ASSERT(soak_iterations > 0);
+  PerformSoakTest(false /* reset channel per iteration */, soak_iterations,
+                  max_failures, max_acceptable_per_iteration_latency_ms);
   gpr_log(GPR_DEBUG, "rpc_soak test done.");
   return true;
 }
 
-bool InteropClient::DoChannelSoakTest(int32_t soak_iterations) {
+bool InteropClient::DoChannelSoakTest(
+    int32_t soak_iterations, int32_t max_failures,
+    int64_t max_acceptable_per_iteration_latency_ms) {
   gpr_log(GPR_DEBUG, "Sending %d RPCs, tearing down the channel each time...",
           soak_iterations);
   GPR_ASSERT(soak_iterations > 0);
-  SimpleRequest request;
-  SimpleResponse response;
-  for (int i = 0; i < soak_iterations; ++i) {
-    serviceStub_.ResetChannel();
-    gpr_log(GPR_DEBUG, "Starting channel_soak iteration %d...", i);
-    if (!PerformLargeUnary(&request, &response)) {
-      gpr_log(GPR_ERROR, "channel_soak test failed on iteration %d", i);
-      return false;
-    }
-    gpr_log(GPR_DEBUG, "channel_soak iteration %d finished", i);
-  }
+  PerformSoakTest(true /* reset channel per iteration */, soak_iterations,
+                  max_failures, max_acceptable_per_iteration_latency_ms);
   gpr_log(GPR_DEBUG, "channel_soak test done.");
   return true;
 }
index 483d9be..2dc0d80 100644 (file)
@@ -76,8 +76,10 @@ class InteropClient {
   // not implemented cross-language. They are considered experimental for now,
   // but at some point in the future, might be codified and implemented in all
   // languages
-  bool DoChannelSoakTest(int32_t soak_iterations);
-  bool DoRpcSoakTest(int32_t soak_iterations);
+  bool DoChannelSoakTest(int32_t soak_iterations, int32_t max_failures,
+                         int64_t max_acceptable_per_iteration_latency_ms);
+  bool DoRpcSoakTest(int32_t soak_iterations, int32_t max_failures,
+                     int64_t max_acceptable_per_iteration_latency_ms);
   bool DoLongLivedChannelTest(int32_t soak_iterations,
                               int32_t iteration_interval);
 
@@ -128,6 +130,15 @@ class InteropClient {
                         const grpc::string& optional_debug_string);
   bool TransientFailureOrAbort();
 
+  std::tuple<bool, int32_t, std::string> PerformOneSoakTestIteration(
+      const bool reset_channel,
+      const int32_t max_acceptable_per_iteration_latency_ms);
+
+  void PerformSoakTest(const bool reset_channel_per_iteration,
+                       const int32_t soak_iterations,
+                       const int32_t max_failures,
+                       const int32_t max_acceptable_per_iteration_latency_ms);
+
   ServiceStub serviceStub_;
   /// If true, abort() is not called for transient failures
   bool do_not_abort_on_transient_failures_;
index 6cb32b2..6d7f3c2 100644 (file)
 #include "test/core/util/test_config.h"
 #include "test/cpp/util/test_config.h"
 
+DEFINE_bool(fail_on_failed_rpc, false, "Fail client if any RPCs fail.");
 DEFINE_int32(num_channels, 1, "Number of channels.");
 DEFINE_bool(print_response, false, "Write RPC response to stdout.");
 DEFINE_int32(qps, 1, "Qps per channel.");
-DEFINE_int32(rpc_timeout_sec, 10, "Per RPC timeout seconds.");
+DEFINE_int32(rpc_timeout_sec, 30, "Per RPC timeout seconds.");
 DEFINE_string(server, "localhost:50051", "Address of server.");
 DEFINE_int32(stats_port, 50052,
              "Port to expose peer distribution stats service.");
@@ -155,14 +156,19 @@ class TestClient {
         }
       }
 
-      if (FLAGS_print_response) {
-        if (call->status.ok()) {
+      if (!call->status.ok()) {
+        if (FLAGS_print_response || FLAGS_fail_on_failed_rpc) {
+          std::cout << "RPC failed: " << call->status.error_code() << ": "
+                    << call->status.error_message() << std::endl;
+        }
+        if (FLAGS_fail_on_failed_rpc) {
+          abort();
+        }
+      } else {
+        if (FLAGS_print_response) {
           std::cout << "Greeting: Hello world, this is "
                     << call->response.hostname() << ", from "
                     << call->context.peer() << std::endl;
-        } else {
-          std::cout << "RPC failed: " << call->status.error_code() << ": "
-                    << call->status.error_message() << std::endl;
         }
       }
 
index e8065fa..d26815f 100644 (file)
@@ -282,7 +282,6 @@ grpc_cc_test(
 grpc_cc_test(
     name = "bm_opencensus_plugin",
     srcs = ["bm_opencensus_plugin.cc"],
-    flaky = True,  # TODO(b/151696309)
     language = "C++",
     deps = [
         ":helpers_secure",
index 908d34a..5f335f0 100644 (file)
@@ -28,6 +28,7 @@
 #include "opencensus/stats/stats.h"
 #include "src/cpp/ext/filters/census/grpc_plugin.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/core/util/test_config.h"
 #include "test/cpp/microbenchmarks/helpers.h"
 
 using ::grpc::RegisterOpenCensusPlugin;
@@ -86,6 +87,8 @@ class EchoServerThread final {
 };
 
 static void BM_E2eLatencyCensusDisabled(benchmark::State& state) {
+  grpc::testing::TestEnvironment env(0, {});
+
   EchoServerThread server;
   std::unique_ptr<grpc::testing::EchoTestService::Stub> stub =
       grpc::testing::EchoTestService::NewStub(grpc::CreateChannel(
@@ -101,11 +104,7 @@ static void BM_E2eLatencyCensusDisabled(benchmark::State& state) {
 BENCHMARK(BM_E2eLatencyCensusDisabled);
 
 static void BM_E2eLatencyCensusEnabled(benchmark::State& state) {
-  // Avoid a data race between registering plugin and shutdown of previous
-  // test (order-dependent) by doing an init/shutdown so that any previous
-  // shutdowns are fully complete first.
-  grpc_init();
-  grpc_shutdown_blocking();
+  grpc::testing::TestEnvironment env(0, {});
 
   // Now start the test by registering the plugin (once in the execution)
   RegisterOnce();
index b35c37c..dd2dac7 100644 (file)
@@ -38,6 +38,7 @@ grpc_cc_test(
     name = "cancel_ares_query_test",
     srcs = ["cancel_ares_query_test.cc"],
     external_deps = ["gtest"],
+    flaky = True,  # TODO(b/157516105)
     deps = [
         ":dns_test_util",
         "//:gpr",
index dd49a2c..38203bc 100644 (file)
@@ -64,25 +64,25 @@ struct TestAddress {
 };
 
 grpc_resolved_address TestAddressToGrpcResolvedAddress(TestAddress test_addr) {
-  grpc_core::UniquePtr<char> host;
-  grpc_core::UniquePtr<char> port;
+  std::string host;
+  std::string port;
   grpc_resolved_address resolved_addr;
   grpc_core::SplitHostPort(test_addr.dest_addr.c_str(), &host, &port);
   if (test_addr.family == AF_INET) {
     sockaddr_in in_dest;
     memset(&in_dest, 0, sizeof(sockaddr_in));
-    in_dest.sin_port = htons(atoi(port.get()));
+    in_dest.sin_port = htons(atoi(port.c_str()));
     in_dest.sin_family = AF_INET;
-    GPR_ASSERT(inet_pton(AF_INET, host.get(), &in_dest.sin_addr) == 1);
+    GPR_ASSERT(inet_pton(AF_INET, host.c_str(), &in_dest.sin_addr) == 1);
     memcpy(&resolved_addr.addr, &in_dest, sizeof(sockaddr_in));
     resolved_addr.len = sizeof(sockaddr_in);
   } else {
     GPR_ASSERT(test_addr.family == AF_INET6);
     sockaddr_in6 in6_dest;
     memset(&in6_dest, 0, sizeof(sockaddr_in6));
-    in6_dest.sin6_port = htons(atoi(port.get()));
+    in6_dest.sin6_port = htons(atoi(port.c_str()));
     in6_dest.sin6_family = AF_INET6;
-    GPR_ASSERT(inet_pton(AF_INET6, host.get(), &in6_dest.sin6_addr) == 1);
+    GPR_ASSERT(inet_pton(AF_INET6, host.c_str(), &in6_dest.sin6_addr) == 1);
     memcpy(&resolved_addr.addr, &in6_dest, sizeof(sockaddr_in6));
     resolved_addr.len = sizeof(sockaddr_in6);
   }
@@ -108,19 +108,17 @@ class MockSourceAddrFactory : public address_sorting_source_addr_factory {
          !ipv6_supported_)) {
       return false;
     }
-    char* ip_addr_str;
     grpc_resolved_address dest_addr_as_resolved_addr;
     memcpy(&dest_addr_as_resolved_addr.addr, dest_addr, dest_addr->len);
     dest_addr_as_resolved_addr.len = dest_addr->len;
-    grpc_sockaddr_to_string(&ip_addr_str, &dest_addr_as_resolved_addr,
-                            false /* normalize */);
+    std::string ip_addr_str = grpc_sockaddr_to_string(
+        &dest_addr_as_resolved_addr, false /* normalize */);
     auto it = dest_addr_to_src_addr_.find(ip_addr_str);
     if (it == dest_addr_to_src_addr_.end()) {
-      gpr_log(GPR_DEBUG, "can't find |%s| in dest to src map", ip_addr_str);
-      gpr_free(ip_addr_str);
+      gpr_log(GPR_DEBUG, "can't find |%s| in dest to src map",
+              ip_addr_str.c_str());
       return false;
     }
-    gpr_free(ip_addr_str);
     grpc_resolved_address source_addr_as_resolved_addr =
         TestAddressToGrpcResolvedAddress(it->second);
     memcpy(source_addr->addr, &source_addr_as_resolved_addr.addr,
@@ -180,13 +178,10 @@ void VerifyLbAddrOutputs(const grpc_core::ServerAddressList& addresses,
                          std::vector<std::string> expected_addrs) {
   EXPECT_EQ(addresses.size(), expected_addrs.size());
   for (size_t i = 0; i < addresses.size(); ++i) {
-    char* ip_addr_str;
-    grpc_sockaddr_to_string(&ip_addr_str, &addresses[i].address(),
-                            false /* normalize */);
+    std::string ip_addr_str =
+        grpc_sockaddr_to_string(&addresses[i].address(), false /* normalize */);
     EXPECT_EQ(expected_addrs[i], ip_addr_str);
-    gpr_free(ip_addr_str);
   }
-  grpc_core::ExecCtx exec_ctx;
 }
 
 /* We need to run each test case inside of its own
index b7b4ebd..c367dfd 100644 (file)
@@ -36,9 +36,9 @@
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/thd.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/pollset.h"
 #include "src/core/lib/iomgr/pollset_set.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/util/cmdline.h"
 #include "test/core/util/port.h"
@@ -81,7 +81,7 @@ struct ArgsStruct {
   gpr_mu* mu;
   grpc_pollset* pollset;
   grpc_pollset_set* pollset_set;
-  grpc_core::Combiner* lock;
+  std::shared_ptr<grpc_core::WorkSerializer> lock;
   grpc_channel_args* channel_args;
 };
 
@@ -90,7 +90,7 @@ void ArgsInit(ArgsStruct* args) {
   grpc_pollset_init(args->pollset, &args->mu);
   args->pollset_set = grpc_pollset_set_create();
   grpc_pollset_set_add_pollset(args->pollset_set, args->pollset);
-  args->lock = grpc_combiner_create();
+  args->lock = std::make_shared<grpc_core::WorkSerializer>();
   gpr_atm_rel_store(&args->done_atm, 0);
   args->channel_args = nullptr;
 }
@@ -109,7 +109,6 @@ void ArgsFinish(ArgsStruct* args) {
   grpc_core::ExecCtx::Get()->Flush();
   grpc_pollset_destroy(args->pollset);
   gpr_free(args->pollset);
-  GRPC_COMBINER_UNREF(args->lock, nullptr);
 }
 
 void PollPollsetUntilRequestDone(ArgsStruct* args) {
index 9829116..59d12be 100755 (executable)
@@ -44,6 +44,8 @@ def _resolver_test_cases(resolver_component_data):
                 target_name,
             'arg_names_and_values': [
                 ('target_name', target_name),
+                ('do_ordered_address_comparison',
+                 test_case['do_ordered_address_comparison']),
                 ('expected_addrs',
                  _build_expected_addrs_cmd_arg(test_case['expected_addrs'])),
                 ('expected_chosen_service_config',
index f323ae0..cb065a3 100644 (file)
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gprpp/host_port.h"
 #include "src/core/lib/gprpp/orphanable.h"
-#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/socket_utils.h"
+#include "src/core/lib/iomgr/work_serializer.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
@@ -87,6 +87,13 @@ using namespace google;
 using namespace gflags;
 
 DEFINE_string(target_name, "", "Target name to resolve.");
+DEFINE_string(do_ordered_address_comparison, "",
+              "Whether or not to compare resolved addresses to expected "
+              "addresses using an ordered comparison. This is useful for "
+              "testing certain behaviors that involve sorting of resolved "
+              "addresses. Note it would be better if this argument was a "
+              "bool flag, but it's a string for ease of invocation from "
+              "the generated python test runner.");
 DEFINE_string(expected_addrs, "",
               "List of expected backend or balancer addresses in the form "
               "'<ip0:port0>,<is_balancer0>;<ip1:port1>,<is_balancer1>;...'. "
@@ -193,7 +200,7 @@ struct ArgsStruct {
   gpr_mu* mu;
   grpc_pollset* pollset;
   grpc_pollset_set* pollset_set;
-  grpc_core::Combiner* lock;
+  std::shared_ptr<grpc_core::WorkSerializer> lock;
   grpc_channel_args* channel_args;
   vector<GrpcLBAddress> expected_addrs;
   std::string expected_service_config_string;
@@ -207,7 +214,7 @@ void ArgsInit(ArgsStruct* args) {
   grpc_pollset_init(args->pollset, &args->mu);
   args->pollset_set = grpc_pollset_set_create();
   grpc_pollset_set_add_pollset(args->pollset_set, args->pollset);
-  args->lock = grpc_combiner_create();
+  args->lock = std::make_shared<grpc_core::WorkSerializer>();
   gpr_atm_rel_store(&args->done_atm, 0);
   args->channel_args = nullptr;
 }
@@ -227,7 +234,6 @@ void ArgsFinish(ArgsStruct* args) {
   grpc_core::ExecCtx::Get()->Flush();
   grpc_pollset_destroy(args->pollset);
   gpr_free(args->pollset);
-  GRPC_COMBINER_UNREF(args->lock, nullptr);
 }
 
 gpr_timespec NSecondDeadline(int seconds) {
@@ -485,8 +491,18 @@ class CheckingResultHandler : public ResultHandler {
               found_lb_addrs.size(), args->expected_addrs.size());
       abort();
     }
-    EXPECT_THAT(args->expected_addrs,
-                UnorderedElementsAreArray(found_lb_addrs));
+    if (FLAGS_do_ordered_address_comparison == "True") {
+      EXPECT_EQ(args->expected_addrs, found_lb_addrs);
+    } else if (FLAGS_do_ordered_address_comparison == "False") {
+      EXPECT_THAT(args->expected_addrs,
+                  UnorderedElementsAreArray(found_lb_addrs));
+    } else {
+      gpr_log(GPR_ERROR,
+              "Invalid for setting for --do_ordered_address_comparison. "
+              "Have %s, want True or False",
+              FLAGS_do_ordered_address_comparison.c_str());
+      GPR_ASSERT(0);
+    }
     const char* service_config_json =
         result.service_config == nullptr
             ? nullptr
@@ -504,11 +520,10 @@ class CheckingResultHandler : public ResultHandler {
                                  std::vector<GrpcLBAddress>* out) {
     for (size_t i = 0; i < addresses.size(); i++) {
       const grpc_core::ServerAddress& addr = addresses[i];
-      char* str;
-      grpc_sockaddr_to_string(&str, &addr.address(), 1 /* normalize */);
-      gpr_log(GPR_INFO, "%s", str);
-      out->emplace_back(GrpcLBAddress(std::string(str), is_balancer));
-      gpr_free(str);
+      std::string str =
+          grpc_sockaddr_to_string(&addr.address(), true /* normalize */);
+      gpr_log(GPR_INFO, "%s", str.c_str());
+      out->emplace_back(GrpcLBAddress(std::move(str), is_balancer));
     }
   }
 };
@@ -522,8 +537,8 @@ int g_fake_non_responsive_dns_server_port = -1;
 void InjectBrokenNameServerList(ares_channel channel) {
   struct ares_addr_port_node dns_server_addrs[2];
   memset(dns_server_addrs, 0, sizeof(dns_server_addrs));
-  grpc_core::UniquePtr<char> unused_host;
-  grpc_core::UniquePtr<char> local_dns_server_port;
+  std::string unused_host;
+  std::string local_dns_server_port;
   GPR_ASSERT(grpc_core::SplitHostPort(FLAGS_local_dns_server_address.c_str(),
                                       &unused_host, &local_dns_server_port));
   gpr_log(GPR_DEBUG,
@@ -544,16 +559,13 @@ void InjectBrokenNameServerList(ares_channel channel) {
   dns_server_addrs[1].family = AF_INET;
   ((char*)&dns_server_addrs[1].addr.addr4)[0] = 0x7f;
   ((char*)&dns_server_addrs[1].addr.addr4)[3] = 0x1;
-  dns_server_addrs[1].tcp_port = atoi(local_dns_server_port.get());
-  dns_server_addrs[1].udp_port = atoi(local_dns_server_port.get());
+  dns_server_addrs[1].tcp_port = atoi(local_dns_server_port.c_str());
+  dns_server_addrs[1].udp_port = atoi(local_dns_server_port.c_str());
   dns_server_addrs[1].next = nullptr;
   GPR_ASSERT(ares_set_servers_ports(channel, dns_server_addrs) == ARES_SUCCESS);
 }
 
-void StartResolvingLocked(void* arg, grpc_error* /*unused*/) {
-  grpc_core::Resolver* r = static_cast<grpc_core::Resolver*>(arg);
-  r->StartLocked();
-}
+void StartResolvingLocked(grpc_core::Resolver* r) { r->StartLocked(); }
 
 void RunResolvesRelevantRecordsTest(
     std::unique_ptr<grpc_core::Resolver::ResultHandler> (*CreateResultHandler)(
@@ -632,9 +644,9 @@ void RunResolvesRelevantRecordsTest(
                                                   CreateResultHandler(&args));
   grpc_channel_args_destroy(resolver_args);
   gpr_free(whole_uri);
-  args.lock->Run(
-      GRPC_CLOSURE_CREATE(StartResolvingLocked, resolver.get(), nullptr),
-      GRPC_ERROR_NONE);
+  auto* resolver_ptr = resolver.get();
+  args.lock->Run([resolver_ptr]() { StartResolvingLocked(resolver_ptr); },
+                 DEBUG_LOCATION);
   grpc_core::ExecCtx::Get()->Flush();
   PollPollsetUntilRequestDone(&args);
   ArgsFinish(&args);
index e5ff9cd..bb54453 100755 (executable)
@@ -122,6 +122,7 @@ test_runner_log('Run test with target: %s' % 'no-srv-ipv4-single-target.resolver
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'no-srv-ipv4-single-target.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '5.5.5.5:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -138,6 +139,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv4-single-target.resolver-te
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv4-single-target.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:1234,True',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -154,6 +156,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv4-multi-target.resolver-tes
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv4-multi-target.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.5:1234,True;1.2.3.6:1234,True;1.2.3.7:1234,True',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -170,6 +173,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv6-single-target.resolver-te
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv6-single-target.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '[2607:f8b0:400a:801::1001]:1234,True',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -186,6 +190,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv6-multi-target.resolver-tes
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv6-multi-target.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '[2607:f8b0:400a:801::1002]:1234,True;[2607:f8b0:400a:801::1003]:1234,True;[2607:f8b0:400a:801::1004]:1234,True',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -202,6 +207,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv4-simple-service-config.res
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv4-simple-service-config.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:1234,True',
   '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService"}],"waitForReady":true}]}',
   '--expected_service_config_error', '',
@@ -218,6 +224,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-no-srv-simple-service-config.
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-no-srv-simple-service-config.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"NoSrvSimpleService"}],"waitForReady":true}]}',
   '--expected_service_config_error', '',
@@ -234,6 +241,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-no-config-for-cpp.resolver-te
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-no-config-for-cpp.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -250,6 +258,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-cpp-config-has-zero-percentag
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-cpp-config-has-zero-percentage.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -266,6 +275,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-second-language-is-cpp.resolv
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-second-language-is-cpp.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"CppService"}],"waitForReady":true}]}',
   '--expected_service_config_error', '',
@@ -282,6 +292,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-config-with-percentages.resol
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-config-with-percentages.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"AlwaysPickedService"}],"waitForReady":true}]}',
   '--expected_service_config_error', '',
@@ -298,6 +309,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv4-target-has-backend-and-ba
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv4-target-has-backend-and-balancer.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:1234,True;1.2.3.4:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -314,6 +326,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv6-target-has-backend-and-ba
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv6-target-has-backend-and-balancer.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '[2607:f8b0:400a:801::1002]:1234,True;[2607:f8b0:400a:801::1002]:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -330,6 +343,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-config-causing-fallback-to-tc
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-config-causing-fallback-to-tcp.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooTwo","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooThree","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooFour","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooFive","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooSix","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooSeven","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooEight","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooNine","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooTen","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooEleven","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooTwelve","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooThirteen","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooFourteen","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooFifteen","service":"SimpleService"}],"waitForReady":true}]}',
   '--expected_service_config_error', '',
@@ -346,6 +360,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv4-single-target-srv-disable
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv4-single-target-srv-disabled.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '2.3.4.5:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -362,6 +377,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv4-multi-target-srv-disabled
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv4-multi-target-srv-disabled.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '9.2.3.5:443,False;9.2.3.6:443,False;9.2.3.7:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -378,6 +394,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv6-single-target-srv-disable
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv6-single-target-srv-disabled.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '[2600::1001]:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -394,6 +411,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv6-multi-target-srv-disabled
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv6-multi-target-srv-disabled.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '[2600::1002]:443,False;[2600::1003]:443,False;[2600::1004]:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -410,6 +428,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv4-simple-service-config-srv
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv4-simple-service-config-srv-disabled.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '5.5.3.4:443,False',
   '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService"}],"waitForReady":true}]}',
   '--expected_service_config_error', '',
@@ -426,6 +445,7 @@ test_runner_log('Run test with target: %s' % 'srv-ipv4-simple-service-config-txt
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'srv-ipv4-simple-service-config-txt-disabled.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:1234,True',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -442,6 +462,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-cpp-config-has-zero-percentag
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-cpp-config-has-zero-percentage-txt-disabled.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -458,6 +479,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-second-language-is-cpp-txt-di
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-second-language-is-cpp-txt-disabled.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -474,6 +496,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-svc_cfg_bad_json.resolver-tes
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-svc_cfg_bad_json.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', 'JSON parse error',
@@ -490,6 +513,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-svc_cfg_bad_client_language.r
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-svc_cfg_bad_client_language.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', 'field:clientLanguage error:should be of type array',
@@ -506,6 +530,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-svc_cfg_bad_percentage.resolv
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-svc_cfg_bad_percentage.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', 'field:percentage error:should be of type number',
@@ -522,6 +547,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-svc_cfg_bad_wait_for_ready.re
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-svc_cfg_bad_wait_for_ready.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', 'field:waitForReady error:Type should be true/false',
@@ -538,6 +564,7 @@ test_runner_log('Run test with target: %s' % 'no-srv-ipv4-single-target-inject-b
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'no-srv-ipv4-single-target-inject-broken-nameservers.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '5.5.5.5:443,False',
   '--expected_chosen_service_config', '',
   '--expected_service_config_error', '',
@@ -554,6 +581,7 @@ test_runner_log('Run test with target: %s' % 'ipv4-config-causing-fallback-to-tc
 current_test_subprocess = subprocess.Popen([
   args.test_bin_path,
   '--target_name', 'ipv4-config-causing-fallback-to-tcp-inject-broken-nameservers.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'False',
   '--expected_addrs', '1.2.3.4:443,False',
   '--expected_chosen_service_config', '{"loadBalancingPolicy":["round_robin"]}',
   '--expected_service_config_error', 'field:loadBalancingPolicy error:type should be string',
@@ -566,6 +594,23 @@ current_test_subprocess.communicate()
 if current_test_subprocess.returncode != 0:
   num_test_failures += 1
 
+test_runner_log('Run test with target: %s' % 'load-balanced-name-with-dualstack-balancer.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'load-balanced-name-with-dualstack-balancer.resolver-tests-version-4.grpctestingexp.',
+  '--do_ordered_address_comparison', 'True',
+  '--expected_addrs', '[::1]:1234,True;[2002::1111]:1234,True',
+  '--expected_chosen_service_config', '',
+  '--expected_service_config_error', '',
+  '--expected_lb_policy', '',
+  '--enable_srv_queries', 'True',
+  '--enable_txt_queries', 'True',
+  '--inject_broken_nameserver_list', 'False',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
 test_runner_log('now kill DNS server')
 dns_server_subprocess.kill()
 dns_server_subprocess.wait()
index c44c39f..af89fb7 100644 (file)
@@ -3,6 +3,7 @@ resolver_component_tests:
 # Tests for which we enable SRV queries
 - expected_addrs:
   - {address: '5.5.5.5:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -15,6 +16,7 @@ resolver_component_tests:
     - {TTL: '2100', data: 5.5.5.5, type: A}
 - expected_addrs:
   - {address: '1.2.3.4:1234', is_balancer: true}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -31,6 +33,7 @@ resolver_component_tests:
   - {address: '1.2.3.5:1234', is_balancer: true}
   - {address: '1.2.3.6:1234', is_balancer: true}
   - {address: '1.2.3.7:1234', is_balancer: true}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -47,6 +50,7 @@ resolver_component_tests:
     - {TTL: '2100', data: 1.2.3.7, type: A}
 - expected_addrs:
   - {address: '[2607:f8b0:400a:801::1001]:1234', is_balancer: true}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -63,6 +67,7 @@ resolver_component_tests:
   - {address: '[2607:f8b0:400a:801::1002]:1234', is_balancer: true}
   - {address: '[2607:f8b0:400a:801::1003]:1234', is_balancer: true}
   - {address: '[2607:f8b0:400a:801::1004]:1234', is_balancer: true}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -79,6 +84,7 @@ resolver_component_tests:
     - {TTL: '2100', data: '2607:f8b0:400a:801::1004', type: AAAA}
 - expected_addrs:
   - {address: '1.2.3.4:1234', is_balancer: true}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService"}],"waitForReady":true}]}'
   expected_service_config_error: null
   expected_lb_policy: round_robin
@@ -96,6 +102,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"NoSrvSimpleService"}],"waitForReady":true}]}'
   expected_service_config_error: null
   expected_lb_policy: round_robin
@@ -111,6 +118,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -126,6 +134,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -141,6 +150,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"CppService"}],"waitForReady":true}]}'
   expected_service_config_error: null
   expected_lb_policy: round_robin
@@ -156,6 +166,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"AlwaysPickedService"}],"waitForReady":true}]}'
   expected_service_config_error: null
   expected_lb_policy: round_robin
@@ -172,6 +183,7 @@ resolver_component_tests:
 - expected_addrs:
   - {address: '1.2.3.4:1234', is_balancer: true}
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -189,6 +201,7 @@ resolver_component_tests:
 - expected_addrs:
   - {address: '[2607:f8b0:400a:801::1002]:1234', is_balancer: true}
   - {address: '[2607:f8b0:400a:801::1002]:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -205,6 +218,7 @@ resolver_component_tests:
     - {TTL: '2100', data: '2607:f8b0:400a:801::1002', type: AAAA}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooTwo","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooThree","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooFour","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooFive","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooSix","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooSeven","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooEight","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooNine","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooTen","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooEleven","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooTwelve","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooThirteen","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooFourteen","service":"SimpleService"}],"waitForReady":true},{"name":[{"method":"FooFifteen","service":"SimpleService"}],"waitForReady":true}]}'
   expected_service_config_error: null
   expected_lb_policy: null
@@ -221,6 +235,7 @@ resolver_component_tests:
 # Tests for which we don't enable SRV queries
 - expected_addrs:
   - {address: '2.3.4.5:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -239,6 +254,7 @@ resolver_component_tests:
   - {address: '9.2.3.5:443', is_balancer: false}
   - {address: '9.2.3.6:443', is_balancer: false}
   - {address: '9.2.3.7:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -259,6 +275,7 @@ resolver_component_tests:
     - {TTL: '2100', data: 9.2.3.7, type: A}
 - expected_addrs:
   - {address: '[2600::1001]:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -277,6 +294,7 @@ resolver_component_tests:
   - {address: '[2600::1002]:443', is_balancer: false}
   - {address: '[2600::1003]:443', is_balancer: false}
   - {address: '[2600::1004]:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -297,6 +315,7 @@ resolver_component_tests:
     - {TTL: '2100', data: '2600::1004', type: AAAA}
 - expected_addrs:
   - {address: '5.5.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService"}],"waitForReady":true}]}'
   expected_service_config_error: null
   expected_lb_policy: round_robin
@@ -316,6 +335,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:1234', is_balancer: true}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -333,6 +353,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -348,6 +369,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -363,6 +385,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: 'JSON parse error'
   expected_lb_policy: null
@@ -378,6 +401,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: 'field:clientLanguage error:should be of type array'
   expected_lb_policy: null
@@ -393,6 +417,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: 'field:percentage error:should be of type number'
   expected_lb_policy: null
@@ -408,6 +433,7 @@ resolver_component_tests:
       type: TXT}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: 'field:waitForReady error:Type should be true/false'
   expected_lb_policy: null
@@ -420,10 +446,11 @@ resolver_component_tests:
     - {TTL: '2100', data: 1.2.3.4, type: A}
     _grpc_config.ipv4-svc_cfg_bad_wait_for_ready:
     - {TTL: '2100', data: 'grpc_config=[{"serviceConfig":{"methodConfig":[{"name":[{"method":"Foo","service":"CppService"}],"waitForReady":"true"}]}}]',
-      type: TXT}      
+      type: TXT}
 # Tests for which we also exercise the resolver's ability to skip past a broken DNS server in its nameserver list
 - expected_addrs:
   - {address: '5.5.5.5:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: null
   expected_service_config_error: null
   expected_lb_policy: null
@@ -436,6 +463,7 @@ resolver_component_tests:
     - {TTL: '2100', data: 5.5.5.5, type: A}
 - expected_addrs:
   - {address: '1.2.3.4:443', is_balancer: false}
+  do_ordered_address_comparison: false
   expected_chosen_service_config: '{"loadBalancingPolicy":["round_robin"]}'
   expected_service_config_error: 'field:loadBalancingPolicy error:type should be string'
   expected_lb_policy: null
@@ -449,3 +477,26 @@ resolver_component_tests:
     _grpc_config.ipv4-config-causing-fallback-to-tcp-inject-broken-nameservers:
     - {TTL: '2100', data: 'grpc_config=[{"serviceConfig":{"loadBalancingPolicy":["round_robin"]}}]',
       type: TXT}
+# This tests that gRPCLB addresses are sorted properly per RFC 6724. Note
+# that the only assumption that this makes is that the machine that the
+# test runs on has a functioning IPv6 loopback (which by the RFC should
+# always be preferred). Note too that the ordering of the AAAA records
+# listed under the dualstack-balancer name is important in order to
+# actually test this sorting.
+- expected_addrs:
+  - {address: '[::1]:1234', is_balancer: true}
+  - {address: '[2002::1111]:1234', is_balancer: true}
+  do_ordered_address_comparison: true
+  expected_chosen_service_config: null
+  expected_service_config_error: null
+  expected_lb_policy: null
+  enable_srv_queries: true
+  enable_txt_queries: true
+  inject_broken_nameserver_list: false
+  record_to_resolve: load-balanced-name-with-dualstack-balancer
+  records:
+    _grpclb._tcp.load-balanced-name-with-dualstack-balancer:
+    - {TTL: '2100', data: 0 0 1234 dualstack-balancer, type: SRV}
+    dualstack-balancer:
+    - {TTL: '2100', data: '2002::1111', type: AAAA}
+    - {TTL: '2100', data: '::1', type: AAAA}
index 03a4477..deac6c4 100644 (file)
@@ -52,8 +52,8 @@ using std::vector;
 namespace grpc {
 namespace testing {
 static std::string get_host(const std::string& worker) {
-  grpc_core::StringView host;
-  grpc_core::StringView port;
+  absl::string_view host;
+  absl::string_view port;
   grpc_core::SplitHostPort(worker.c_str(), &host, &port);
   return std::string(host.data(), host.size());
 }
@@ -326,6 +326,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
     if (server_config.core_limit() != 0) {
       gpr_log(GPR_ERROR,
               "server config core limit is set but ignored by driver");
+      GPR_ASSERT(false);
     }
 
     ServerArgs args;
@@ -333,10 +334,12 @@ std::unique_ptr<ScenarioResult> RunScenario(
     servers[i].stream = servers[i].stub->RunServer(alloc_context(&contexts));
     if (!servers[i].stream->Write(args)) {
       gpr_log(GPR_ERROR, "Could not write args to server %zu", i);
+      GPR_ASSERT(false);
     }
     ServerStatus init_status;
     if (!servers[i].stream->Read(&init_status)) {
       gpr_log(GPR_ERROR, "Server %zu did not yield initial status", i);
+      GPR_ASSERT(false);
     }
     if (qps_server_target_override.length() > 0) {
       // overriding the qps server target only works if there is 1 server
@@ -347,11 +350,10 @@ std::unique_ptr<ScenarioResult> RunScenario(
       cli_target += std::to_string(i);
       client_config.add_server_targets(cli_target);
     } else {
-      std::string host;
-      grpc_core::UniquePtr<char> cli_target;
-      host = get_host(workers[i]);
-      grpc_core::JoinHostPort(&cli_target, host.c_str(), init_status.port());
-      client_config.add_server_targets(cli_target.get());
+      std::string host = get_host(workers[i]);
+      std::string cli_target =
+          grpc_core::JoinHostPort(host.c_str(), init_status.port());
+      client_config.add_server_targets(cli_target.c_str());
     }
   }
 
@@ -384,6 +386,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
 
     if (initial_client_config.core_limit() != 0) {
       gpr_log(GPR_ERROR, "client config core limit set but ignored");
+      GPR_ASSERT(false);
     }
 
     // Reduce channel count so that total channels specified is held regardless
@@ -401,6 +404,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
     clients[i].stream = clients[i].stub->RunClient(alloc_context(&contexts));
     if (!clients[i].stream->Write(args)) {
       gpr_log(GPR_ERROR, "Could not write args to client %zu", i);
+      GPR_ASSERT(false);
     }
   }
 
@@ -408,6 +412,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
     ClientStatus init_status;
     if (!clients[i].stream->Read(&init_status)) {
       gpr_log(GPR_ERROR, "Client %zu did not yield initial status", i);
+      GPR_ASSERT(false);
     }
   }
 
@@ -424,12 +429,14 @@ std::unique_ptr<ScenarioResult> RunScenario(
     auto client = &clients[i];
     if (!client->stream->Write(client_mark)) {
       gpr_log(GPR_ERROR, "Couldn't write mark to client %zu", i);
+      GPR_ASSERT(false);
     }
   }
   for (size_t i = 0; i < num_clients; i++) {
     auto client = &clients[i];
     if (!client->stream->Read(&client_status)) {
       gpr_log(GPR_ERROR, "Couldn't get status from client %zu", i);
+      GPR_ASSERT(false);
     }
   }
 
@@ -445,24 +452,28 @@ std::unique_ptr<ScenarioResult> RunScenario(
     auto server = &servers[i];
     if (!server->stream->Write(server_mark)) {
       gpr_log(GPR_ERROR, "Couldn't write mark to server %zu", i);
+      GPR_ASSERT(false);
     }
   }
   for (size_t i = 0; i < num_clients; i++) {
     auto client = &clients[i];
     if (!client->stream->Write(client_mark)) {
       gpr_log(GPR_ERROR, "Couldn't write mark to client %zu", i);
+      GPR_ASSERT(false);
     }
   }
   for (size_t i = 0; i < num_servers; i++) {
     auto server = &servers[i];
     if (!server->stream->Read(&server_status)) {
       gpr_log(GPR_ERROR, "Couldn't get status from server %zu", i);
+      GPR_ASSERT(false);
     }
   }
   for (size_t i = 0; i < num_clients; i++) {
     auto client = &clients[i];
     if (!client->stream->Read(&client_status)) {
       gpr_log(GPR_ERROR, "Couldn't get status from client %zu", i);
+      GPR_ASSERT(false);
     }
   }
 
@@ -486,9 +497,11 @@ std::unique_ptr<ScenarioResult> RunScenario(
     auto client = &clients[i];
     if (!client->stream->Write(client_mark)) {
       gpr_log(GPR_ERROR, "Couldn't write mark to client %zu", i);
+      GPR_ASSERT(false);
     }
     if (!client->stream->WritesDone()) {
       gpr_log(GPR_ERROR, "Failed WritesDone for client %zu", i);
+      GPR_ASSERT(false);
     }
   }
   gpr_log(GPR_INFO, "Finishing servers");
@@ -496,9 +509,11 @@ std::unique_ptr<ScenarioResult> RunScenario(
     auto server = &servers[i];
     if (!server->stream->Write(server_mark)) {
       gpr_log(GPR_ERROR, "Couldn't write mark to server %zu", i);
+      GPR_ASSERT(false);
     }
     if (!server->stream->WritesDone()) {
       gpr_log(GPR_ERROR, "Failed WritesDone for server %zu", i);
+      GPR_ASSERT(false);
     }
   }
 
@@ -518,6 +533,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
       GPR_ASSERT(!client->stream->Read(&client_status));
     } else {
       gpr_log(GPR_ERROR, "Couldn't get final status from client %zu", i);
+      GPR_ASSERT(false);
     }
   }
   for (size_t i = 0; i < num_clients; i++) {
@@ -531,6 +547,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
     if (!success) {
       gpr_log(GPR_ERROR, "Client %zu had an error %s", i,
               s.error_message().c_str());
+      GPR_ASSERT(false);
     }
   }
 
@@ -553,6 +570,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
       GPR_ASSERT(!server->stream->Read(&server_status));
     } else {
       gpr_log(GPR_ERROR, "Couldn't get final status from server %zu", i);
+      GPR_ASSERT(false);
     }
   }
   for (size_t i = 0; i < num_servers; i++) {
@@ -566,6 +584,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
     if (!success) {
       gpr_log(GPR_ERROR, "Server %zu had an error %s", i,
               s.error_message().c_str());
+      GPR_ASSERT(false);
     }
   }
 
index 78dae62..fd20776 100644 (file)
@@ -108,6 +108,7 @@ class WorkerServiceImpl final : public WorkerService::Service {
   Status RunClient(
       ServerContext* ctx,
       ServerReaderWriter<ClientStatus, ClientArgs>* stream) override {
+    gpr_log(GPR_INFO, "RunClient: Entering");
     InstanceGuard g(this);
     if (!g.Acquired()) {
       return Status(StatusCode::RESOURCE_EXHAUSTED, "Client worker busy");
@@ -122,6 +123,7 @@ class WorkerServiceImpl final : public WorkerService::Service {
   Status RunServer(
       ServerContext* ctx,
       ServerReaderWriter<ServerStatus, ServerArgs>* stream) override {
+    gpr_log(GPR_INFO, "RunServer: Entering");
     InstanceGuard g(this);
     if (!g.Acquired()) {
       return Status(StatusCode::RESOURCE_EXHAUSTED, "Server worker busy");
@@ -279,15 +281,23 @@ QpsWorker::QpsWorker(int driver_port, int server_port,
 
   std::unique_ptr<ServerBuilder> builder = CreateQpsServerBuilder();
   if (driver_port >= 0) {
-    grpc_core::UniquePtr<char> server_address;
-    grpc_core::JoinHostPort(&server_address, "::", driver_port);
+    std::string server_address = grpc_core::JoinHostPort("::", driver_port);
     builder->AddListeningPort(
-        server_address.get(),
+        server_address.c_str(),
         GetCredentialsProvider()->GetServerCredentials(credential_type));
   }
   builder->RegisterService(impl_.get());
 
   server_ = builder->BuildAndStart();
+  if (server_ == nullptr) {
+    gpr_log(GPR_ERROR,
+            "QpsWorker: Fail to BuildAndStart(driver_port=%d, server_port=%d)",
+            driver_port, server_port);
+  } else {
+    gpr_log(GPR_INFO,
+            "QpsWorker: BuildAndStart(driver_port=%d, server_port=%d) done",
+            driver_port, server_port);
+  }
 }
 
 QpsWorker::~QpsWorker() {}
index b6cb020..6a07acc 100644 (file)
@@ -80,9 +80,8 @@ class AsyncQpsServerTest final : public grpc::testing::Server {
     auto port_num = port();
     // Negative port number means inproc server, so no listen port needed
     if (port_num >= 0) {
-      grpc_core::UniquePtr<char> server_address;
-      grpc_core::JoinHostPort(&server_address, "::", port_num);
-      builder->AddListeningPort(server_address.get(),
+      std::string server_address = grpc_core::JoinHostPort("::", port_num);
+      builder->AddListeningPort(server_address.c_str(),
                                 Server::CreateServerCredentials(config));
     }
 
index 4b6f651..e4aa109 100644 (file)
@@ -102,9 +102,8 @@ class CallbackServer final : public grpc::testing::Server {
     auto port_num = port();
     // Negative port number means inproc server, so no listen port needed
     if (port_num >= 0) {
-      grpc_core::UniquePtr<char> server_address;
-      grpc_core::JoinHostPort(&server_address, "::", port_num);
-      builder->AddListeningPort(server_address.get(),
+      std::string server_address = grpc_core::JoinHostPort("::", port_num);
+      builder->AddListeningPort(server_address.c_str(),
                                 Server::CreateServerCredentials(config));
     }
 
index f69a8f0..19d406a 100644 (file)
@@ -160,9 +160,8 @@ class SynchronousServer final : public grpc::testing::Server {
     auto port_num = port();
     // Negative port number means inproc server, so no listen port needed
     if (port_num >= 0) {
-      grpc_core::UniquePtr<char> server_address;
-      grpc_core::JoinHostPort(&server_address, "::", port_num);
-      builder->AddListeningPort(server_address.get(),
+      std::string server_address = grpc_core::JoinHostPort("::", port_num);
+      builder->AddListeningPort(server_address.c_str(),
                                 Server::CreateServerCredentials(config));
     }
 
index c3695ba..2a8ad6d 100644 (file)
@@ -202,7 +202,6 @@ grpc_cc_test(
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing:simple_messages_proto",
-        "//test/core/end2end:ssl_test_data",
         "//test/core/util:grpc_test_util",
     ],
 )
index 1f7af81..207bef1 100644 (file)
@@ -48,9 +48,13 @@ DEFINE_string(
     "If not empty, load this PEM formatted private key. Requires use of "
     "--ssl_client_cert");
 DEFINE_string(
+    local_connect_type, "local_tcp",
+    "The type of local connections for which local channel credentials will "
+    "be applied. Should be local_tcp or uds.");
+DEFINE_string(
     channel_creds_type, "",
-    "The channel creds type: insecure, ssl, gdc (Google Default Credentials) "
-    "or alts.");
+    "The channel creds type: insecure, ssl, gdc (Google Default Credentials), "
+    "alts, or local.");
 DEFINE_string(
     call_creds, "",
     "Call credentials to use: none (default), or access_token=<token>. If "
@@ -138,10 +142,20 @@ CliCredentials::GetChannelCredentials() const {
   } else if (FLAGS_channel_creds_type.compare("alts") == 0) {
     return grpc::experimental::AltsCredentials(
         grpc::experimental::AltsCredentialsOptions());
+  } else if (FLAGS_channel_creds_type.compare("local") == 0) {
+    if (FLAGS_local_connect_type.compare("local_tcp") == 0) {
+      return grpc::experimental::LocalCredentials(LOCAL_TCP);
+    } else if (FLAGS_local_connect_type.compare("uds") == 0) {
+      return grpc::experimental::LocalCredentials(UDS);
+    } else {
+      fprintf(stderr,
+              "--local_connect_type=%s invalid; must be local_tcp or uds.\n",
+              FLAGS_local_connect_type.c_str());
+    }
   }
   fprintf(stderr,
-          "--channel_creds_type=%s invalid; must be insecure, ssl, gdc or "
-          "alts.\n",
+          "--channel_creds_type=%s invalid; must be insecure, ssl, gdc, "
+          "alts, or local.\n",
           FLAGS_channel_creds_type.c_str());
   return std::shared_ptr<grpc::ChannelCredentials>();
 }
@@ -203,7 +217,8 @@ std::shared_ptr<grpc::ChannelCredentials> CliCredentials::GetCredentials()
 }
 
 const grpc::string CliCredentials::GetCredentialUsage() const {
-  return "    --enable_ssl             ; Set whether to use ssl (deprecated)\n"
+  return "    --enable_ssl             ; Set whether to use ssl "
+         "(deprecated)\n"
          "    --use_auth               ; Set whether to create default google"
          " credentials\n"
          "                             ; (deprecated)\n"
@@ -213,7 +228,9 @@ const grpc::string CliCredentials::GetCredentialUsage() const {
          "    --ssl_target             ; Set server host for ssl validation\n"
          "    --ssl_client_cert        ; Client cert for ssl\n"
          "    --ssl_client_key         ; Client private key for ssl\n"
-         "    --channel_creds_type     ; Set to insecure, ssl, gdc, or alts\n"
+         "    --local_connect_type     ; Set to local_tcp or uds\n"
+         "    --channel_creds_type     ; Set to insecure, ssl, gdc, alts, or "
+         "local\n"
          "    --call_creds             ; Set to none, or"
          " access_token=<token>\n";
 }
index 10e13d9..663b44b 100644 (file)
@@ -51,6 +51,9 @@
        --decode=grpc.testing.SimpleResponse \
        src/proto/grpc/testing/messages.proto \
        < output.bin > output.txt
+   10. --default_service_config, optional default service config to use
+       on the channel. Note that this may be ignored if the name resolver
+       returns a service config.
 */
 
 #include <fstream>
@@ -68,10 +71,10 @@ DEFINE_string(outfile, "", "Output file (default is stdout)");
 static bool SimplePrint(const grpc::string& outfile,
                         const grpc::string& output) {
   if (outfile.empty()) {
-    std::cout << output << std::endl;
+    std::cout << output << std::flush;
   } else {
     std::ofstream output_file(outfile, std::ios::app | std::ios::binary);
-    output_file << output << std::endl;
+    output_file << output << std::flush;
     output_file.close();
   }
   return true;
index 053fd38..a7bdb2b 100644 (file)
@@ -57,6 +57,11 @@ DEFINE_string(proto_path, ".", "Path to look for the proto file.");
 DEFINE_string(protofiles, "", "Name of the proto file.");
 DEFINE_bool(binary_input, false, "Input in binary format");
 DEFINE_bool(binary_output, false, "Output in binary format");
+DEFINE_string(
+    default_service_config, "",
+    "Default service config to use on the channel, if non-empty. Note "
+    "that this will be ignored if the name resolver returns a service "
+    "config.");
 DEFINE_bool(json_input, false, "Input in json format");
 DEFINE_bool(json_output, false, "Output in json format");
 DEFINE_string(infile, "", "Input file (default is stdin)");
@@ -217,6 +222,10 @@ std::shared_ptr<grpc::Channel> CreateCliChannel(
   if (!cred.GetSslTargetNameOverride().empty()) {
     args.SetSslTargetNameOverride(cred.GetSslTargetNameOverride());
   }
+  if (!FLAGS_default_service_config.empty()) {
+    args.SetString(GRPC_ARG_SERVICE_CONFIG,
+                   FLAGS_default_service_config.c_str());
+  }
   return ::grpc::CreateCustomChannel(server_address, cred.GetCredentials(),
                                      args);
 }
index 175f16c..5d15e8c 100644 (file)
@@ -118,6 +118,7 @@ DECLARE_bool(batch);
 DECLARE_string(metadata);
 DECLARE_string(protofiles);
 DECLARE_string(proto_path);
+DECLARE_string(default_service_config);
 
 namespace {
 
@@ -1192,6 +1193,28 @@ TEST_F(GrpcToolTest, ListCommand_OverrideSslHostName) {
   ShutdownServer();
 }
 
+TEST_F(GrpcToolTest, ConfiguringDefaultServiceConfig) {
+  // Test input "grpc_cli list localhost:<port>
+  // --default_service_config={\"loadBalancingConfig\":[{\"pick_first\":{}}]}"
+  std::stringstream output_stream;
+  const grpc::string server_address = SetUpServer();
+  const char* argv[] = {"grpc_cli", "ls", server_address.c_str()};
+  // Just check that the tool is still operational when --default_service_config
+  // is configured. This particular service config is in reality redundant with
+  // the channel's default configuration.
+  FLAGS_l = false;
+  FLAGS_default_service_config =
+      "{\"loadBalancingConfig\":[{\"pick_first\":{}}]}";
+  EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+                                   std::bind(PrintStream, &output_stream,
+                                             std::placeholders::_1)));
+  FLAGS_default_service_config = "";
+  EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
+                          "grpc.testing.EchoTestService\n"
+                          "grpc.reflection.v1alpha.ServerReflection\n"));
+  ShutdownServer();
+}
+
 }  // namespace testing
 }  // namespace grpc
 
index f2f22f9..e65c1f8 100644 (file)
     <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="Google.Protobuf, Version=3.11.2.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
-      <HintPath>..\packages\Google.Protobuf.3.11.2\lib\net45\Google.Protobuf.dll</HintPath>
+    <Reference Include="Google.Protobuf">
+      <HintPath>..\packages\Google.Protobuf.3.12.2\lib\net45\Google.Protobuf.dll</HintPath>
     </Reference>
   </ItemGroup>
   <ItemGroup>
index 014b983..75c7973 100644 (file)
@@ -16,7 +16,7 @@
     <PackageReference Include="Grpc" Version="__GRPC_NUGET_VERSION__" />
     <PackageReference Include="Grpc.Auth" Version="__GRPC_NUGET_VERSION__" />
     <PackageReference Include="Grpc.Tools" Version="__GRPC_NUGET_VERSION__" />
-    <PackageReference Include="Google.Protobuf" Version="3.11.2" />
+    <PackageReference Include="Google.Protobuf" Version="3.12.2" />
   </ItemGroup>
   
   <ItemGroup>
@@ -27,4 +27,4 @@
   <ItemGroup>
     <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
index e0ba8ee..0703376 100644 (file)
@@ -8,9 +8,9 @@
   <package id="Grpc.Core" version="__GRPC_NUGET_VERSION__" targetFramework="net45" />
   <package id="Grpc.Core.Api" version="__GRPC_NUGET_VERSION__" targetFramework="net45" />
   <package id="Grpc.Tools" version="__GRPC_NUGET_VERSION__" targetFramework="net45" />
-  <package id="Google.Protobuf" version="3.11.2" targetFramework="net45" />
+  <package id="Google.Protobuf" version="3.12.2" targetFramework="net45" />
   <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
   <package id="System.Buffers" version="4.4.0" targetFramework="net45" />
   <package id="System.Memory" version="4.5.3" targetFramework="net45" />
   <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net45" />
-</packages>
\ No newline at end of file
+</packages>
index a581d1f..70b7590 100644 (file)
@@ -20,20 +20,24 @@ load("@bazel_toolchains//rules/exec_properties:exec_properties.bzl", "create_exe
 
 alias(
     name = "rbe_windows",
-    actual = ":rbe_windows_1803",
+    actual = ":rbe_windows_2019",
 )
 
 # RBE Windows
 platform(
-    name = "rbe_windows_1803",
+    name = "rbe_windows_2019",
     constraint_values = [
         "@bazel_tools//platforms:x86_64",
         "@bazel_tools//platforms:windows",
-        "@bazel_tools//tools/cpp:msvc",
     ],
     exec_properties = create_exec_properties_dict(
-        container_image = "docker://gcr.io/grpc-testing/rbe_windows_toolchain@sha256:75728e7d6d804090f71095e5fec627b18cfa1f47adc52096c209f2a687e06b2e",
-        gce_machine_type = "n1-highmem-2",
+        # See rbe_win2019/Dockerfile for image details
+        container_image = "docker://gcr.io/grpc-testing/rbe_windows2019_withdbg_toolchain@sha256:7b04ee7e29f942adbf4f70edd2ec4ba20a3e7237e1b54f5cae4b239c6ca41105",
+        
+        # Use a different machine type than used on linux to avoid accidentally scheduling linux jobs on windows workers and vice versa on older release branches
+        gce_machine_type = "n1-standard-2",
         os_family = "Windows",
+        # labels only supported starting from https://github.com/bazelbuild/bazel-toolchains/pull/748
+        #labels = {"os": "windows_2019"},
     ),
 )
diff --git a/third_party/toolchains/README.md b/third_party/toolchains/README.md
new file mode 100644 (file)
index 0000000..4a26825
--- /dev/null
@@ -0,0 +1,5 @@
+# Windows RBE toolchain configuration
+
+- bazel_0.26.0_rbe_windows: The autogenerated toolchain for windows RBE. See go/rbe-windows-user-guide
+
+- rbe_win2019: The windows dockerfile to rebuild the docker image we use on RBE workers. See go/rbe-windows-user-guide
\ No newline at end of file
@@ -1,79 +1,76 @@
+# This dockerfile is taken from go/rbe-windows-user-guide
+# (including the fix --compilation_mode=dbg)
+
 # This Dockerfile creates an image that:
 # - Has the correct MTU setting for networking from inside the container to work.
 # - Has Visual Studio 2015 Build Tools installed.
 # - Has msys2 + git, curl, zip, unzip installed.
 # - Has Python 2.7 installed.
-# - Has Bazel installed.
-
 # TODO(jsharpe): Consider replacing "ADD $URI $DEST" with "Invoke-WebRequest -Method Get -Uri $URI -OutFile $DEST"
-
 # Use the latest Windows Server Core image.
 #
-# WARNING: What's the `:1803` about? There are two versions of Windows Server
-# 2016: a "regular" one (corresponding to `microsoft/windowsservercore`) is on
-# a slow release cadence, and a fast release cadence one (corresponding to
-# `microsoft/windowsservercore:1803`). If you chose a different image than
-# described above, probably omit the `:1803` or change it to a different
-# number.
-FROM microsoft/windowsservercore:1803
-
+# WARNING: What's the `:ltsc2019` about?
+# There are two versions of Windows Server 2019:
+# 1. A "regular" one (corresponding to `mcr.microsoft.com/windows/servercore:ltsc2019`)
+# is on a slow release cadence and is the Long-Term Servicing Channel.
+# Mainstream support for this image will end on 1/9/2024.
+# 2. A "fast" release cadence one (corresponding to
+# `mcr.microsoft.com/windows/servercore:1909`) is the Semi-Annual Channel.
+# Mainstream support for this image will end on 5/11/2021.
+#
+# If you choose a different
+# image than described above, change the `:ltsc2019` tag.
+# Start a temporary container in which we install 7-Zip to extract msys2
+FROM mcr.microsoft.com/windows/servercore:ltsc2019 as extract-msys2
 SHELL ["powershell.exe", "-ExecutionPolicy", "Bypass", "-Command", "$ErrorActionPreference='Stop'; $ProgressPreference='SilentlyContinue'; $VerbosePreference = 'Continue';"]
-
-# TODO(b/112379377): Workaround until bug is fixed.
-RUN netsh interface ipv4 set subinterface \"vEthernet (Ethernet)\" mtu=1460 store=persistent
-
-# Install Visual Studio 2015 Build Tools.
-RUN Invoke-WebRequest "https://download.microsoft.com/download/5/f/7/5f7acaeb-8363-451f-9425-68a90f98b238/visualcppbuildtools_full.exe" \
-                -OutFile visualcppbuildtools_full.exe -UseBasicParsing ; \
-        Start-Process -FilePath 'visualcppbuildtools_full.exe' -ArgumentList '/quiet', '/NoRestart' -Wait ; \
-        Remove-Item .\visualcppbuildtools_full.exe;
-
-# TODO(jsharpe): Alternate install for msys2: https://github.com/StefanScherer/dockerfiles-windows/issues/30
-
 # Install 7-Zip and add it to the path.
 ADD https://www.7-zip.org/a/7z1801-x64.msi C:\\TEMP\\7z.msi
 RUN Start-Process msiexec.exe -ArgumentList \"/i C:\\TEMP\\7z.msi /qn /norestart /log C:\\TEMP\\7z_install_log.txt\" -wait
 RUN $oldpath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).path; \
   $newpath = \"$oldpath;C:\Program Files\7-Zip\"; \
   Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath
-
-# Install msys2, and add some extra tools.
-ADD http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20161025.tar.xz C:\\TEMP\\msys2.tar.xz
+# Extract msys2
+ADD http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20181211.tar.xz C:\\TEMP\\msys2.tar.xz
 RUN 7z x C:\TEMP\msys2.tar.xz -oC:\TEMP\msys2.tar
 RUN 7z x C:\TEMP\msys2.tar -oC:\tools
+# Start building the actual image
+FROM mcr.microsoft.com/windows/servercore:ltsc2019
+SHELL ["powershell.exe", "-ExecutionPolicy", "Bypass", "-Command", "$ErrorActionPreference='Stop'; $ProgressPreference='SilentlyContinue'; $VerbosePreference = 'Continue';"]
+# TODO(b/112379377): Workaround until bug is fixed.
+RUN Get-NetAdapter | Where-Object Name -like "*Ethernet*" | ForEach-Object { & netsh interface ipv4 set subinterface $_.InterfaceIndex mtu=1460 store=persistent }
+# Enable Long Paths for Win32 File/Folder APIs.
+RUN New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem -Name LongPathsEnabled -Value 1 -PropertyType DWORD -Force
+
+# Install Visual Studio 2015 Build Tools.
+RUN Invoke-WebRequest "https://download.microsoft.com/download/5/f/7/5f7acaeb-8363-451f-9425-68a90f98b238/visualcppbuildtools_full.exe" \
+                -OutFile visualcppbuildtools_full.exe -UseBasicParsing ; \
+        Start-Process -FilePath 'visualcppbuildtools_full.exe' -ArgumentList '/quiet', '/NoRestart', '/InstallSelectableItems "Win10SDK_VisibleV1"' -Wait ; \
+        Remove-Item .\visualcppbuildtools_full.exe;
+# Add ucrtbased.dll to the system directory to allow --compilation_mode=dbg to
+# work. This DLL should be automatically copied to C:\Windows\System32 by the
+# installer, but isn't when the installer is run on Docker, for some reason.
+RUN Copy-Item \"C:\Program Files (x86)\Windows Kits\10\bin\x64\ucrt\ucrtbased.dll\" C:\Windows\System32
+
+
+# TODO(jsharpe): Alternate install for msys2: https://github.com/StefanScherer/dockerfiles-windows/issues/30
+# From the temporary extract-msys2 container, copy the tools directory to this container
+COPY --from=extract-msys2 ["C:/tools", "C:/tools"]
+# Add msys2 to the PATH variable
 RUN $oldpath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).path; \
   $newpath = \"$oldpath;C:\tools\msys64;C:\tools\msys64\usr\bin\"; \
   Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath
-RUN Start-Process msys2 -ArgumentList 'pacman -noconfirm -Syuu git curl zip unzip' -Wait
-
+# Bazel documentation says to use -Syuu but this doesn't work in Docker. See
+# http://g/foundry-windows/PDMVXbGew7Y
+RUN bash.exe -c \"pacman-key --init && pacman-key --populate msys2 && pacman-key --refresh-keys && pacman --noconfirm -Syy git curl zip unzip\"
 # Install Visual C++ Redistributable for Visual Studio 2015:
 ADD https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe C:\\TEMP\\vc_redist.x64.exe
 RUN C:\TEMP\vc_redist.x64.exe /quiet /install
-
 # Install Python 2.7.
 ADD https://www.python.org/ftp/python/2.7.14/python-2.7.14.amd64.msi C:\\TEMP\\python.msi
 RUN Start-Process msiexec.exe -ArgumentList \"/i C:\\TEMP\\python.msi /qn /norestart /log C:\\TEMP\\python_install_log.txt\" -wait
 RUN $oldpath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).path; \
   $newpath = \"$oldpath;C:\Python27\"; \
   Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath
-
-# Install Bazel.
-RUN Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name BAZEL_SH -Value \"C:\tools\msys64\usr\bin\bash.exe\"
-RUN Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name BAZEL_VC -Value \"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\"
-RUN [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;
-ADD https://github.com/bazelbuild/bazel/releases/download/0.26.0/bazel-0.26.0-windows-x86_64.exe C:\\bin\\bazel.exe
-RUN $oldpath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).path; \
-  $newpath = \"$oldpath;C:\bin\"; \
-  Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath
-
-# TODO(jsharpe): This requires entropy so may be problematic on a headless machine: https://wiki.archlinux.org/index.php/Pacman/Package_signing#Initializing_the_keyring
-RUN Start-Process msys2 -ArgumentList 'pacman-key --init' -Wait
-# TODO(jsharpe): If you don't run this then the next command can't succeed since it needs to prompt to remove catgets.
-RUN pacman --noconfirm -R libcatgets catgets
-# Bazel documentation says to use -Syuu but this doesn't work in Docker. See
-# http://g/foundry-windows/PDMVXbGew7Y
-RUN pacman --noconfirm -Syy git curl zip unzip
-
 RUN \
   Add-Type -AssemblyName \"System.IO.Compression.FileSystem\"; \
   $zulu_url = \"https://cdn.azul.com/zulu/bin/zulu8.28.0.1-jdk8.0.163-win_x64.zip\"; \
@@ -88,9 +85,10 @@ RUN \
   [Environment]::SetEnvironmentVariable(\"PATH\", $env:PATH, \"Machine\"); \
   $env:JAVA_HOME = $zulu_root; \
   [Environment]::SetEnvironmentVariable(\"JAVA_HOME\", $env:JAVA_HOME, \"Machine\")
-
 # Restore default shell for Windows containers.
 SHELL ["cmd.exe", "/s", "/c"]
-
 # Default to PowerShell if no other command specified.
 CMD ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
+
+
+
index bc8f78c..ba56492 100755 (executable)
@@ -43,7 +43,9 @@ fi
 VERSION=1.0.0
 echo "INFO: Running bazel wrapper (see //tools/bazel for details), bazel version $VERSION will be used instead of system-wide bazel installation." >&2
 
-BASEURL=https://github.com/bazelbuild/bazel/releases/download/
+# update tools/update_mirror.sh to populate the mirror with new bazel archives
+BASEURL_MIRROR="https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/bazel/releases/download"
+BASEURL="https://github.com/bazelbuild/bazel/releases/download"
 pushd "$(dirname "$0")" >/dev/null
 TOOLDIR=$(pwd)
 
@@ -63,7 +65,9 @@ esac
 filename="bazel-$VERSION-$suffix"
 
 if [ ! -x "$filename" ] ; then
-  curl -L "$BASEURL/$VERSION/$filename" > "$filename"
+  # first try to download using mirror, fallback to download from github
+  echo "Downloading bazel, will try URLs: ${BASEURL_MIRROR}/${VERSION}/${filename} ${BASEURL}/${VERSION}/${filename}" >&2
+  curl --fail -L --output "${filename}" "${BASEURL_MIRROR}/${VERSION}/${filename}" || curl --fail -L --output "${filename}" "${BASEURL}/${VERSION}/${filename}"
   chmod a+x "$filename"
 fi
 
index 8dd57c4..51d2993 100755 (executable)
@@ -37,17 +37,23 @@ proto_files=( \
   "envoy/annotations/deprecation.proto" \
   "envoy/annotations/resource.proto" \
   "envoy/api/v2/auth/cert.proto" \
+  "envoy/api/v2/auth/common.proto" \
+  "envoy/api/v2/auth/secret.proto" \
+  "envoy/api/v2/auth/tls.proto" \
   "envoy/api/v2/cds.proto" \
   "envoy/api/v2/cluster/circuit_breaker.proto" \
   "envoy/api/v2/cluster/filter.proto" \
   "envoy/api/v2/cluster/outlier_detection.proto" \
   "envoy/api/v2/core/address.proto" \
   "envoy/api/v2/core/base.proto" \
+  "envoy/api/v2/core/backoff.proto" \
   "envoy/api/v2/core/config_source.proto" \
+  "envoy/api/v2/core/event_service_config.proto" \
   "envoy/api/v2/core/grpc_service.proto" \
   "envoy/api/v2/core/health_check.proto" \
   "envoy/api/v2/core/http_uri.proto" \
   "envoy/api/v2/core/protocol.proto" \
+  "envoy/api/v2/core/socket_option.proto" \
   "envoy/api/v2/cluster.proto" \
   "envoy/api/v2/discovery.proto" \
   "envoy/api/v2/eds.proto" \
@@ -68,6 +74,7 @@ proto_files=( \
   "envoy/config/listener/v2/api_listener.proto" \
   "envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto" \
   "envoy/config/filter/accesslog/v2/accesslog.proto" \
+  "envoy/config/trace/v2/http_tracer.proto" \
   "envoy/service/discovery/v2/ads.proto" \
   "envoy/service/load_stats/v2/lrs.proto" \
   "envoy/type/http.proto" \
@@ -98,6 +105,7 @@ proto_files=( \
   "udpa/data/orca/v1/orca_load_report.proto" \
   "udpa/annotations/migrate.proto" \
   "udpa/annotations/sensitive.proto" \
+  "udpa/annotations/status.proto" \
   "validate/validate.proto")
 
 for i in "${proto_files[@]}"
index 831d62e..c264bf8 100755 (executable)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import print_function
 import argparse
 import datetime
 import os
@@ -129,9 +130,9 @@ assert (re.search(RE_LICENSE['Makefile'], load('Makefile')))
 def log(cond, why, filename):
     if not cond: return
     if args.output == 'details':
-        print '%s: %s' % (why, filename)
+        print('%s: %s' % (why, filename))
     else:
-        print filename
+        print(filename)
 
 
 # scan files, validate the text
diff --git a/tools/distrib/python/grpc_prefixed/.gitignore b/tools/distrib/python/grpc_prefixed/.gitignore
new file mode 100644 (file)
index 0000000..9d0b71a
--- /dev/null
@@ -0,0 +1,2 @@
+build
+dist
diff --git a/tools/distrib/python/grpc_prefixed/generate.py b/tools/distrib/python/grpc_prefixed/generate.py
new file mode 100644 (file)
index 0000000..864971f
--- /dev/null
@@ -0,0 +1,140 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Generates grpc-prefixed packages using template renderer.
+
+To use this script, please use 3.7+ interpreter. This script is work-directory
+agnostic. A quick executable command:
+
+    python3 tools/distrib/python/grpc_prefixed/generate.py
+"""
+
+import dataclasses
+import datetime
+import logging
+import os
+import shutil
+import subprocess
+import sys
+
+import jinja2
+
+WORK_PATH = os.path.realpath(os.path.dirname(__file__))
+LICENSE = os.path.join(WORK_PATH, '../../../../LICENSE')
+BUILD_PATH = os.path.join(WORK_PATH, 'build')
+DIST_PATH = os.path.join(WORK_PATH, 'dist')
+
+env = jinja2.Environment(
+    loader=jinja2.FileSystemLoader(os.path.join(WORK_PATH, 'templates')))
+
+LOGGER = logging.getLogger(__name__)
+POPEN_TIMEOUT_S = datetime.timedelta(minutes=1).total_seconds()
+
+
+@dataclasses.dataclass
+class PackageMeta:
+    """Meta-info of a PyPI package."""
+    name: str
+    name_long: str
+    destination_package: str
+    version: str = '1.0.0'
+
+
+def clean() -> None:
+    try:
+        shutil.rmtree(BUILD_PATH)
+    except FileNotFoundError:
+        pass
+
+    try:
+        shutil.rmtree(DIST_PATH)
+    except FileNotFoundError:
+        pass
+
+
+def generate_package(meta: PackageMeta) -> None:
+    # Makes package directory
+    package_path = os.path.join(BUILD_PATH, meta.name)
+    os.makedirs(package_path, exist_ok=True)
+
+    # Copy license
+    shutil.copyfile(LICENSE, os.path.join(package_path, 'LICENSE'))
+
+    # Generates source code
+    for template_name in env.list_templates():
+        template = env.get_template(template_name)
+        with open(
+                os.path.join(package_path,
+                             template_name.replace('.template', '')), 'w') as f:
+            f.write(template.render(dataclasses.asdict(meta)))
+
+    # Creates wheel
+    job = subprocess.Popen([
+        sys.executable,
+        os.path.join(package_path, 'setup.py'), 'sdist', '--dist-dir', DIST_PATH
+    ],
+                           cwd=package_path,
+                           stdout=subprocess.PIPE,
+                           stderr=subprocess.STDOUT)
+    outs, _ = job.communicate(timeout=POPEN_TIMEOUT_S)
+
+    # Logs result
+    if job.returncode != 0:
+        LOGGER.error('Wheel creation failed with %d', job.returncode)
+        LOGGER.error(outs)
+    else:
+        LOGGER.info('Package <%s> generated', meta.name)
+
+
+def main():
+    clean()
+
+    generate_package(
+        PackageMeta(name='grpc',
+                    name_long='gRPC Python',
+                    destination_package='grpcio'))
+
+    generate_package(
+        PackageMeta(name='grpc-status',
+                    name_long='gRPC Rich Error Status',
+                    destination_package='grpcio-status'))
+
+    generate_package(
+        PackageMeta(name='grpc-channelz',
+                    name_long='gRPC Channel Tracing',
+                    destination_package='grpcio-channelz'))
+
+    generate_package(
+        PackageMeta(name='grpc-tools',
+                    name_long='ProtoBuf Code Generator',
+                    destination_package='grpcio-tools'))
+
+    generate_package(
+        PackageMeta(name='grpc-reflection',
+                    name_long='gRPC Reflection',
+                    destination_package='grpcio-reflection'))
+
+    generate_package(
+        PackageMeta(name='grpc-testing',
+                    name_long='gRPC Testing Utility',
+                    destination_package='grpcio-testing'))
+
+    generate_package(
+        PackageMeta(name='grpc-health-checking',
+                    name_long='gRPC Health Checking',
+                    destination_package='grpcio-health-checking'))
+
+
+if __name__ == "__main__":
+    logging.basicConfig(level=logging.INFO)
+    main()
diff --git a/tools/distrib/python/grpc_prefixed/templates/MANIFEST.in.template b/tools/distrib/python/grpc_prefixed/templates/MANIFEST.in.template
new file mode 100644 (file)
index 0000000..5840309
--- /dev/null
@@ -0,0 +1,4 @@
+include setup.py
+include README.rst
+include LICENSE
+global-exclude *.pyc
diff --git a/tools/distrib/python/grpc_prefixed/templates/README.rst.template b/tools/distrib/python/grpc_prefixed/templates/README.rst.template
new file mode 100644 (file)
index 0000000..299ba9f
--- /dev/null
@@ -0,0 +1,2 @@
+The official package of {{ name_long }} is `{{ destination_package }} <https://pypi.org/project/{{ destination_package }}/>`_.
+Please download that package instead.
diff --git a/tools/distrib/python/grpc_prefixed/templates/setup.py.template b/tools/distrib/python/grpc_prefixed/templates/setup.py.template
new file mode 100644 (file)
index 0000000..2d62270
--- /dev/null
@@ -0,0 +1,45 @@
+# Copyright 2020 The gRPC Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Setup module for the {{ name_long }} package."""
+
+import sys
+
+import setuptools
+
+CLASSIFIERS = [
+    'Development Status :: 7 - Inactive',
+    'Programming Language :: Python',
+    'Programming Language :: Python :: 2',
+    'Programming Language :: Python :: 3',
+    'License :: OSI Approved :: Apache Software License',
+]
+
+
+HINT = 'Please install the official package with: pip install {{ destination_package }}'
+
+
+if 'sdist' not in sys.argv:
+    raise RuntimeError(HINT)
+
+
+setuptools.setup(
+    name='{{ name }}',
+    version='{{ version }}',
+    description=HINT,
+    author='The gRPC Authors',
+    author_email='grpc-io@googlegroups.com',
+    url='https://grpc.io',
+    license='Apache License 2.0',
+    classifiers=CLASSIFIERS
+)
index 2aeab68..38646ee 100644 (file)
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!!
 
-VERSION = '1.29.1'
+VERSION = '1.30.0'
index a557be5..1d2c12b 100644 (file)
@@ -20,4 +20,4 @@ PROTO_FILES=['google/protobuf/wrappers.proto', 'google/protobuf/type.proto', 'go
 CC_INCLUDE='third_party/protobuf/src'
 PROTO_INCLUDE='third_party/protobuf/src'
 
-PROTOBUF_SUBMODULE_VERSION="fe1790ca0df67173702f70d5646b82f48f412b99"
+PROTOBUF_SUBMODULE_VERSION="678da4f76eb9168c9965afc2149944a66cd48546"
index 4c9639b..cd4e722 100755 (executable)
@@ -26,6 +26,7 @@ DIRS=(
     'src'
     'test'
     'tools'
+    'setup.py'
 )
 
 VIRTUALENV=yapf_virtual_environment
index e94a928..a208ae0 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FROM alpine:3.7
+FROM alpine:3.9
 
 RUN apk add --update build-base linux-headers python python-dev py-pip
 
index 4d80a33..390ab45 100644 (file)
@@ -24,9 +24,7 @@ RUN yum install -y curl-devel expat-devel gettext-devel linux-headers openssl-de
 # Install Python build requirements
 RUN /opt/python/cp27-cp27m/bin/pip install --upgrade cython
 RUN /opt/python/cp27-cp27mu/bin/pip install --upgrade cython
-RUN /opt/python/cp34-cp34m/bin/pip install --upgrade cython
 RUN /opt/python/cp35-cp35m/bin/pip install --upgrade cython
 RUN /opt/python/cp36-cp36m/bin/pip install --upgrade cython
 RUN /opt/python/cp37-cp37m/bin/pip install --upgrade cython
-RUN /opt/python/cp37-cp37m/bin/pip install --upgrade cython
 RUN /opt/python/cp38-cp38/bin/pip install --upgrade cython
index 324f64f..6e5e433 100644 (file)
@@ -24,9 +24,7 @@ RUN yum install -y curl-devel expat-devel gettext-devel linux-headers openssl-de
 # Install Python build requirements
 RUN /opt/python/cp27-cp27m/bin/pip install --upgrade cython
 RUN /opt/python/cp27-cp27mu/bin/pip install --upgrade cython
-RUN /opt/python/cp34-cp34m/bin/pip install --upgrade cython
 RUN /opt/python/cp35-cp35m/bin/pip install --upgrade cython
 RUN /opt/python/cp36-cp36m/bin/pip install --upgrade cython
 RUN /opt/python/cp37-cp37m/bin/pip install --upgrade cython
-RUN /opt/python/cp37-cp37m/bin/pip install --upgrade cython
 RUN /opt/python/cp38-cp38/bin/pip install --upgrade cython
index 20e3294..93c4e6d 100644 (file)
@@ -29,9 +29,10 @@ ENV CLANG_TIDY=clang-tidy-6.0
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index 917d8a4..39d26d4 100644 (file)
@@ -57,9 +57,10 @@ RUN apt-get update && apt-get install -y time && apt-get clean
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index 917d8a4..39d26d4 100644 (file)
@@ -57,9 +57,10 @@ RUN apt-get update && apt-get install -y time && apt-get clean
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index d48dfb3..477618e 100644 (file)
@@ -58,9 +58,10 @@ RUN apt-get update && apt-get install -y time && apt-get clean
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index 09b72d0..78f6a72 100644 (file)
@@ -25,9 +25,10 @@ RUN ln -s /usr/local/go/bin/go /usr/local/bin
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index ee37a0b..06787bc 100644 (file)
@@ -25,9 +25,10 @@ RUN ln -s /usr/local/go/bin/go /usr/local/bin
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index 95b8b23..2467c1e 100644 (file)
@@ -25,9 +25,10 @@ RUN ln -s /usr/local/go/bin/go /usr/local/bin
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index 09ab216..e8384dd 100644 (file)
@@ -25,9 +25,10 @@ RUN ln -s /usr/local/go/bin/go /usr/local/bin
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index f04dc08..d0232d6 100644 (file)
@@ -25,9 +25,10 @@ RUN ln -s /usr/local/go/bin/go /usr/local/bin
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index 5ef618e..06f2d12 100644 (file)
@@ -22,7 +22,9 @@ cp -r /var/local/jenkins/grpc-java /tmp/grpc-java
 cp -r /var/local/jenkins/service_account $HOME || true
 
 pushd /tmp/grpc-java
-./gradlew --no-daemon :grpc-interop-testing:installDist -PskipCodegen=true -PskipAndroid=true
+# make two attempts; downloads can fail. See https://github.com/grpc/grpc/issues/18892
+./gradlew --no-daemon :grpc-interop-testing:installDist -PskipCodegen=true -PskipAndroid=true || \
+    ./gradlew --no-daemon :grpc-interop-testing:installDist -PskipCodegen=true -PskipAndroid=true
 
 mkdir -p /var/local/git/grpc-java/
 cp -r --parents -t /var/local/git/grpc-java/ \
index 1007995..cc9e254 100644 (file)
@@ -58,9 +58,10 @@ RUN apt-get update && apt-get install -y time && apt-get clean
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index 8f9a7c3..bce6c12 100755 (executable)
@@ -40,9 +40,11 @@ cd src/php
 
 DONE=0
 for ((i = 0; i < 5; i++)); do
-  php -d extension=ext/grpc/modules/grpc.so /usr/local/bin/composer install && DONE=1
-  [[ "$DONE" == 1 ]] && break
+  php -d extension=ext/grpc/modules/grpc.so /usr/local/bin/composer install && DONE=1 && break
 done
-[[ "$DONE" != 1 ]] && echo "Failed to do composer install" && exit 1
 
-./bin/generate_proto_php.sh
+if [ "$DONE" != "1" ]
+then
+  echo "Failed to do composer install"
+  exit 1
+fi
index 7de1755..26a49be 100755 (executable)
@@ -40,9 +40,11 @@ cd src/php
 
 DONE=0
 for ((i = 0; i < 5; i++)); do
-  php -d extension=ext/grpc/modules/grpc.so /usr/local/bin/composer install && DONE=1
-  [[ "$DONE" == 1 ]] && break
+  php -d extension=ext/grpc/modules/grpc.so /usr/local/bin/composer install && DONE=1 && break
 done
-[[ "$DONE" != 1 ]] && echo "Failed to do composer install" && exit 1
 
-./bin/generate_proto_php.sh
+if [ "$DONE" != "1" ]
+then
+  echo "Failed to do composer install"
+  exit 1
+fi
index 3583d78..8793d5f 100644 (file)
@@ -49,14 +49,13 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 # Install Python 2.7
 RUN apt-get update && apt-get install -y python2.7 python-all-dev
 RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 # Add Debian 'buster' repository, we will need it for installing newer versions of python
 RUN echo 'deb http://ftp.de.debian.org/debian buster main' >> /etc/apt/sources.list
 RUN echo 'APT::Default-Release "stretch";' | tee -a /etc/apt/apt.conf.d/00local
index 3583d78..8793d5f 100644 (file)
@@ -49,14 +49,13 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 # Install Python 2.7
 RUN apt-get update && apt-get install -y python2.7 python-all-dev
 RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 # Add Debian 'buster' repository, we will need it for installing newer versions of python
 RUN echo 'deb http://ftp.de.debian.org/debian buster main' >> /etc/apt/sources.list
 RUN echo 'APT::Default-Release "stretch";' | tee -a /etc/apt/apt.conf.d/00local
index 4866c7d..b3becf1 100644 (file)
@@ -58,9 +58,10 @@ RUN apt-get update && apt-get install -y time && apt-get clean
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index 2e0841a..7d2068e 100755 (executable)
@@ -36,14 +36,15 @@ do
   # contents of the docker image always changes the SHA (e.g. using "ADD file" 
   # cmd in the dockerfile in not ok as contents of the added file will not be
   # reflected in the SHA).
-  DOCKER_IMAGE_NAME=$(basename $DOCKERFILE_DIR)_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ )
+  DOCKER_IMAGE_NAME=$(basename $DOCKERFILE_DIR)
+  DOCKER_IMAGE_TAG=$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ )
 
   # skip the image if it already exists in the repo 
-  curl --silent -f -lSL https://registry.hub.docker.com/v2/repositories/${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME}/tags/latest > /dev/null \
+  curl --silent -f -lSL https://registry.hub.docker.com/v2/repositories/${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME}/tags/${DOCKER_IMAGE_TAG} > /dev/null \
       && continue
 
-  docker build -t ${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME} ${DOCKERFILE_DIR}
-      
+  docker build -t ${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG} ${DOCKERFILE_DIR}
+
   # "docker login" needs to be run in advance
-  docker push ${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME}
+  docker push ${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG}
 done
index 229835a..e41f1ab 100644 (file)
@@ -41,9 +41,10 @@ RUN apt-get update && apt-get -y install \
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
index cc6ed85..684c26f 100644 (file)
@@ -49,10 +49,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -61,13 +57,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #================
 # C# dependencies
 
index 08dc872..c75945f 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FROM alpine:3.5
+FROM alpine:3.9
 
 # Install Git and basic packages.
 RUN apk update && apk add \
index f5bacb8..0c4324f 100644 (file)
@@ -49,10 +49,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -61,13 +57,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #=================
 # C++ dependencies
 RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
index 8cb6af1..00f51cf 100644 (file)
@@ -50,10 +50,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -62,13 +58,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #=================
 # C++ dependencies
 RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
index 104b669..ce5e074 100644 (file)
@@ -50,10 +50,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -62,13 +58,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #=================
 # C++ dependencies
 RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
index d05b350..08ed1da 100644 (file)
@@ -51,10 +51,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -63,13 +59,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #=================
 # C++ dependencies (purposely excluding Clang because it's part of the base image)
 RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev && apt-get clean
index a3659d3..08cff8d 100644 (file)
@@ -49,10 +49,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -61,13 +57,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #=================
 # C++ dependencies
 RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
index 37ed9b8..380bc7a 100644 (file)
@@ -49,10 +49,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -61,13 +57,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #=================
 # C++ dependencies
 RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
index d007738..724e41b 100644 (file)
@@ -49,10 +49,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -61,13 +57,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #=================
 # C++ dependencies
 RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
index 9394fc2..9f9f247 100644 (file)
@@ -50,10 +50,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -62,13 +58,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #=================
 # C++ dependencies
 RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
index 7cbe7b0..30c278c 100644 (file)
@@ -50,10 +50,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 
 # Install Electron apt dependencies
 RUN apt-get update && apt-get install -y \
@@ -73,13 +69,17 @@ RUN apt-get update && apt-get install -y \
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #==================
 # Node dependencies
 
diff --git a/tools/dockerfile/test/php73_zts_stretch_x64/Dockerfile b/tools/dockerfile/test/php73_zts_stretch_x64/Dockerfile
new file mode 100644 (file)
index 0000000..0113d68
--- /dev/null
@@ -0,0 +1,45 @@
+# Copyright 2016 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FROM php:7.3-zts-stretch
+
+RUN apt-get -qq update && apt-get -qq install -y \
+  autoconf automake build-essential git libtool curl \
+  zlib1g-dev \
+  python-all-dev \
+  python3-all-dev \
+  python-setuptools
+
+WORKDIR /tmp
+
+RUN git clone https://github.com/krakjoe/pthreads
+
+RUN cd pthreads && \
+  phpize && \
+  ./configure && \
+  make && \
+  make install
+
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
+RUN pip install --upgrade pip==19.3.1
+RUN pip install virtualenv==16.7.9
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
+
+RUN curl -sS https://getcomposer.org/installer | php
+RUN mv composer.phar /usr/local/bin/composer
+
+RUN mkdir /var/local/jenkins
+
+# Define the default command.
+CMD ["bash"]
index 55ea982..60fec1d 100644 (file)
@@ -61,10 +61,6 @@ RUN cd /var/local/git/php-src \
   && make \
   && make install
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -73,13 +69,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #=================     
 # PHP Test dependencies        
 
index 94023bb..5a19119 100644 (file)
@@ -50,10 +50,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -62,13 +58,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #=================
 # PHP dependencies
 
index 2356813..1b806ab 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FROM alpine:3.3
+FROM alpine:3.9
 
 # Install Git and basic packages.
 RUN apk update && apk add \
index 0bbc11a..876c5dc 100644 (file)
@@ -49,14 +49,13 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 # Install Python 2.7
 RUN apt-get update && apt-get install -y python2.7 python-all-dev
 RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 # Add Debian 'buster' repository, we will need it for installing newer versions of python
 RUN echo 'deb http://ftp.de.debian.org/debian buster main' >> /etc/apt/sources.list
 RUN echo 'APT::Default-Release "stretch";' | tee -a /etc/apt/apt.conf.d/00local
index bfedf43..5e4ca94 100644 (file)
@@ -49,14 +49,13 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 # Install Python 2.7
 RUN apt-get update && apt-get install -y python2.7 python-all-dev
 RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 # Add Debian 'buster' repository, we will need it for installing newer versions of python
 RUN echo 'deb http://ftp.de.debian.org/debian buster main' >> /etc/apt/sources.list
 RUN echo 'APT::Default-Release "stretch";' | tee -a /etc/apt/apt.conf.d/00local
index 3d47584..bc92bd6 100644 (file)
@@ -49,14 +49,13 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 # Install Python 2.7
 RUN apt-get update && apt-get install -y python2.7 python-all-dev
 RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 # Add Debian 'buster' repository, we will need it for installing newer versions of python
 RUN echo 'deb http://ftp.de.debian.org/debian buster main' >> /etc/apt/sources.list
 RUN echo 'APT::Default-Release "stretch";' | tee -a /etc/apt/apt.conf.d/00local
index 6745055..00edc45 100644 (file)
@@ -49,14 +49,13 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 # Install Python 2.7
 RUN apt-get update && apt-get install -y python2.7 python-all-dev
 RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 # Add Debian 'buster' repository, we will need it for installing newer versions of python
 RUN echo 'deb http://ftp.de.debian.org/debian buster main' >> /etc/apt/sources.list
 RUN echo 'APT::Default-Release "stretch";' | tee -a /etc/apt/apt.conf.d/00local
index 8d780f0..3202eb0 100644 (file)
@@ -49,14 +49,13 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 # Install Python 2.7
 RUN apt-get update && apt-get install -y python2.7 python-all-dev
 RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 # Add Debian 'buster' repository, we will need it for installing newer versions of python
 RUN echo 'deb http://ftp.de.debian.org/debian buster main' >> /etc/apt/sources.list
 RUN echo 'APT::Default-Release "stretch";' | tee -a /etc/apt/apt.conf.d/00local
index 713fd6f..9cde174 100644 (file)
@@ -49,14 +49,13 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 # Install Python 2.7
 RUN apt-get update && apt-get install -y python2.7 python-all-dev
 RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 # Add Debian 'buster' repository, we will need it for installing newer versions of python
 RUN echo 'deb http://ftp.de.debian.org/debian buster main' >> /etc/apt/sources.list
 RUN echo 'APT::Default-Release "stretch";' | tee -a /etc/apt/apt.conf.d/00local
index bfee944..12dc385 100644 (file)
@@ -50,10 +50,6 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 #====================
 # Python dependencies
 
@@ -62,13 +58,17 @@ RUN pip install --upgrade google-api-python-client oauth2client
 RUN apt-get update && apt-get install -y \
     python-all-dev \
     python3-all-dev \
-    python-pip
+    python-setuptools
 
 # Install Python packages from PyPI
+RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 RUN pip install --upgrade pip==19.3.1
 RUN pip install virtualenv==16.7.9
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 #==================
 # Ruby dependencies
 
index 3666b26..c5dd7d6 100644 (file)
@@ -49,14 +49,13 @@ RUN apt-get update && apt-get install -y \
 # Build profiling
 RUN apt-get update && apt-get install -y time && apt-get clean
 
-# Google Cloud platform API libraries
-RUN apt-get update && apt-get install -y python-pip && apt-get clean
-RUN pip install --upgrade google-api-python-client oauth2client
-
 # Install Python 2.7
 RUN apt-get update && apt-get install -y python2.7 python-all-dev
 RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
 
+# Google Cloud platform API libraries
+RUN pip install --upgrade google-api-python-client oauth2client
+
 
 RUN mkdir /var/local/jenkins
 
index 9bfdf4b..8abc33a 100644 (file)
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC C++"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.29.1
+PROJECT_NUMBER         = 1.30.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
index f571697..1c71110 100644 (file)
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC C++"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.29.1
+PROJECT_NUMBER         = 1.30.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -1161,6 +1161,9 @@ src/core/ext/filters/client_channel/server_address.cc \
 src/core/ext/filters/client_channel/server_address.h \
 src/core/ext/filters/client_channel/service_config.cc \
 src/core/ext/filters/client_channel/service_config.h \
+src/core/ext/filters/client_channel/service_config_call_data.h \
+src/core/ext/filters/client_channel/service_config_parser.cc \
+src/core/ext/filters/client_channel/service_config_parser.h \
 src/core/ext/filters/client_channel/subchannel.cc \
 src/core/ext/filters/client_channel/subchannel.h \
 src/core/ext/filters/client_channel/subchannel_interface.h \
@@ -1266,6 +1269,12 @@ src/core/ext/upb-generated/envoy/annotations/resource.upb.c \
 src/core/ext/upb-generated/envoy/annotations/resource.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/cds.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/cds.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c \
@@ -1278,10 +1287,14 @@ src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c \
@@ -1290,6 +1303,8 @@ src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/eds.upb.c \
@@ -1330,6 +1345,8 @@ src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v
 src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h \
 src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c \
 src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h \
+src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c \
+src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h \
 src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c \
 src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h \
 src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c \
@@ -1386,6 +1403,8 @@ src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
 src/core/ext/upb-generated/udpa/annotations/migrate.upb.h \
 src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \
 src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h \
+src/core/ext/upb-generated/udpa/annotations/status.upb.c \
+src/core/ext/upb-generated/udpa/annotations/status.upb.h \
 src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
 src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \
 src/core/ext/upb-generated/validate/validate.upb.c \
@@ -1495,17 +1514,14 @@ src/core/lib/gprpp/global_config_env.h \
 src/core/lib/gprpp/global_config_generic.h \
 src/core/lib/gprpp/host_port.cc \
 src/core/lib/gprpp/host_port.h \
-src/core/lib/gprpp/inlined_vector.h \
 src/core/lib/gprpp/manual_constructor.h \
 src/core/lib/gprpp/map.h \
 src/core/lib/gprpp/memory.h \
 src/core/lib/gprpp/mpscq.cc \
 src/core/lib/gprpp/mpscq.h \
-src/core/lib/gprpp/optional.h \
 src/core/lib/gprpp/orphanable.h \
 src/core/lib/gprpp/ref_counted.h \
 src/core/lib/gprpp/ref_counted_ptr.h \
-src/core/lib/gprpp/string_view.h \
 src/core/lib/gprpp/sync.h \
 src/core/lib/gprpp/thd.h \
 src/core/lib/gprpp/thd_posix.cc \
index fd50700..b026c8b 100644 (file)
@@ -961,6 +961,9 @@ src/core/ext/filters/client_channel/server_address.cc \
 src/core/ext/filters/client_channel/server_address.h \
 src/core/ext/filters/client_channel/service_config.cc \
 src/core/ext/filters/client_channel/service_config.h \
+src/core/ext/filters/client_channel/service_config_call_data.h \
+src/core/ext/filters/client_channel/service_config_parser.cc \
+src/core/ext/filters/client_channel/service_config_parser.h \
 src/core/ext/filters/client_channel/subchannel.cc \
 src/core/ext/filters/client_channel/subchannel.h \
 src/core/ext/filters/client_channel/subchannel_interface.h \
@@ -1073,6 +1076,12 @@ src/core/ext/upb-generated/envoy/annotations/resource.upb.c \
 src/core/ext/upb-generated/envoy/annotations/resource.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/cds.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/cds.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c \
@@ -1085,10 +1094,14 @@ src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c \
@@ -1097,6 +1110,8 @@ src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h \
+src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c \
+src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c \
 src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h \
 src/core/ext/upb-generated/envoy/api/v2/eds.upb.c \
@@ -1137,6 +1152,8 @@ src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v
 src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h \
 src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c \
 src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h \
+src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c \
+src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h \
 src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c \
 src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h \
 src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c \
@@ -1193,6 +1210,8 @@ src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
 src/core/ext/upb-generated/udpa/annotations/migrate.upb.h \
 src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \
 src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h \
+src/core/ext/upb-generated/udpa/annotations/status.upb.c \
+src/core/ext/upb-generated/udpa/annotations/status.upb.h \
 src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
 src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \
 src/core/ext/upb-generated/validate/validate.upb.c \
@@ -1306,17 +1325,14 @@ src/core/lib/gprpp/global_config_env.h \
 src/core/lib/gprpp/global_config_generic.h \
 src/core/lib/gprpp/host_port.cc \
 src/core/lib/gprpp/host_port.h \
-src/core/lib/gprpp/inlined_vector.h \
 src/core/lib/gprpp/manual_constructor.h \
 src/core/lib/gprpp/map.h \
 src/core/lib/gprpp/memory.h \
 src/core/lib/gprpp/mpscq.cc \
 src/core/lib/gprpp/mpscq.h \
-src/core/lib/gprpp/optional.h \
 src/core/lib/gprpp/orphanable.h \
 src/core/lib/gprpp/ref_counted.h \
 src/core/lib/gprpp/ref_counted_ptr.h \
-src/core/lib/gprpp/string_view.h \
 src/core/lib/gprpp/sync.h \
 src/core/lib/gprpp/thd.h \
 src/core/lib/gprpp/thd_posix.cc \
index 6a4a642..04bd314 100644 (file)
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC Objective-C"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.29.1
+PROJECT_NUMBER         = 1.30.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
index ba80a36..0b63b92 100644 (file)
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC Objective-C"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.29.1
+PROJECT_NUMBER         = 1.30.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
diff --git a/tools/gce/create_win2019_container_vm.sh b/tools/gce/create_win2019_container_vm.sh
new file mode 100755 (executable)
index 0000000..02db428
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/bash
+# Copyright 2017 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Creates a worker for debugging/experiments.
+# The worker will have all the prerequisites that are installed on kokoro
+# windows workers.
+
+set -ex
+
+cd "$(dirname "$0")"
+
+CLOUD_PROJECT=grpc-testing
+ZONE=us-central1-b
+
+if [ "$1" != "" ]
+then
+  INSTANCE_NAME="$1"
+else
+  INSTANCE_NAME="${USER}-win2019-for-containers-test1"
+fi
+
+MACHINE_TYPE=e2-standard-8
+
+# The image version might need updating.
+gcloud compute instances create "$INSTANCE_NAME" \
+    --project="$CLOUD_PROJECT" \
+    --zone "$ZONE" \
+    --machine-type "$MACHINE_TYPE" \
+    --boot-disk-size=400GB \
+    --boot-disk-type pd-ssd \
+    --image-project=windows-cloud \
+    --image-family=windows-2019-for-containers
+
+# or use --image-family=windows-2019-core-for-containers
index 755cad8..e68a89a 100644 (file)
@@ -36,11 +36,16 @@ fi
 
 if [ "${PREPARE_BUILD_INSTALL_DEPS_RUBY}" == "true" ]
 then
-  set +ex  # rvm script is very verbose and exits with errorcode
-  # Advice from https://github.com/Homebrew/homebrew-cask/issues/8629#issuecomment-68641176
-  brew update && brew upgrade brew-cask && brew cleanup && brew cask cleanup
-  set -e  # rvm commands are very verbose
+  brew update
+  # special case fix for https://github.com/grpc/grpc/issues/23027
+  rm -f /usr/local/bin/gpg
+  rm -f /usr/local/bin/gpgconf
+  rm -f /usr/local/bin/gpgsm
+  # end https://github.com/grpc/grpc/issues/23027
+  brew cleanup
+  set +ex
   source $HOME/.rvm/scripts/rvm
+  set -ex
   for RUBY_VERSION in 2.5.0 2.7.0; do
     rvm --debug requirements "ruby-${RUBY_VERSION}"
     time rvm install "$RUBY_VERSION"
@@ -51,7 +56,6 @@ then
   time gem install cocoapods --version 1.3.1 --no-document
   rvm osx-ssl-certs status all
   rvm osx-ssl-certs update all
-  set -ex
 fi
 
 if [ "${PREPARE_BUILD_INSTALL_DEPS_OBJC}" == "true" ]
index a9a74ee..0fe64eb 100755 (executable)
@@ -48,7 +48,7 @@ touch "$TOOLS_DIR"/src/proto/grpc/testing/__init__.py
 
 bazel build //src/python/grpcio_tests/tests_py3_only/interop:xds_interop_client
 
-GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,cds_lb,eds_lb,priority_lb,weighted_target_lb,lrs_lb "$PYTHON" \
+GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,xds_routing_lb,cds_lb,eds_lb,priority_lb,weighted_target_lb,lrs_lb "$PYTHON" \
   tools/run_tests/run_xds_tests.py \
     --test_case=all \
     --project_id=grpc-testing \
@@ -56,4 +56,4 @@ GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,cds_lb,eds_lb,priority_l
     --path_to_server_binary=/java_server/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/xds-test-server \
     --gcp_suffix=$(date '+%s') \
     --verbose \
-    --client_cmd='bazel run //src/python/grpcio_tests/tests_py3_only/interop:xds_interop_client -- --server=xds-experimental:///{server_uri} --stats_port={stats_port} --qps={qps} --verbose'
+    --client_cmd='bazel run //src/python/grpcio_tests/tests_py3_only/interop:xds_interop_client -- --server=xds:///{server_uri} --stats_port={stats_port} --qps={qps} --verbose'
index 943ba2b..eee8876 100755 (executable)
@@ -48,7 +48,7 @@ touch "$TOOLS_DIR"/src/proto/grpc/testing/__init__.py
 
 bazel build test/cpp/interop:xds_interop_client
 
-GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,cds_lb,eds_lb,priority_lb,weighted_target_lb,lrs_lb "$PYTHON" \
+GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,xds_routing_lb,cds_lb,eds_lb,priority_lb,weighted_target_lb,lrs_lb "$PYTHON" \
   tools/run_tests/run_xds_tests.py \
     --test_case=all \
     --project_id=grpc-testing \
@@ -56,4 +56,4 @@ GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,cds_lb,eds_lb,priority_l
     --path_to_server_binary=/java_server/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/xds-test-server \
     --gcp_suffix=$(date '+%s') \
     --verbose \
-    --client_cmd='bazel-bin/test/cpp/interop/xds_interop_client --server=xds-experimental:///{server_uri} --stats_port={stats_port} --qps={qps}'
+    --client_cmd='bazel-bin/test/cpp/interop/xds_interop_client --server=xds:///{server_uri} --stats_port={stats_port} --qps={qps} {fail_on_failed_rpc}'
diff --git a/tools/internal_ci/linux/grpc_xds_csharp.cfg b/tools/internal_ci/linux/grpc_xds_csharp.cfg
new file mode 100644 (file)
index 0000000..579cd47
--- /dev/null
@@ -0,0 +1,25 @@
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_xds_csharp.sh"
+timeout_mins: 90
+action {
+  define_artifacts {
+    regex: "**/*sponge_log.*"
+    regex: "github/grpc/reports/**"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_xds_csharp.sh b/tools/internal_ci/linux/grpc_xds_csharp.sh
new file mode 100755 (executable)
index 0000000..26bb7e3
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+# Copyright 2017 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+
+export DOCKERFILE_DIR=tools/dockerfile/test/csharp_stretch_x64
+export DOCKER_RUN_SCRIPT=tools/internal_ci/linux/grpc_xds_csharp_test_in_docker.sh
+export OUTPUT_DIR=reports
+exec tools/run_tests/dockerize/build_and_run_docker.sh
diff --git a/tools/internal_ci/linux/grpc_xds_csharp_test_in_docker.sh b/tools/internal_ci/linux/grpc_xds_csharp_test_in_docker.sh
new file mode 100755 (executable)
index 0000000..85ddb2c
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -ex -o igncr || set -ex
+
+mkdir -p /var/local/git
+git clone /var/local/jenkins/grpc /var/local/git/grpc
+(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \
+&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \
+${name}')
+cd /var/local/git/grpc
+
+VIRTUAL_ENV=$(mktemp -d)
+virtualenv "$VIRTUAL_ENV"
+PYTHON="$VIRTUAL_ENV"/bin/python
+"$PYTHON" -m pip install --upgrade pip
+"$PYTHON" -m pip install --upgrade grpcio grpcio-tools google-api-python-client google-auth-httplib2 oauth2client
+
+# Prepare generated Python code.
+TOOLS_DIR=tools/run_tests
+PROTO_SOURCE_DIR=src/proto/grpc/testing
+PROTO_DEST_DIR="$TOOLS_DIR"/"$PROTO_SOURCE_DIR"
+mkdir -p "$PROTO_DEST_DIR"
+touch "$TOOLS_DIR"/src/__init__.py
+touch "$TOOLS_DIR"/src/proto/__init__.py
+touch "$TOOLS_DIR"/src/proto/grpc/__init__.py
+touch "$TOOLS_DIR"/src/proto/grpc/testing/__init__.py
+
+"$PYTHON" -m grpc_tools.protoc \
+    --proto_path=. \
+    --python_out="$TOOLS_DIR" \
+    --grpc_python_out="$TOOLS_DIR" \
+    "$PROTO_SOURCE_DIR"/test.proto \
+    "$PROTO_SOURCE_DIR"/messages.proto \
+    "$PROTO_SOURCE_DIR"/empty.proto
+
+python tools/run_tests/run_tests.py -l csharp -c opt --build_only
+
+GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,xds_routing_lb,cds_lb,eds_lb,priority_lb,weighted_target_lb,lrs_lb "$PYTHON" \
+  tools/run_tests/run_xds_tests.py \
+    --test_case=all \
+    --project_id=grpc-testing \
+    --source_image=projects/grpc-testing/global/images/xds-test-server \
+    --path_to_server_binary=/java_server/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/xds-test-server \
+    --gcp_suffix=$(date '+%s') \
+    --verbose \
+    --client_cmd='dotnet exec src/csharp/Grpc.IntegrationTesting.XdsClient/bin/Release/netcoreapp2.1/Grpc.IntegrationTesting.XdsClient.dll -- --server=xds:///{server_uri} --stats_port={stats_port} --qps={qps}'
diff --git a/tools/internal_ci/linux/grpc_xds_php.cfg b/tools/internal_ci/linux/grpc_xds_php.cfg
new file mode 100644 (file)
index 0000000..f7a12b4
--- /dev/null
@@ -0,0 +1,25 @@
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_xds_php.sh"
+timeout_mins: 180
+action {
+  define_artifacts {
+    regex: "**/*sponge_log.*"
+    regex: "github/grpc/reports/**"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_xds_php.sh b/tools/internal_ci/linux/grpc_xds_php.sh
new file mode 100755 (executable)
index 0000000..8b64343
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+# Copyright 2017 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+
+export DOCKERFILE_DIR=tools/dockerfile/test/php73_zts_stretch_x64
+export DOCKER_RUN_SCRIPT=tools/internal_ci/linux/grpc_xds_php_test_in_docker.sh
+export OUTPUT_DIR=reports
+exec tools/run_tests/dockerize/build_and_run_docker.sh
diff --git a/tools/internal_ci/linux/grpc_xds_php_test_in_docker.sh b/tools/internal_ci/linux/grpc_xds_php_test_in_docker.sh
new file mode 100755 (executable)
index 0000000..0d1deff
--- /dev/null
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -ex -o igncr || set -ex
+
+mkdir -p /var/local/git
+git clone /var/local/jenkins/grpc /var/local/git/grpc
+(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \
+&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \
+${name}')
+cd /var/local/git/grpc
+
+VIRTUAL_ENV=$(mktemp -d)
+virtualenv "$VIRTUAL_ENV"
+PYTHON="$VIRTUAL_ENV"/bin/python
+"$PYTHON" -m pip install --upgrade pip
+"$PYTHON" -m pip install --upgrade grpcio-tools google-api-python-client google-auth-httplib2 oauth2client
+
+# Prepare generated Python code.
+TOOLS_DIR=tools/run_tests
+PROTO_SOURCE_DIR=src/proto/grpc/testing
+PROTO_DEST_DIR="$TOOLS_DIR"/"$PROTO_SOURCE_DIR"
+mkdir -p "$PROTO_DEST_DIR"
+touch "$TOOLS_DIR"/src/__init__.py
+touch "$TOOLS_DIR"/src/proto/__init__.py
+touch "$TOOLS_DIR"/src/proto/grpc/__init__.py
+touch "$TOOLS_DIR"/src/proto/grpc/testing/__init__.py
+
+"$PYTHON" -m grpc_tools.protoc \
+    --proto_path=. \
+    --python_out="$TOOLS_DIR" \
+    --grpc_python_out="$TOOLS_DIR" \
+    "$PROTO_SOURCE_DIR"/test.proto \
+    "$PROTO_SOURCE_DIR"/messages.proto \
+    "$PROTO_SOURCE_DIR"/empty.proto
+
+# Generate and compile the PHP extension.
+(pear package && \
+  find . -name grpc-*.tgz | xargs -I{} pecl install {})
+
+# Prepare generated PHP code.
+export CC=/usr/bin/gcc
+./tools/bazel build @com_google_protobuf//:protoc
+./tools/bazel build src/compiler:grpc_php_plugin
+(cd src/php && \
+  composer install && \
+  ./bin/generate_proto_php.sh)
+
+GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,xds_routing_lb,cds_lb,eds_lb,priority_lb,weighted_target_lb,lrs_lb "$PYTHON" \
+  tools/run_tests/run_xds_tests.py \
+  --test_case=all \
+  --project_id=grpc-testing \
+  --source_image=projects/grpc-testing/global/images/xds-test-server \
+  --path_to_server_binary=/java_server/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/xds-test-server \
+  --gcp_suffix=$(date '+%s') \
+  --verbose \
+  --client_cmd='php -d extension=grpc.so -d extension=pthreads.so src/php/tests/interop/xds_client.php --server=xds:///{server_uri} --stats_port={stats_port} --qps={qps}'
diff --git a/tools/internal_ci/linux/grpc_xds_ruby.cfg b/tools/internal_ci/linux/grpc_xds_ruby.cfg
new file mode 100644 (file)
index 0000000..87401ba
--- /dev/null
@@ -0,0 +1,25 @@
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_xds_ruby.sh"
+timeout_mins: 180
+action {
+  define_artifacts {
+    regex: "**/*sponge_log.*"
+    regex: "github/grpc/reports/**"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_xds_ruby.sh b/tools/internal_ci/linux/grpc_xds_ruby.sh
new file mode 100644 (file)
index 0000000..1b22193
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+# Copyright 2017 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+
+export DOCKERFILE_DIR=tools/dockerfile/test/ruby_jessie_x64
+export DOCKER_RUN_SCRIPT=tools/internal_ci/linux/grpc_xds_ruby_test_in_docker.sh
+export OUTPUT_DIR=reports
+exec tools/run_tests/dockerize/build_and_run_docker.sh
diff --git a/tools/internal_ci/linux/grpc_xds_ruby_test_in_docker.sh b/tools/internal_ci/linux/grpc_xds_ruby_test_in_docker.sh
new file mode 100644 (file)
index 0000000..c88f6e3
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+# Copyright 2020 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -ex -o igncr || set -ex
+
+mkdir -p /var/local/git
+git clone /var/local/jenkins/grpc /var/local/git/grpc
+(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \
+&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \
+${name}')
+cd /var/local/git/grpc
+
+VIRTUAL_ENV=$(mktemp -d)
+virtualenv "$VIRTUAL_ENV"
+PYTHON="$VIRTUAL_ENV"/bin/python
+"$PYTHON" -m pip install --upgrade pip
+"$PYTHON" -m pip install --upgrade grpcio-tools google-api-python-client google-auth-httplib2 oauth2client
+
+# Prepare generated Python code.
+TOOLS_DIR=tools/run_tests
+PROTO_SOURCE_DIR=src/proto/grpc/testing
+PROTO_DEST_DIR="$TOOLS_DIR"/"$PROTO_SOURCE_DIR"
+mkdir -p "$PROTO_DEST_DIR"
+touch "$TOOLS_DIR"/src/__init__.py
+touch "$TOOLS_DIR"/src/proto/__init__.py
+touch "$TOOLS_DIR"/src/proto/grpc/__init__.py
+touch "$TOOLS_DIR"/src/proto/grpc/testing/__init__.py
+
+"$PYTHON" -m grpc_tools.protoc \
+    --proto_path=. \
+    --python_out="$TOOLS_DIR" \
+    --grpc_python_out="$TOOLS_DIR" \
+    "$PROTO_SOURCE_DIR"/test.proto \
+    "$PROTO_SOURCE_DIR"/messages.proto \
+    "$PROTO_SOURCE_DIR"/empty.proto
+
+(cd src/ruby && bundle && rake compile)
+
+GRPC_VERBOSITY=debug GRPC_TRACE=xds_client,xds_resolver,xds_routing_lb,cds_lb,eds_lb,priority_lb,weighted_target_lb,lrs_lb "$PYTHON" \
+  tools/run_tests/run_xds_tests.py \
+    --test_case=all \
+    --project_id=grpc-testing \
+    --source_image=projects/grpc-testing/global/images/xds-test-server \
+    --path_to_server_binary=/java_server/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/xds-test-server \
+    --gcp_suffix=$(date '+%s') \
+    --verbose \
+    --client_cmd='ruby src/ruby/pb/test/xds_client.rb --server=xds:///{server_uri} --stats_port={stats_port} --qps={qps}'
index 96e2b33..b2b77be 100644 (file)
@@ -155,6 +155,7 @@ LANG_RELEASE_MATRIX = {
             ('v1.26.0', ReleaseInfo(runtimes=['go1.11'])),
             ('v1.27.1', ReleaseInfo(runtimes=['go1.11'])),
             ('v1.28.0', ReleaseInfo(runtimes=['go1.11'])),
+            ('v1.29.0', ReleaseInfo(runtimes=['go1.11'])),
         ]),
     'java':
         OrderedDict([
@@ -214,7 +215,10 @@ LANG_RELEASE_MATRIX = {
             ('v1.23.0', ReleaseInfo()),
             ('v1.24.0', ReleaseInfo()),
             ('v1.25.0', ReleaseInfo()),
-            ('v1.26.0', ReleaseInfo()),
+            ('v1.26.1', ReleaseInfo()),
+            ('v1.27.2', ReleaseInfo()),
+            ('v1.28.1', ReleaseInfo()),
+            ('v1.29.0', ReleaseInfo()),
         ]),
     'python':
         OrderedDict([
index 4f69794..c260670 100644 (file)
@@ -1,9 +1,5 @@
 startup --host_jvm_args=-Dbazel.DigestFunction=SHA256
 
-# TODO(jtattermusch): Currently building with --compilation_mode=dbg is broken on Windows RBE
-# so we need to explicitly override it to use fastbuild.
-build:windows_dbg --compilation_mode=fastbuild
-
 build --remote_cache=grpcs://remotebuildexecution.googleapis.com
 build --remote_executor=grpcs://remotebuildexecution.googleapis.com
 
@@ -26,7 +22,7 @@ build --strategy=Closure=remote
 build --genrule_strategy=remote
 build --remote_timeout=7200  # very large value to avoid problems like https://github.com/grpc/grpc/issues/20777
 
-build --remote_instance_name=projects/grpc-testing/instances/grpc-windows-rbe-test
+build --remote_instance_name=projects/grpc-testing/instances/default_instance
 
 build --verbose_failures=true
 
index a5ef428..7e9bc77 100755 (executable)
@@ -33,7 +33,7 @@ cd -
 # $@ - Extra args to pass to docker run
 
 # Use image name based on Dockerfile location checksum
-DOCKER_IMAGE_NAME=$(basename "$DOCKERFILE_DIR")_$(sha1sum "$DOCKERFILE_DIR/Dockerfile" | cut -f1 -d\ )
+DOCKER_IMAGE_NAME=$(basename "$DOCKERFILE_DIR"):$(sha1sum "$DOCKERFILE_DIR/Dockerfile" | cut -f1 -d\ )
 
 # Pull the base image to force an update
 if [ "$DOCKER_BASE_IMAGE" != "" ]
index aeaae3f..4a7908b 100755 (executable)
@@ -30,7 +30,7 @@ cd -
 # DOCKERHUB_ORGANIZATION - If set, pull a prebuilt image from given dockerhub org.
 
 # Use image name based on Dockerfile location checksum
-DOCKER_IMAGE_NAME=$(basename "$DOCKERFILE_DIR")_$(sha1sum "$DOCKERFILE_DIR/Dockerfile" | cut -f1 -d\ )
+DOCKER_IMAGE_NAME=$(basename "$DOCKERFILE_DIR"):$(sha1sum "$DOCKERFILE_DIR/Dockerfile" | cut -f1 -d\ )
 
 if [ "$DOCKERHUB_ORGANIZATION" != "" ]
 then
index 9516c5a..5b5bfb6 100755 (executable)
@@ -84,9 +84,9 @@ fi
 # on OSX use md5 instead of sha1sum
 if command -v sha1sum > /dev/null;
 then
-  BASE_IMAGE=${BASE_NAME}_$(sha1sum "tools/dockerfile/interoptest/$BASE_NAME/Dockerfile" | cut -f1 -d\ )
+  BASE_IMAGE=${BASE_NAME}:$(sha1sum "tools/dockerfile/interoptest/$BASE_NAME/Dockerfile" | cut -f1 -d\ )
 else
-  BASE_IMAGE=${BASE_NAME}_$(md5 -r "tools/dockerfile/interoptest/$BASE_NAME/Dockerfile" | cut -f1 -d\ )
+  BASE_IMAGE=${BASE_NAME}:$(md5 -r "tools/dockerfile/interoptest/$BASE_NAME/Dockerfile" | cut -f1 -d\ )
 fi
 
 if [ "$DOCKERHUB_ORGANIZATION" != "" ]
index b09efd6..d07c55a 100644 (file)
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
-    "name": "concurrent_connectivity_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "uses_polling": true
-  }, 
-  {
-    "args": [], 
-    "benchmark": false, 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c", 
     "name": "connection_refused_test", 
     "platforms": [
       "linux", 
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
-    "name": "cancel_ares_query_test", 
+    "name": "channel_arguments_test", 
     "platforms": [
       "linux", 
       "mac", 
       "posix", 
       "windows"
     ], 
-    "uses_polling": true
+    "uses_polling": false
   }, 
   {
     "args": [], 
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
-    "name": "channel_arguments_test", 
+    "name": "channel_filter_test", 
     "platforms": [
       "linux", 
       "mac", 
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
-    "name": "channel_filter_test", 
+    "name": "channel_trace_test", 
     "platforms": [
       "linux", 
       "mac", 
       "posix", 
       "windows"
     ], 
-    "uses_polling": false
+    "uses_polling": true
   }, 
   {
     "args": [], 
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
-    "name": "channel_trace_test", 
+    "name": "channelz_registry_test", 
     "platforms": [
       "linux", 
       "mac", 
       "posix", 
       "windows"
     ], 
-    "uses_polling": true
+    "uses_polling": false
   }, 
   {
     "args": [], 
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
-    "name": "channelz_registry_test", 
+    "name": "channelz_service_test", 
     "platforms": [
       "linux", 
       "mac", 
       "posix", 
       "windows"
     ], 
-    "uses_polling": false
+    "uses_polling": true
   }, 
   {
     "args": [], 
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
-    "name": "channelz_service_test", 
+    "name": "channelz_test", 
     "platforms": [
       "linux", 
       "mac", 
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
-    "name": "optional_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "uses_polling": true
-  }, 
-  {
-    "args": [], 
-    "benchmark": false, 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "gtest": true, 
-    "language": "c++", 
     "name": "orphanable_test", 
     "platforms": [
       "linux", 
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
-    "name": "string_view_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "uses_polling": true
-  }, 
-  {
-    "args": [], 
-    "benchmark": false, 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "gtest": true, 
-    "language": "c++", 
     "name": "test_cpp_client_credentials_test", 
     "platforms": [
       "linux", 
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/error_refcount"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/f03120d1a8376638e071735bf4746454b6ede389"
     ], 
     "ci_platforms": [
index e79a889..60031fa 100755 (executable)
@@ -224,8 +224,8 @@ pip_install_dir "$ROOT/src/python/grpcio_testing"
 
 # Build/install tests
 pip_install coverage==4.4 oauth2client==4.1.0 \
-            google-auth==1.0.0 requests==2.14.2 \
-            googleapis-common-protos==1.5.5
+            google-auth>=1.17.2 requests==2.14.2 \
+            googleapis-common-protos>=1.5.5 rsa==4.0
 $VENV_PYTHON "$ROOT/src/python/grpcio_tests/setup.py" preprocess
 $VENV_PYTHON "$ROOT/src/python/grpcio_tests/setup.py" build_package_protos
 pip_install_dir "$ROOT/src/python/grpcio_tests"
diff --git a/tools/run_tests/run_build_statistics.py b/tools/run_tests/run_build_statistics.py
deleted file mode 100755 (executable)
index d88f3db..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2016 gRPC authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Tool to get build statistics from Jenkins and upload to BigQuery."""
-
-from __future__ import print_function
-
-import argparse
-import jenkinsapi
-from jenkinsapi.custom_exceptions import JenkinsAPIException
-from jenkinsapi.jenkins import Jenkins
-import json
-import os
-import re
-import sys
-import urllib
-
-gcp_utils_dir = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '../gcp/utils'))
-sys.path.append(gcp_utils_dir)
-import big_query_utils
-
-_PROJECT_ID = 'grpc-testing'
-_HAS_MATRIX = True
-_BUILDS = {
-    'gRPC_interop_master': not _HAS_MATRIX,
-    'gRPC_master_linux': not _HAS_MATRIX,
-    'gRPC_master_macos': not _HAS_MATRIX,
-    'gRPC_master_windows': not _HAS_MATRIX,
-    'gRPC_performance_master': not _HAS_MATRIX,
-    'gRPC_portability_master_linux': not _HAS_MATRIX,
-    'gRPC_portability_master_windows': not _HAS_MATRIX,
-    'gRPC_master_asanitizer_c': not _HAS_MATRIX,
-    'gRPC_master_asanitizer_cpp': not _HAS_MATRIX,
-    'gRPC_master_msan_c': not _HAS_MATRIX,
-    'gRPC_master_tsanitizer_c': not _HAS_MATRIX,
-    'gRPC_master_tsan_cpp': not _HAS_MATRIX,
-    'gRPC_interop_pull_requests': not _HAS_MATRIX,
-    'gRPC_performance_pull_requests': not _HAS_MATRIX,
-    'gRPC_portability_pull_requests_linux': not _HAS_MATRIX,
-    'gRPC_portability_pr_win': not _HAS_MATRIX,
-    'gRPC_pull_requests_linux': not _HAS_MATRIX,
-    'gRPC_pull_requests_macos': not _HAS_MATRIX,
-    'gRPC_pr_win': not _HAS_MATRIX,
-    'gRPC_pull_requests_asan_c': not _HAS_MATRIX,
-    'gRPC_pull_requests_asan_cpp': not _HAS_MATRIX,
-    'gRPC_pull_requests_msan_c': not _HAS_MATRIX,
-    'gRPC_pull_requests_tsan_c': not _HAS_MATRIX,
-    'gRPC_pull_requests_tsan_cpp': not _HAS_MATRIX,
-}
-_URL_BASE = 'https://grpc-testing.appspot.com/job'
-
-# This is a dynamic list where known and active issues should be added.
-# Fixed ones should be removed.
-# Also try not to add multiple messages from the same failure.
-_KNOWN_ERRORS = [
-    'Failed to build workspace Tests with scheme AllTests',
-    'Build timed out',
-    'TIMEOUT: tools/run_tests/pre_build_node.sh',
-    'TIMEOUT: tools/run_tests/pre_build_ruby.sh',
-    'FATAL: Unable to produce a script file',
-    'FAILED: build_docker_c\+\+',
-    'cannot find package \"cloud.google.com/go/compute/metadata\"',
-    'LLVM ERROR: IO failure on output stream.',
-    'MSBUILD : error MSB1009: Project file does not exist.',
-    'fatal: git fetch_pack: expected ACK/NAK',
-    'Failed to fetch from http://github.com/grpc/grpc.git',
-    ('hudson.remoting.RemotingSystemException: java.io.IOException: '
-     'Backing channel is disconnected.'),
-    'hudson.remoting.ChannelClosedException',
-    'Could not initialize class hudson.Util',
-    'Too many open files in system',
-    'FAILED: bins/tsan/qps_openloop_test GRPC_POLL_STRATEGY=epoll',
-    'FAILED: bins/tsan/qps_openloop_test GRPC_POLL_STRATEGY=legacy',
-    'FAILED: bins/tsan/qps_openloop_test GRPC_POLL_STRATEGY=poll',
-    ('tests.bins/asan/h2_proxy_test streaming_error_response '
-     'GRPC_POLL_STRATEGY=legacy'),
-    'hudson.plugins.git.GitException',
-    'Couldn\'t find any revision to build',
-    'org.jenkinsci.plugin.Diskcheck.preCheckout',
-    'Something went wrong while deleting Files',
-]
-_NO_REPORT_FILES_FOUND_ERROR = 'No test report files were found.'
-_UNKNOWN_ERROR = 'Unknown error'
-_DATASET_ID = 'build_statistics'
-
-
-def _scrape_for_known_errors(html):
-    error_list = []
-    for known_error in _KNOWN_ERRORS:
-        errors = re.findall(known_error, html)
-        this_error_count = len(errors)
-        if this_error_count > 0:
-            error_list.append({
-                'description': known_error,
-                'count': this_error_count
-            })
-            print('====> %d failures due to %s' %
-                  (this_error_count, known_error))
-    return error_list
-
-
-def _no_report_files_found(html):
-    return _NO_REPORT_FILES_FOUND_ERROR in html
-
-
-def _get_last_processed_buildnumber(build_name):
-    query = 'SELECT max(build_number) FROM [%s:%s.%s];' % (
-        _PROJECT_ID, _DATASET_ID, build_name)
-    query_job = big_query_utils.sync_query_job(bq, _PROJECT_ID, query)
-    page = bq.jobs().getQueryResults(
-        pageToken=None, **query_job['jobReference']).execute(num_retries=3)
-    if page['rows'][0]['f'][0]['v']:
-        return int(page['rows'][0]['f'][0]['v'])
-    return 0
-
-
-def _process_matrix(build, url_base):
-    matrix_list = []
-    for matrix in build.get_matrix_runs():
-        matrix_str = re.match('.*\\xc2\\xbb ((?:[^,]+,?)+) #.*',
-                              matrix.name).groups()[0]
-        matrix_tuple = matrix_str.split(',')
-        json_url = '%s/config=%s,language=%s,platform=%s/testReport/api/json' % (
-            url_base, matrix_tuple[0], matrix_tuple[1], matrix_tuple[2])
-        console_url = '%s/config=%s,language=%s,platform=%s/consoleFull' % (
-            url_base, matrix_tuple[0], matrix_tuple[1], matrix_tuple[2])
-        matrix_dict = {
-            'name': matrix_str,
-            'duration': matrix.get_duration().total_seconds()
-        }
-        matrix_dict.update(_process_build(json_url, console_url))
-        matrix_list.append(matrix_dict)
-
-    return matrix_list
-
-
-def _process_build(json_url, console_url):
-    build_result = {}
-    error_list = []
-    try:
-        html = urllib.urlopen(json_url).read()
-        test_result = json.loads(html)
-        print('====> Parsing result from %s' % json_url)
-        failure_count = test_result['failCount']
-        build_result['pass_count'] = test_result['passCount']
-        build_result['failure_count'] = failure_count
-        # This means Jenkins failure occurred.
-        build_result['no_report_files_found'] = _no_report_files_found(html)
-        # Only check errors if Jenkins failure occurred.
-        if build_result['no_report_files_found']:
-            error_list = _scrape_for_known_errors(html)
-    except Exception as e:
-        print('====> Got exception for %s: %s.' % (json_url, str(e)))
-        print('====> Parsing errors from %s.' % console_url)
-        html = urllib.urlopen(console_url).read()
-        build_result['pass_count'] = 0
-        build_result['failure_count'] = 1
-        # In this case, the string doesn't exist in the result html but the fact
-        # that we fail to parse the result html indicates Jenkins failure and hence
-        # no report files were generated.
-        build_result['no_report_files_found'] = True
-        error_list = _scrape_for_known_errors(html)
-
-    if error_list:
-        build_result['error'] = error_list
-    elif build_result['no_report_files_found']:
-        build_result['error'] = [{'description': _UNKNOWN_ERROR, 'count': 1}]
-    else:
-        build_result['error'] = [{'description': '', 'count': 0}]
-
-    return build_result
-
-
-# parse command line
-argp = argparse.ArgumentParser(description='Get build statistics.')
-argp.add_argument('-u', '--username', default='jenkins')
-argp.add_argument('-b',
-                  '--builds',
-                  choices=['all'] + sorted(_BUILDS.keys()),
-                  nargs='+',
-                  default=['all'])
-args = argp.parse_args()
-
-J = Jenkins('https://grpc-testing.appspot.com', args.username, 'apiToken')
-bq = big_query_utils.create_big_query()
-
-for build_name in _BUILDS.keys() if 'all' in args.builds else args.builds:
-    print('====> Build: %s' % build_name)
-    # Since get_last_completed_build() always fails due to malformatted string
-    # error, we use get_build_metadata() instead.
-    job = None
-    try:
-        job = J[build_name]
-    except Exception as e:
-        print('====> Failed to get build %s: %s.' % (build_name, str(e)))
-        continue
-    last_processed_build_number = _get_last_processed_buildnumber(build_name)
-    last_complete_build_number = job.get_last_completed_buildnumber()
-    # To avoid processing all builds for a project never looked at. In this case,
-    # only examine 10 latest builds.
-    starting_build_number = max(last_processed_build_number + 1,
-                                last_complete_build_number - 9)
-    for build_number in xrange(starting_build_number,
-                               last_complete_build_number + 1):
-        print('====> Processing %s build %d.' % (build_name, build_number))
-        build = None
-        try:
-            build = job.get_build_metadata(build_number)
-            print('====> Build status: %s.' % build.get_status())
-            if build.get_status() == 'ABORTED':
-                continue
-            # If any build is still running, stop processing this job. Next time, we
-            # start from where it was left so that all builds are processed
-            # sequentially.
-            if build.is_running():
-                print('====> Build %d is still running.' % build_number)
-                break
-        except KeyError:
-            print('====> Build %s is missing. Skip.' % build_number)
-            continue
-        build_result = {
-            'build_number': build_number,
-            'timestamp': str(build.get_timestamp())
-        }
-        url_base = json_url = '%s/%s/%d' % (_URL_BASE, build_name, build_number)
-        if _BUILDS[build_name]:  # The build has matrix, such as gRPC_master.
-            build_result['matrix'] = _process_matrix(build, url_base)
-        else:
-            json_url = '%s/testReport/api/json' % url_base
-            console_url = '%s/consoleFull' % url_base
-            build_result['duration'] = build.get_duration().total_seconds()
-            build_stat = _process_build(json_url, console_url)
-            build_result.update(build_stat)
-        rows = [big_query_utils.make_row(build_number, build_result)]
-        if not big_query_utils.insert_rows(bq, _PROJECT_ID, _DATASET_ID,
-                                           build_name, rows):
-            print('====> Error uploading result to bigquery.')
-            sys.exit(1)
index d183c5b..eff5288 100755 (executable)
@@ -499,7 +499,7 @@ class PHPLanguage:
         return {}
 
     def unimplemented_test_cases(self):
-        return _SKIP_COMPRESSION + \
+        return _SKIP_SERVER_COMPRESSION + \
             _SKIP_DATA_FRAME_PADDING + \
             _SKIP_SPECIAL_STATUS_MESSAGE + \
             _SKIP_GOOGLE_DEFAULT_CREDS + \
@@ -528,7 +528,7 @@ class PHP7Language:
         return {}
 
     def unimplemented_test_cases(self):
-        return _SKIP_COMPRESSION + \
+        return _SKIP_SERVER_COMPRESSION + \
             _SKIP_DATA_FRAME_PADDING + \
             _SKIP_SPECIAL_STATUS_MESSAGE + \
             _SKIP_GOOGLE_DEFAULT_CREDS + \
@@ -786,9 +786,9 @@ _LANGUAGES_WITH_HTTP2_CLIENTS_FOR_HTTP2_SERVER_TEST_CASES = [
     'java', 'go', 'python', 'c++'
 ]
 
-_LANGUAGES_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++']
+_LANGUAGES_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++', 'python']
 
-_SERVERS_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++']
+_SERVERS_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++', 'python']
 
 _TRANSPORT_SECURITY_OPTIONS = ['tls', 'alts', 'insecure']
 
index 8f1d9b1..3073d30 100755 (executable)
@@ -32,6 +32,7 @@ from oauth2client.client import GoogleCredentials
 import python_utils.jobset as jobset
 import python_utils.report_utils as report_utils
 
+from src.proto.grpc.testing import empty_pb2
 from src.proto.grpc.testing import messages_pb2
 from src.proto.grpc.testing import test_pb2_grpc
 
@@ -46,12 +47,14 @@ logger.setLevel(logging.WARNING)
 _TEST_CASES = [
     'backends_restart',
     'change_backend_service',
+    'gentle_failover',
     'new_instance_group_receives_traffic',
     'ping_pong',
     'remove_instance_group',
     'round_robin',
     'secondary_locality_gets_no_requests_on_partial_primary_failure',
     'secondary_locality_gets_requests_on_primary_failure',
+    'traffic_splitting',
 ]
 
 
@@ -103,7 +106,7 @@ argp.add_argument('--zone', default='us-central1-a')
 argp.add_argument('--secondary_zone',
                   default='us-west1-b',
                   help='Zone to use for secondary TD locality tests')
-argp.add_argument('--qps', default=10, type=int, help='Client QPS')
+argp.add_argument('--qps', default=100, type=int, help='Client QPS')
 argp.add_argument(
     '--wait_for_backend_sec',
     default=1200,
@@ -183,8 +186,12 @@ argp.add_argument('--log_client_output',
                   help='Log captured client output',
                   default=False,
                   action='store_true')
+# TODO(ericgribkoff) Remove this flag once all test environments are verified to
+# have access to the alpha compute APIs.
 argp.add_argument('--only_stable_gcp_apis',
-                  help='Do not use alpha compute APIs',
+                  help='Do not use alpha compute APIs. Some tests may be '
+                  'incompatible with this option (gRPC health checks are '
+                  'currently alpha and required for simulating server failure',
                   default=False,
                   action='store_true')
 args = argp.parse_args()
@@ -198,7 +205,9 @@ _WAIT_FOR_OPERATION_SEC = 300
 _INSTANCE_GROUP_SIZE = args.instance_group_size
 _NUM_TEST_RPCS = 10 * args.qps
 _WAIT_FOR_STATS_SEC = 180
+_WAIT_FOR_VALID_CONFIG_SEC = 60
 _WAIT_FOR_URL_MAP_PATCH_SEC = 300
+_CONNECTION_TIMEOUT_SEC = 60
 _GCP_API_RETRIES = 5
 _BOOTSTRAP_TEMPLATE = """
 {{
@@ -221,12 +230,13 @@ _BOOTSTRAP_TEMPLATE = """
     ]
   }}]
 }}""" % (args.network.split('/')[-1], args.zone, args.xds_server)
-_TESTS_USING_SECONDARY_IG = [
-    'secondary_locality_gets_no_requests_on_partial_primary_failure',
-    'secondary_locality_gets_requests_on_primary_failure'
+
+# TODO(ericgribkoff) Add change_backend_service to this list once TD no longer
+# sends an update with no localities when adding the MIG to the backend service
+# can race with the URL map patch.
+_TESTS_TO_FAIL_ON_RPC_FAILURE = [
+    'new_instance_group_receives_traffic', 'ping_pong', 'round_robin'
 ]
-_USE_SECONDARY_IG = any(
-    [t in args.test_case for t in _TESTS_USING_SECONDARY_IG])
 _PATH_MATCHER_NAME = 'path-matcher'
 _BASE_TEMPLATE_NAME = 'test-template'
 _BASE_INSTANCE_GROUP_NAME = 'test-ig'
@@ -249,15 +259,16 @@ def get_client_stats(num_rpcs, timeout_sec):
         request = messages_pb2.LoadBalancerStatsRequest()
         request.num_rpcs = num_rpcs
         request.timeout_sec = timeout_sec
-        rpc_timeout = timeout_sec * 2  # Allow time for connection establishment
-        try:
-            response = stub.GetClientStats(request,
-                                           wait_for_ready=True,
-                                           timeout=rpc_timeout)
-            logger.debug('Invoked GetClientStats RPC: %s', response)
-            return response
-        except grpc.RpcError as rpc_error:
-            logger.exception('GetClientStats RPC failed')
+        rpc_timeout = timeout_sec + _CONNECTION_TIMEOUT_SEC
+        response = stub.GetClientStats(request,
+                                       wait_for_ready=True,
+                                       timeout=rpc_timeout)
+        logger.debug('Invoked GetClientStats RPC: %s', response)
+        return response
+
+
+class RpcDistributionError(Exception):
+    pass
 
 
 def _verify_rpcs_to_given_backends(backends, timeout_sec, num_rpcs,
@@ -280,12 +291,12 @@ def _verify_rpcs_to_given_backends(backends, timeout_sec, num_rpcs,
             error_msg = '%d RPCs failed' % stats.num_failures
         if not error_msg:
             return
-    raise Exception(error_msg)
+    raise RpcDistributionError(error_msg)
 
 
 def wait_until_all_rpcs_go_to_given_backends_or_fail(backends,
                                                      timeout_sec,
-                                                     num_rpcs=100):
+                                                     num_rpcs=_NUM_TEST_RPCS):
     _verify_rpcs_to_given_backends(backends,
                                    timeout_sec,
                                    num_rpcs,
@@ -294,13 +305,49 @@ def wait_until_all_rpcs_go_to_given_backends_or_fail(backends,
 
 def wait_until_all_rpcs_go_to_given_backends(backends,
                                              timeout_sec,
-                                             num_rpcs=100):
+                                             num_rpcs=_NUM_TEST_RPCS):
     _verify_rpcs_to_given_backends(backends,
                                    timeout_sec,
                                    num_rpcs,
                                    allow_failures=False)
 
 
+def compare_distributions(actual_distribution, expected_distribution,
+                          threshold):
+    """Compare if two distributions are similar.
+
+    Args:
+      actual_distribution: A list of floats, contains the actual distribution.
+      expected_distribution: A list of floats, contains the expected distribution.
+      threshold: Number within [0,100], the threshold percentage by which the
+        actual distribution can differ from the expected distribution.
+
+    Returns:
+      The similarity between the distributions as a boolean. Returns true if the
+      actual distribution lies within the threshold of the expected
+      distribution, false otherwise.
+    
+    Raises:
+      ValueError: if threshold is not with in [0,100].
+      Exception: containing detailed error messages.
+    """
+    if len(expected_distribution) != len(actual_distribution):
+        raise Exception(
+            'Error: expected and actual distributions have different size (%d vs %d)'
+            % (len(expected_distribution), len(actual_distribution)))
+    if threshold < 0 or threshold > 100:
+        raise ValueError('Value error: Threshold should be between 0 to 100')
+    threshold_fraction = threshold / 100.0
+    for expected, actual in zip(expected_distribution, actual_distribution):
+        if actual < (expected * (1 - threshold_fraction)):
+            raise Exception("actual(%f) < expected(%f-%d%%)" %
+                            (actual, expected, threshold))
+        if actual > (expected * (1 + threshold_fraction)):
+            raise Exception("actual(%f) > expected(%f+%d%%)" %
+                            (actual, expected, threshold))
+    return True
+
+
 def test_backends_restart(gcp, backend_service, instance_group):
     logger.info('Running test_backends_restart')
     instance_names = get_instance_names(gcp, instance_group)
@@ -346,9 +393,6 @@ def test_change_backend_service(gcp, original_backend_service, instance_group,
                                              _WAIT_FOR_STATS_SEC)
     try:
         patch_url_map_backend_service(gcp, alternate_backend_service)
-        # TODO(ericgribkoff) Verify no RPCs fail during backend switch.
-        # Currently TD may briefly send an update with no localities if adding
-        # the MIG to the backend service above races with the URL map patch.
         wait_until_all_rpcs_go_to_given_backends(alternate_backend_instances,
                                                  _WAIT_FOR_URL_MAP_PATCH_SEC)
     finally:
@@ -356,6 +400,62 @@ def test_change_backend_service(gcp, original_backend_service, instance_group,
         patch_backend_instances(gcp, alternate_backend_service, [])
 
 
+def test_gentle_failover(gcp,
+                         backend_service,
+                         primary_instance_group,
+                         secondary_instance_group,
+                         swapped_primary_and_secondary=False):
+    logger.info('Running test_gentle_failover')
+    num_primary_instances = len(get_instance_names(gcp, primary_instance_group))
+    min_instances_for_gentle_failover = 3  # Need >50% failure to start failover
+    try:
+        if num_primary_instances < min_instances_for_gentle_failover:
+            resize_instance_group(gcp, primary_instance_group,
+                                  min_instances_for_gentle_failover)
+        patch_backend_instances(
+            gcp, backend_service,
+            [primary_instance_group, secondary_instance_group])
+        primary_instance_names = get_instance_names(gcp, primary_instance_group)
+        secondary_instance_names = get_instance_names(gcp,
+                                                      secondary_instance_group)
+        wait_for_healthy_backends(gcp, backend_service, primary_instance_group)
+        wait_for_healthy_backends(gcp, backend_service,
+                                  secondary_instance_group)
+        wait_until_all_rpcs_go_to_given_backends(primary_instance_names,
+                                                 _WAIT_FOR_STATS_SEC)
+        instances_to_stop = primary_instance_names[:-1]
+        remaining_instances = primary_instance_names[-1:]
+        try:
+            set_serving_status(instances_to_stop,
+                               gcp.service_port,
+                               serving=False)
+            wait_until_all_rpcs_go_to_given_backends(
+                remaining_instances + secondary_instance_names,
+                _WAIT_FOR_BACKEND_SEC)
+        finally:
+            set_serving_status(primary_instance_names,
+                               gcp.service_port,
+                               serving=True)
+    except RpcDistributionError as e:
+        if not swapped_primary_and_secondary and is_primary_instance_group(
+                gcp, secondary_instance_group):
+            # Swap expectation of primary and secondary instance groups.
+            test_gentle_failover(gcp,
+                                 backend_service,
+                                 secondary_instance_group,
+                                 primary_instance_group,
+                                 swapped_primary_and_secondary=True)
+        else:
+            raise e
+    finally:
+        patch_backend_instances(gcp, backend_service, [primary_instance_group])
+        resize_instance_group(gcp, primary_instance_group,
+                              num_primary_instances)
+        instance_names = get_instance_names(gcp, primary_instance_group)
+        wait_until_all_rpcs_go_to_given_backends(instance_names,
+                                                 _WAIT_FOR_BACKEND_SEC)
+
+
 def test_new_instance_group_receives_traffic(gcp, backend_service,
                                              instance_group,
                                              same_zone_instance_group):
@@ -438,65 +538,216 @@ def test_round_robin(gcp, backend_service, instance_group):
 
 
 def test_secondary_locality_gets_no_requests_on_partial_primary_failure(
-        gcp, backend_service, primary_instance_group,
-        secondary_zone_instance_group):
+        gcp,
+        backend_service,
+        primary_instance_group,
+        secondary_instance_group,
+        swapped_primary_and_secondary=False):
     logger.info(
-        'Running test_secondary_locality_gets_no_requests_on_partial_primary_failure'
+        'Running secondary_locality_gets_no_requests_on_partial_primary_failure'
     )
     try:
         patch_backend_instances(
             gcp, backend_service,
-            [primary_instance_group, secondary_zone_instance_group])
+            [primary_instance_group, secondary_instance_group])
         wait_for_healthy_backends(gcp, backend_service, primary_instance_group)
         wait_for_healthy_backends(gcp, backend_service,
-                                  secondary_zone_instance_group)
-        primary_instance_names = get_instance_names(gcp, instance_group)
-        secondary_instance_names = get_instance_names(
-            gcp, secondary_zone_instance_group)
+                                  secondary_instance_group)
+        primary_instance_names = get_instance_names(gcp, primary_instance_group)
         wait_until_all_rpcs_go_to_given_backends(primary_instance_names,
                                                  _WAIT_FOR_STATS_SEC)
-        original_size = len(primary_instance_names)
-        resize_instance_group(gcp, primary_instance_group, original_size - 1)
-        remaining_instance_names = get_instance_names(gcp,
-                                                      primary_instance_group)
-        wait_until_all_rpcs_go_to_given_backends(remaining_instance_names,
-                                                 _WAIT_FOR_BACKEND_SEC)
+        instances_to_stop = primary_instance_names[:1]
+        remaining_instances = primary_instance_names[1:]
+        try:
+            set_serving_status(instances_to_stop,
+                               gcp.service_port,
+                               serving=False)
+            wait_until_all_rpcs_go_to_given_backends(remaining_instances,
+                                                     _WAIT_FOR_BACKEND_SEC)
+        finally:
+            set_serving_status(primary_instance_names,
+                               gcp.service_port,
+                               serving=True)
+    except RpcDistributionError as e:
+        if not swapped_primary_and_secondary and is_primary_instance_group(
+                gcp, secondary_instance_group):
+            # Swap expectation of primary and secondary instance groups.
+            test_secondary_locality_gets_no_requests_on_partial_primary_failure(
+                gcp,
+                backend_service,
+                secondary_instance_group,
+                primary_instance_group,
+                swapped_primary_and_secondary=True)
+        else:
+            raise e
     finally:
         patch_backend_instances(gcp, backend_service, [primary_instance_group])
-        resize_instance_group(gcp, primary_instance_group, original_size)
 
 
 def test_secondary_locality_gets_requests_on_primary_failure(
-        gcp, backend_service, primary_instance_group,
-        secondary_zone_instance_group):
-    logger.info(
-        'Running test_secondary_locality_gets_requests_on_primary_failure')
+        gcp,
+        backend_service,
+        primary_instance_group,
+        secondary_instance_group,
+        swapped_primary_and_secondary=False):
+    logger.info('Running secondary_locality_gets_requests_on_primary_failure')
     try:
         patch_backend_instances(
             gcp, backend_service,
-            [primary_instance_group, secondary_zone_instance_group])
+            [primary_instance_group, secondary_instance_group])
         wait_for_healthy_backends(gcp, backend_service, primary_instance_group)
         wait_for_healthy_backends(gcp, backend_service,
-                                  secondary_zone_instance_group)
-        primary_instance_names = get_instance_names(gcp, instance_group)
-        secondary_instance_names = get_instance_names(
-            gcp, secondary_zone_instance_group)
+                                  secondary_instance_group)
+        primary_instance_names = get_instance_names(gcp, primary_instance_group)
+        secondary_instance_names = get_instance_names(gcp,
+                                                      secondary_instance_group)
         wait_until_all_rpcs_go_to_given_backends(primary_instance_names,
-                                                 _WAIT_FOR_BACKEND_SEC)
-        original_size = len(primary_instance_names)
-        resize_instance_group(gcp, primary_instance_group, 0)
-        wait_until_all_rpcs_go_to_given_backends(secondary_instance_names,
-                                                 _WAIT_FOR_BACKEND_SEC)
-
-        resize_instance_group(gcp, primary_instance_group, original_size)
-        new_instance_names = get_instance_names(gcp, primary_instance_group)
-        wait_for_healthy_backends(gcp, backend_service, primary_instance_group)
-        wait_until_all_rpcs_go_to_given_backends(new_instance_names,
-                                                 _WAIT_FOR_BACKEND_SEC)
+                                                 _WAIT_FOR_STATS_SEC)
+        try:
+            set_serving_status(primary_instance_names,
+                               gcp.service_port,
+                               serving=False)
+            wait_until_all_rpcs_go_to_given_backends(secondary_instance_names,
+                                                     _WAIT_FOR_BACKEND_SEC)
+        finally:
+            set_serving_status(primary_instance_names,
+                               gcp.service_port,
+                               serving=True)
+    except RpcDistributionError as e:
+        if not swapped_primary_and_secondary and is_primary_instance_group(
+                gcp, secondary_instance_group):
+            # Swap expectation of primary and secondary instance groups.
+            test_secondary_locality_gets_requests_on_primary_failure(
+                gcp,
+                backend_service,
+                secondary_instance_group,
+                primary_instance_group,
+                swapped_primary_and_secondary=True)
+        else:
+            raise e
     finally:
         patch_backend_instances(gcp, backend_service, [primary_instance_group])
 
 
+def test_traffic_splitting(gcp, original_backend_service, instance_group,
+                           alternate_backend_service, same_zone_instance_group):
+    # This test start with all traffic going to original_backend_service. Then
+    # it updates URL-map to set default action to traffic splitting between
+    # original and alternate. It waits for all backends in both services to
+    # receive traffic, then verifies that weights are expected.
+    logger.info('Running test_traffic_splitting')
+
+    # The config validation for proxyless doesn't allow setting
+    # default_route_action. To test traffic splitting, we need to set the
+    # route action to weighted clusters. Disable validate
+    # validate_for_proxyless for this test. This can be removed when
+    # validation accepts default_route_action.
+    logger.info('disabling validate_for_proxyless in target proxy')
+    set_validate_for_proxyless(gcp, False)
+
+    logger.info('waiting for original backends to become healthy')
+    wait_for_healthy_backends(gcp, original_backend_service, instance_group)
+
+    patch_backend_instances(gcp, alternate_backend_service,
+                            [same_zone_instance_group])
+    logger.info('waiting for alternate to become healthy')
+    wait_for_healthy_backends(gcp, alternate_backend_service,
+                              same_zone_instance_group)
+
+    original_backend_instances = get_instance_names(gcp, instance_group)
+    logger.info('original backends instances: %s', original_backend_instances)
+
+    alternate_backend_instances = get_instance_names(gcp,
+                                                     same_zone_instance_group)
+    logger.info('alternate backends instances: %s', alternate_backend_instances)
+
+    # Start with all traffic going to original_backend_service.
+    logger.info('waiting for traffic to all go to original backends')
+    wait_until_all_rpcs_go_to_given_backends(original_backend_instances,
+                                             _WAIT_FOR_STATS_SEC)
+
+    try:
+        # Patch urlmap, change route action to traffic splitting between
+        # original and alternate.
+        logger.info('patching url map with traffic splitting')
+        original_service_percentage, alternate_service_percentage = 20, 80
+        patch_url_map_backend_service(
+            gcp,
+            services_with_weights={
+                original_backend_service: original_service_percentage,
+                alternate_backend_service: alternate_service_percentage,
+            })
+        # Split percentage between instances: [20,80] -> [10,10,40,40].
+        expected_instance_percentage = [
+            original_service_percentage * 1.0 / len(original_backend_instances)
+        ] * len(original_backend_instances) + [
+            alternate_service_percentage * 1.0 /
+            len(alternate_backend_instances)
+        ] * len(alternate_backend_instances)
+
+        # Wait for traffic to go to both services.
+        logger.info(
+            'waiting for traffic to go to all backends (including alternate)')
+        wait_until_all_rpcs_go_to_given_backends(
+            original_backend_instances + alternate_backend_instances,
+            _WAIT_FOR_STATS_SEC)
+
+        # Verify that weights between two services are expected.
+        retry_count = 10
+        # Each attempt takes about 10 seconds, 10 retries is equivalent to 100
+        # seconds timeout.
+        for i in range(retry_count):
+            stats = get_client_stats(_NUM_TEST_RPCS, _WAIT_FOR_STATS_SEC)
+            got_instance_count = [
+                stats.rpcs_by_peer[i] for i in original_backend_instances
+            ] + [stats.rpcs_by_peer[i] for i in alternate_backend_instances]
+            total_count = sum(got_instance_count)
+            got_instance_percentage = [
+                x * 100.0 / total_count for x in got_instance_count
+            ]
+
+            try:
+                compare_distributions(got_instance_percentage,
+                                      expected_instance_percentage, 5)
+            except Exception as e:
+                logger.info('attempt %d', i)
+                logger.info('got percentage: %s', got_instance_percentage)
+                logger.info('expected percentage: %s',
+                            expected_instance_percentage)
+                logger.info(e)
+                if i == retry_count - 1:
+                    raise Exception(
+                        'RPC distribution (%s) differs from expected (%s)',
+                        got_instance_percentage, expected_instance_percentage)
+            else:
+                logger.info("success")
+                break
+    finally:
+        patch_url_map_backend_service(gcp, original_backend_service)
+        patch_backend_instances(gcp, alternate_backend_service, [])
+        set_validate_for_proxyless(gcp, True)
+
+
+def set_serving_status(instances, service_port, serving):
+    for instance in instances:
+        with grpc.insecure_channel('%s:%d' %
+                                   (instance, service_port)) as channel:
+            stub = test_pb2_grpc.XdsUpdateHealthServiceStub(channel)
+            if serving:
+                stub.SetServing(empty_pb2.Empty())
+            else:
+                stub.SetNotServing(empty_pb2.Empty())
+
+
+def is_primary_instance_group(gcp, instance_group):
+    # Clients may connect to a TD instance in a different region than the
+    # client, in which case primary/secondary assignments may not be based on
+    # the client's actual locality.
+    instance_names = get_instance_names(gcp, instance_group)
+    stats = get_client_stats(_NUM_TEST_RPCS, _WAIT_FOR_STATS_SEC)
+    return all(peer in instance_names for peer in stats.rpcs_by_peer.keys())
+
+
 def get_startup_script(path_to_server_binary, service_port):
     if path_to_server_binary:
         return "nohup %s --port=%d 1>/dev/null &" % (path_to_server_binary,
@@ -580,6 +831,8 @@ def add_instance_group(gcp, zone, name, size):
     instance_group = InstanceGroup(config['name'], result['instanceGroup'],
                                    zone)
     gcp.instance_groups.append(instance_group)
+    wait_for_instance_group_to_reach_expected_size(gcp, instance_group, size,
+                                                   _WAIT_FOR_OPERATION_SEC)
     return instance_group
 
 
@@ -684,12 +937,27 @@ def patch_url_map_host_rule_with_port(gcp, name, backend_service, host_name):
     wait_for_global_operation(gcp, result['name'])
 
 
-def create_target_proxy(gcp, name):
+def set_validate_for_proxyless(gcp, validate_for_proxyless):
+    if not gcp.alpha_compute:
+        logger.debug(
+            'Not setting validateForProxy because alpha is not enabled')
+        return
+    # This function deletes global_forwarding_rule and target_proxy, then
+    # recreate target_proxy with validateForProxyless=False. This is necessary
+    # because patching target_grpc_proxy isn't supported.
+    delete_global_forwarding_rule(gcp)
+    delete_target_proxy(gcp)
+    create_target_proxy(gcp, gcp.target_proxy.name, validate_for_proxyless)
+    create_global_forwarding_rule(gcp, gcp.global_forwarding_rule.name,
+                                  [gcp.service_port])
+
+
+def create_target_proxy(gcp, name, validate_for_proxyless=True):
     if gcp.alpha_compute:
         config = {
             'name': name,
             'url_map': gcp.url_map.url,
-            'validate_for_proxyless': True,
+            'validate_for_proxyless': validate_for_proxyless,
         }
         logger.debug('Sending GCP request with body=%s', config)
         result = gcp.alpha_compute.targetGrpcProxies().insert(
@@ -934,23 +1202,34 @@ def resize_instance_group(gcp,
                             instance_group.zone,
                             result['name'],
                             timeout_sec=360)
-    start_time = time.time()
-    while True:
-        current_size = len(get_instance_names(gcp, instance_group))
-        if current_size == new_size:
-            break
-        if time.time() - start_time > timeout_sec:
-            raise Exception('Failed to resize primary instance group')
-        time.sleep(2)
+    wait_for_instance_group_to_reach_expected_size(gcp, instance_group,
+                                                   new_size, timeout_sec)
+
 
+def patch_url_map_backend_service(gcp,
+                                  backend_service=None,
+                                  services_with_weights=None):
+    '''change url_map's backend service
+
+    Only one of backend_service and service_with_weights can be not None.
+    '''
+    if backend_service and services_with_weights:
+        raise ValueError(
+            'both backend_service and service_with_weights are not None.')
+
+    default_service = backend_service.url if backend_service else None
+    default_route_action = {
+        'weightedBackendServices': [{
+            'backendService': service.url,
+            'weight': w,
+        } for service, w in services_with_weights.items()]
+    } if services_with_weights else None
 
-def patch_url_map_backend_service(gcp, backend_service):
     config = {
-        'defaultService':
-            backend_service.url,
         'pathMatchers': [{
             'name': _PATH_MATCHER_NAME,
-            'defaultService': backend_service.url,
+            'defaultService': default_service,
+            'defaultRouteAction': default_route_action,
         }]
     }
     logger.debug('Sending GCP request with body=%s', config)
@@ -960,6 +1239,20 @@ def patch_url_map_backend_service(gcp, backend_service):
     wait_for_global_operation(gcp, result['name'])
 
 
+def wait_for_instance_group_to_reach_expected_size(gcp, instance_group,
+                                                   expected_size, timeout_sec):
+    start_time = time.time()
+    while True:
+        current_size = len(get_instance_names(gcp, instance_group))
+        if current_size == expected_size:
+            break
+        if time.time() - start_time > timeout_sec:
+            raise Exception(
+                'Instance group had expected size %d but actual size %d' %
+                (expected_size, current_size))
+        time.sleep(2)
+
+
 def wait_for_global_operation(gcp,
                               operation,
                               timeout_sec=_WAIT_FOR_OPERATION_SEC):
@@ -1001,24 +1294,35 @@ def wait_for_healthy_backends(gcp,
                               timeout_sec=_WAIT_FOR_BACKEND_SEC):
     start_time = time.time()
     config = {'group': instance_group.url}
+    expected_size = len(get_instance_names(gcp, instance_group))
     while time.time() - start_time <= timeout_sec:
         result = gcp.compute.backendServices().getHealth(
             project=gcp.project,
             backendService=backend_service.name,
             body=config).execute(num_retries=_GCP_API_RETRIES)
         if 'healthStatus' in result:
+            logger.info('received healthStatus: %s', result['healthStatus'])
             healthy = True
             for instance in result['healthStatus']:
                 if instance['healthState'] != 'HEALTHY':
                     healthy = False
                     break
-            if healthy:
+            if healthy and expected_size == len(result['healthStatus']):
                 return
         time.sleep(2)
     raise Exception('Not all backends became healthy within %d seconds: %s' %
                     (timeout_sec, result))
 
 
+def wait_for_config_propagation(gcp, instance_group, client_cmd, client_env):
+    """Use client to verify config propagation from GCP->TD->client"""
+    instance_names = get_instance_names(gcp, instance_group)
+    client_process = subprocess.Popen(shlex.split(client_cmd), env=client_env)
+    wait_until_all_rpcs_go_to_given_backends(instance_names,
+                                             _WAIT_FOR_VALID_CONFIG_SEC)
+    client_process.terminate()
+
+
 def get_instance_names(gcp, instance_group):
     instance_names = []
     result = gcp.compute.instanceGroups().listInstances(
@@ -1037,6 +1341,7 @@ def get_instance_names(gcp, instance_group):
         # just extract the name manually.
         instance_name = item['instance'].split('/')[-1]
         instance_names.append(instance_name)
+    logger.info('retrieved instance names: %s', instance_names)
     return instance_names
 
 
@@ -1116,8 +1421,7 @@ try:
     template_name = _BASE_TEMPLATE_NAME + args.gcp_suffix
     instance_group_name = _BASE_INSTANCE_GROUP_NAME + args.gcp_suffix
     same_zone_instance_group_name = _BASE_INSTANCE_GROUP_NAME + '-same-zone' + args.gcp_suffix
-    if _USE_SECONDARY_IG:
-        secondary_zone_instance_group_name = _BASE_INSTANCE_GROUP_NAME + '-secondary-zone' + args.gcp_suffix
+    secondary_zone_instance_group_name = _BASE_INSTANCE_GROUP_NAME + '-secondary-zone' + args.gcp_suffix
     if args.use_existing_gcp_resources:
         logger.info('Reusing existing GCP resources')
         get_health_check(gcp, health_check_name)
@@ -1138,9 +1442,8 @@ try:
         instance_group = get_instance_group(gcp, args.zone, instance_group_name)
         same_zone_instance_group = get_instance_group(
             gcp, args.zone, same_zone_instance_group_name)
-        if _USE_SECONDARY_IG:
-            secondary_zone_instance_group = get_instance_group(
-                gcp, args.secondary_zone, secondary_zone_instance_group_name)
+        secondary_zone_instance_group = get_instance_group(
+            gcp, args.secondary_zone, secondary_zone_instance_group_name)
     else:
         create_health_check(gcp, health_check_name)
         create_health_check_firewall_rule(gcp, firewall_name)
@@ -1170,15 +1473,13 @@ try:
         patch_backend_instances(gcp, backend_service, [instance_group])
         same_zone_instance_group = add_instance_group(
             gcp, args.zone, same_zone_instance_group_name, _INSTANCE_GROUP_SIZE)
-        if _USE_SECONDARY_IG:
-            secondary_zone_instance_group = add_instance_group(
-                gcp, args.secondary_zone, secondary_zone_instance_group_name,
-                _INSTANCE_GROUP_SIZE)
+        secondary_zone_instance_group = add_instance_group(
+            gcp, args.secondary_zone, secondary_zone_instance_group_name,
+            _INSTANCE_GROUP_SIZE)
 
     wait_for_healthy_backends(gcp, backend_service, instance_group)
 
     if args.test_case:
-
         if gcp.service_port == _DEFAULT_SERVICE_PORT:
             server_uri = service_host_name
         else:
@@ -1192,10 +1493,6 @@ try:
                         node_id=socket.gethostname()).encode('utf-8'))
                 bootstrap_path = bootstrap_file.name
         client_env = dict(os.environ, GRPC_XDS_BOOTSTRAP=bootstrap_path)
-        client_cmd = shlex.split(
-            args.client_cmd.format(server_uri=server_uri,
-                                   stats_port=args.stats_port,
-                                   qps=args.qps))
 
         test_results = {}
         failed_tests = []
@@ -1207,6 +1504,22 @@ try:
             test_log_filename = os.path.join(log_dir, _SPONGE_LOG_NAME)
             test_log_file = open(test_log_filename, 'w+')
             client_process = None
+            if test_case in _TESTS_TO_FAIL_ON_RPC_FAILURE:
+                wait_for_config_propagation(
+                    gcp, instance_group,
+                    args.client_cmd.format(server_uri=server_uri,
+                                           stats_port=args.stats_port,
+                                           qps=args.qps,
+                                           fail_on_failed_rpc=False),
+                    client_env)
+                fail_on_failed_rpc = '--fail_on_failed_rpc=true'
+            else:
+                fail_on_failed_rpc = '--fail_on_failed_rpc=false'
+            client_cmd = shlex.split(
+                args.client_cmd.format(server_uri=server_uri,
+                                       stats_port=args.stats_port,
+                                       qps=args.qps,
+                                       fail_on_failed_rpc=fail_on_failed_rpc))
             try:
                 client_process = subprocess.Popen(client_cmd,
                                                   env=client_env,
@@ -1219,6 +1532,9 @@ try:
                                                 instance_group,
                                                 alternate_backend_service,
                                                 same_zone_instance_group)
+                elif test_case == 'gentle_failover':
+                    test_gentle_failover(gcp, backend_service, instance_group,
+                                         secondary_zone_instance_group)
                 elif test_case == 'new_instance_group_receives_traffic':
                     test_new_instance_group_receives_traffic(
                         gcp, backend_service, instance_group,
@@ -1239,9 +1555,17 @@ try:
                     test_secondary_locality_gets_requests_on_primary_failure(
                         gcp, backend_service, instance_group,
                         secondary_zone_instance_group)
+                elif test_case == 'traffic_splitting':
+                    test_traffic_splitting(gcp, backend_service, instance_group,
+                                           alternate_backend_service,
+                                           same_zone_instance_group)
                 else:
                     logger.error('Unknown test case: %s', test_case)
                     sys.exit(1)
+                if client_process.poll() is not None:
+                    raise Exception(
+                        'Client process exited prematurely with exit code %d' %
+                        client_process.returncode)
                 result.state = 'PASSED'
                 result.returncode = 0
             except Exception as e:
@@ -1250,7 +1574,7 @@ try:
                 result.state = 'FAILED'
                 result.message = str(e)
             finally:
-                if client_process:
+                if client_process and not client_process.returncode:
                     client_process.terminate()
                 test_log_file.close()
                 # Workaround for Python 3, as report_utils will invoke decode() on
index 641692d..6a01e71 100755 (executable)
@@ -68,6 +68,7 @@ _GRPC_DEP_NAMES = [
 ]
 
 _GRPC_BAZEL_ONLY_DEPS = [
+    'upb',  # third_party/upb is checked in locally
     'rules_cc',
     'com_google_absl',
     'io_opencensus_cpp',
@@ -109,7 +110,12 @@ class BazelEvalState(object):
         if args['name'] in _GRPC_BAZEL_ONLY_DEPS:
             self.names_and_urls[args['name']] = 'dont care'
             return
-        self.names_and_urls[args['name']] = args['url']
+        url = args.get('url', None)
+        if not url:
+            # we will only be looking for git commit hashes, so concatenating
+            # the urls is fine.
+            url = ' '.join(args['urls'])
+        self.names_and_urls[args['name']] = url
 
     def git_repository(self, **args):
         assert self.names_and_urls.get(args['name']) is None
@@ -165,6 +171,11 @@ if len(workspace_git_hashes - git_submodule_hashes) > 0:
     print(
         "Found discrepancies between git submodules and Bazel WORKSPACE dependencies"
     )
+    print("workspace_git_hashes: %s" % workspace_git_hashes)
+    print("git_submodule_hashes: %s" % git_submodule_hashes)
+    print("workspace_git_hashes - git_submodule_hashes: %s" %
+          (workspace_git_hashes - git_submodule_hashes))
+    sys.exit(1)
 
 # Also check that we can override each dependency
 for name in _GRPC_DEP_NAMES:
index 05a28ea..e301924 100755 (executable)
@@ -29,16 +29,16 @@ cat << EOF | awk '{ print $1 }' | sort > "$want_submodules"
  df3ea785d8c30a9503321a3d35ee7d35808f190d third_party/abseil-cpp (heads/master)
  090faecb454fbd6e6e17a75ef8146acb037118d4 third_party/benchmark (v1.5.0)
  73594cde8c9a52a102c4341c244c833aa61b9c06 third_party/bloaty (remotes/origin/wide-14-g73594cd)
1c2769383f027befac5b75b6cedd25daf3bf4dcf third_party/boringssl-with-bazel (remotes/origin/master-with-bazel)
3ab047a8e377083a9b38dc908fe1612d5743a021 third_party/boringssl-with-bazel (remotes/origin/master-with-bazel)
  e982924acee7f7313b4baa4ee5ec000c5e373c30 third_party/cares/cares (cares-1_15_0)
0487bbb43c3e8b54c7332f74ba7344d8265774f7 third_party/envoy-api (heads/master)
8dcc476be69437b505af181a6e8b167fdb101d7e third_party/envoy-api (heads/master)
  28f50e0fed19872e0fd50dd23ce2ee8cd759338e third_party/gflags (v2.2.0-5-g30dbc81)
  80ed4d0bbf65d57cc267dfc63bd2584557f11f9b third_party/googleapis (common-protos-1_3_1-915-g80ed4d0bb)
  c9ccac7cb7345901884aabf5d1a786cfa6e2f397 third_party/googletest (6e2f397)
  15ae750151ac9341e5945eb38f8982d59fb99201 third_party/libuv (v1.34.0)
fe1790ca0df67173702f70d5646b82f48f412b99 protobuf (v3.7.0-rc.2-756-gfe1790ca0)
c0a080f4bea50bc087cdd8551143ee538cf3459e third_party/protoc-gen-validate (v0.0.10)
db4b343e48c1264bb4d9ff491b059300701dc7c7 third_party/udpa (heads/master)
678da4f76eb9168c9965afc2149944a66cd48546 third_party/protobuf (v3.12.2)
0f2bc6c0fdac9113e3863ea6e30e5b2bd33e3b40 third_party/protoc-gen-validate (v0.0.10)
e8cd3a4bb307e2c810cffff99f93e96e6d7fee85 third_party/udpa (heads/master)
  cacf7f1d4e3d44d871b605da3b647f07d718623f third_party/zlib (v1.2.11)
 EOF