diff --git a/BUILD b/BUILD index 20b7ed8e86f..f2caa63ed0d 100644 --- a/BUILD +++ b/BUILD @@ -1797,16 +1797,17 @@ grpc_cc_library( "gpr", "grpc_public_hdrs", "grpc_trace", - "orphanable", "ref_counted_ptr", "stats", "//src/core:arena", + "//src/core:call_arena_allocator", "//src/core:channel_args", "//src/core:channel_stack_type", "//src/core:compression", "//src/core:connectivity_state", "//src/core:iomgr_fwd", "//src/core:ref_counted", + "//src/core:resource_quota", "//src/core:slice", "//src/core:stats_data", "//src/core:time", @@ -1885,6 +1886,7 @@ grpc_cc_library( "config", "gpr", "grpc_base", + "grpc_client_channel", "grpc_public_hdrs", "legacy_channel", "ref_counted_ptr", @@ -1892,6 +1894,7 @@ grpc_cc_library( "//src/core:arena", "//src/core:channel_args", "//src/core:channel_stack_type", + "//src/core:experiments", "//src/core:iomgr_fwd", "//src/core:ref_counted", "//src/core:slice", @@ -3698,11 +3701,13 @@ grpc_cc_library( grpc_cc_library( name = "grpc_client_channel", srcs = [ + "//src/core:client_channel/client_channel.cc", "//src/core:client_channel/client_channel_factory.cc", "//src/core:client_channel/client_channel_filter.cc", "//src/core:client_channel/client_channel_plugin.cc", "//src/core:client_channel/dynamic_filters.cc", "//src/core:client_channel/global_subchannel_pool.cc", + "//src/core:client_channel/load_balanced_call_destination.cc", "//src/core:client_channel/local_subchannel_pool.cc", "//src/core:client_channel/retry_filter.cc", "//src/core:client_channel/retry_filter_legacy_call_data.cc", @@ -3710,10 +3715,12 @@ grpc_cc_library( "//src/core:client_channel/subchannel_stream_client.cc", ], hdrs = [ + "//src/core:client_channel/client_channel.h", "//src/core:client_channel/client_channel_factory.h", "//src/core:client_channel/client_channel_filter.h", "//src/core:client_channel/dynamic_filters.h", "//src/core:client_channel/global_subchannel_pool.h", + "//src/core:client_channel/load_balanced_call_destination.h", "//src/core:client_channel/local_subchannel_pool.h", "//src/core:client_channel/retry_filter.h", "//src/core:client_channel/retry_filter_legacy_call_data.h", @@ -3735,21 +3742,17 @@ grpc_cc_library( "absl/strings:cord", "absl/types:optional", "absl/types:variant", - "@com_google_protobuf//upb:base", - "@com_google_protobuf//upb:mem", - "@com_google_protobuf//upb:message", ], language = "c++", visibility = ["@grpc:client_channel"], deps = [ - "api_trace", "backoff", "call_combiner", "call_tracer", + "channel", "channel_arg_names", "channelz", "config", - "config_vars", "debug_location", "endpoint_addresses", "exec_ctx", @@ -3760,26 +3763,23 @@ grpc_cc_library( "grpc_security_base", "grpc_service_config_impl", "grpc_trace", - "http_connect_handshaker", "iomgr", - "iomgr_timer", "lb_child_policy_handler", "legacy_context", "orphanable", - "parse_address", "promise", - "protobuf_duration_upb", "ref_counted_ptr", "sockaddr_utils", "stats", "uri_parser", "work_serializer", - "xds_orca_service_upb", - "xds_orca_upb", "//src/core:activity", "//src/core:arena", "//src/core:arena_promise", "//src/core:backend_metric_parser", + "//src/core:call_destination", + "//src/core:call_filters", + "//src/core:call_spine", "//src/core:cancel_callback", "//src/core:channel_args", "//src/core:channel_fwd", @@ -3793,33 +3793,33 @@ grpc_cc_library( "//src/core:connectivity_state", "//src/core:construct_destruct", "//src/core:context", - "//src/core:delegating_helper", "//src/core:dual_ref_counted", - "//src/core:env", "//src/core:error", "//src/core:error_utils", + "//src/core:exec_ctx_wakeup_scheduler", "//src/core:experiments", - "//src/core:gpr_atm", "//src/core:gpr_manual_constructor", "//src/core:grpc_backend_metric_data", - "//src/core:grpc_message_size_filter", + "//src/core:grpc_channel_idle_filter", "//src/core:grpc_service_config", + "//src/core:idle_filter_state", "//src/core:init_internally", + "//src/core:interception_chain", "//src/core:iomgr_fwd", "//src/core:json", - "//src/core:json_args", - "//src/core:json_channel_args", - "//src/core:json_object_loader", "//src/core:latch", "//src/core:lb_policy", "//src/core:lb_policy_registry", + "//src/core:loop", "//src/core:map", "//src/core:memory_quota", + "//src/core:metadata", "//src/core:metadata_batch", + "//src/core:metrics", + "//src/core:observable", "//src/core:pipe", "//src/core:poll", "//src/core:pollset_set", - "//src/core:proxy_mapper", "//src/core:proxy_mapper_registry", "//src/core:ref_counted", "//src/core:resolved_address", @@ -3827,11 +3827,13 @@ grpc_cc_library( "//src/core:retry_service_config", "//src/core:retry_throttle", "//src/core:seq", - "//src/core:service_config_parser", + "//src/core:single_set_ptr", + "//src/core:sleep", "//src/core:slice", "//src/core:slice_buffer", "//src/core:slice_refcount", "//src/core:stats_data", + "//src/core:status_flag", "//src/core:status_helper", "//src/core:subchannel_connector", "//src/core:subchannel_interface", @@ -3840,7 +3842,6 @@ grpc_cc_library( "//src/core:try_seq", "//src/core:unique_type_name", "//src/core:useful", - "//src/core:validation_errors", ], ) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f5c39bfda8..64da739cd32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1002,7 +1002,9 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx client_authority_filter_test) add_dependencies(buildtests_cxx client_callback_end2end_test) add_dependencies(buildtests_cxx client_channel_service_config_test) - add_dependencies(buildtests_cxx client_channel_test) + if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) + add_dependencies(buildtests_cxx client_channel_test) + endif() add_dependencies(buildtests_cxx client_context_test_peer_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx client_fork_test) @@ -1026,6 +1028,9 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx compressed_payload_test) add_dependencies(buildtests_cxx compression_test) add_dependencies(buildtests_cxx concurrent_connectivity_test) + if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) + add_dependencies(buildtests_cxx connected_subchannel_test) + endif() add_dependencies(buildtests_cxx connection_prefix_bad_client_test) add_dependencies(buildtests_cxx connection_refused_test) add_dependencies(buildtests_cxx connectivity_state_test) @@ -1194,6 +1199,9 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx latch_test) add_dependencies(buildtests_cxx lb_get_cpu_stats_test) add_dependencies(buildtests_cxx lb_load_data_store_test) + if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) + add_dependencies(buildtests_cxx load_balanced_call_destination_test) + endif() add_dependencies(buildtests_cxx load_config_test) add_dependencies(buildtests_cxx load_file_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) @@ -1436,6 +1444,7 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx streams_not_seen_test) add_dependencies(buildtests_cxx string_ref_test) add_dependencies(buildtests_cxx string_test) + add_dependencies(buildtests_cxx subchannel_args_test) add_dependencies(buildtests_cxx switch_test) add_dependencies(buildtests_cxx sync_test) add_dependencies(buildtests_cxx system_roots_test) @@ -1830,6 +1839,7 @@ add_library(grpc src/core/channelz/channelz.cc src/core/channelz/channelz_registry.cc src/core/client_channel/backup_poller.cc + src/core/client_channel/client_channel.cc src/core/client_channel/client_channel_factory.cc src/core/client_channel/client_channel_filter.cc src/core/client_channel/client_channel_plugin.cc @@ -1837,6 +1847,7 @@ add_library(grpc src/core/client_channel/config_selector.cc src/core/client_channel/dynamic_filters.cc src/core/client_channel/global_subchannel_pool.cc + src/core/client_channel/load_balanced_call_destination.cc src/core/client_channel/local_subchannel_pool.cc src/core/client_channel/retry_filter.cc src/core/client_channel/retry_filter_legacy_call_data.cc @@ -2292,6 +2303,7 @@ add_library(grpc src/core/lib/event_engine/work_queue/basic_work_queue.cc src/core/lib/experiments/config.cc src/core/lib/experiments/experiments.cc + src/core/lib/gprpp/dump_args.cc src/core/lib/gprpp/load_file.cc src/core/lib/gprpp/per_cpu.cc src/core/lib/gprpp/posix/directory_reader.cc @@ -2927,6 +2939,7 @@ add_library(grpc_unsecure src/core/channelz/channelz.cc src/core/channelz/channelz_registry.cc src/core/client_channel/backup_poller.cc + src/core/client_channel/client_channel.cc src/core/client_channel/client_channel_factory.cc src/core/client_channel/client_channel_filter.cc src/core/client_channel/client_channel_plugin.cc @@ -2934,6 +2947,7 @@ add_library(grpc_unsecure src/core/client_channel/config_selector.cc src/core/client_channel/dynamic_filters.cc src/core/client_channel/global_subchannel_pool.cc + src/core/client_channel/load_balanced_call_destination.cc src/core/client_channel/local_subchannel_pool.cc src/core/client_channel/retry_filter.cc src/core/client_channel/retry_filter_legacy_call_data.cc @@ -3085,6 +3099,7 @@ add_library(grpc_unsecure src/core/lib/event_engine/work_queue/basic_work_queue.cc src/core/lib/experiments/config.cc src/core/lib/experiments/experiments.cc + src/core/lib/gprpp/dump_args.cc src/core/lib/gprpp/load_file.cc src/core/lib/gprpp/per_cpu.cc src/core/lib/gprpp/ref_counted_string.cc @@ -5203,6 +5218,7 @@ add_library(grpc_authorization_provider src/core/lib/event_engine/work_queue/basic_work_queue.cc src/core/lib/experiments/config.cc src/core/lib/experiments/experiments.cc + src/core/lib/gprpp/dump_args.cc src/core/lib/gprpp/load_file.cc src/core/lib/gprpp/per_cpu.cc src/core/lib/gprpp/ref_counted_string.cc @@ -8506,6 +8522,7 @@ add_executable(call_filters_test src/core/lib/debug/trace.cc src/core/lib/experiments/config.cc src/core/lib/experiments/experiments.cc + src/core/lib/gprpp/dump_args.cc src/core/lib/gprpp/ref_counted_string.cc src/core/lib/gprpp/status_helper.cc src/core/lib/gprpp/time.cc @@ -10526,46 +10543,56 @@ target_link_libraries(client_channel_service_config_test endif() if(gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) -add_executable(client_channel_test - test/core/client_channel/client_channel_test.cc -) -if(WIN32 AND MSVC) - if(BUILD_SHARED_LIBS) - target_compile_definitions(client_channel_test - PRIVATE - "GPR_DLL_IMPORTS" - "GRPC_DLL_IMPORTS" - ) + add_executable(client_channel_test + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.cc + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.h + test/core/call/yodel/test_main.cc + test/core/call/yodel/yodel_test.cc + test/core/client_channel/client_channel_test.cc + test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc + ) + if(WIN32 AND MSVC) + if(BUILD_SHARED_LIBS) + target_compile_definitions(client_channel_test + PRIVATE + "GPR_DLL_IMPORTS" + "GRPC_DLL_IMPORTS" + ) + endif() endif() -endif() -target_compile_features(client_channel_test PUBLIC cxx_std_14) -target_include_directories(client_channel_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_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_compile_features(client_channel_test PUBLIC cxx_std_14) + target_include_directories(client_channel_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_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(client_channel_test - ${_gRPC_ALLTARGETS_LIBRARIES} - gtest - grpc_test_util -) + target_link_libraries(client_channel_test + ${_gRPC_ALLTARGETS_LIBRARIES} + gtest + ${_gRPC_PROTOBUF_LIBRARIES} + grpc_test_util + ) +endif() endif() if(gRPC_BUILD_TESTS) @@ -11340,6 +11367,58 @@ target_link_libraries(concurrent_connectivity_test ) +endif() +if(gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) + + add_executable(connected_subchannel_test + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.cc + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.h + test/core/call/yodel/test_main.cc + test/core/call/yodel/yodel_test.cc + test/core/client_channel/connected_subchannel_test.cc + test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc + ) + if(WIN32 AND MSVC) + if(BUILD_SHARED_LIBS) + target_compile_definitions(connected_subchannel_test + PRIVATE + "GPR_DLL_IMPORTS" + "GRPC_DLL_IMPORTS" + ) + endif() + endif() + target_compile_features(connected_subchannel_test PUBLIC cxx_std_14) + target_include_directories(connected_subchannel_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_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(connected_subchannel_test + ${_gRPC_ALLTARGETS_LIBRARIES} + gtest + ${_gRPC_PROTOBUF_LIBRARIES} + grpc_test_util + ) + + +endif() endif() if(gRPC_BUILD_TESTS) @@ -17832,6 +17911,7 @@ add_executable(interception_chain_test src/core/lib/event_engine/work_queue/basic_work_queue.cc src/core/lib/experiments/config.cc src/core/lib/experiments/experiments.cc + src/core/lib/gprpp/dump_args.cc src/core/lib/gprpp/load_file.cc src/core/lib/gprpp/per_cpu.cc src/core/lib/gprpp/ref_counted_string.cc @@ -18985,6 +19065,58 @@ target_link_libraries(lb_load_data_store_test ) +endif() +if(gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) + + add_executable(load_balanced_call_destination_test + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.cc + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h + ${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.h + test/core/call/yodel/test_main.cc + test/core/call/yodel/yodel_test.cc + test/core/client_channel/load_balanced_call_destination_test.cc + test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc + ) + if(WIN32 AND MSVC) + if(BUILD_SHARED_LIBS) + target_compile_definitions(load_balanced_call_destination_test + PRIVATE + "GPR_DLL_IMPORTS" + "GRPC_DLL_IMPORTS" + ) + endif() + endif() + target_compile_features(load_balanced_call_destination_test PUBLIC cxx_std_14) + target_include_directories(load_balanced_call_destination_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_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(load_balanced_call_destination_test + ${_gRPC_ALLTARGETS_LIBRARIES} + gtest + ${_gRPC_PROTOBUF_LIBRARIES} + grpc_test_util + ) + + +endif() endif() if(gRPC_BUILD_TESTS) @@ -29324,6 +29456,48 @@ target_link_libraries(string_test ) +endif() +if(gRPC_BUILD_TESTS) + +add_executable(subchannel_args_test + test/core/client_channel/subchannel_args_test.cc +) +if(WIN32 AND MSVC) + if(BUILD_SHARED_LIBS) + target_compile_definitions(subchannel_args_test + PRIVATE + "GPR_DLL_IMPORTS" + "GRPC_DLL_IMPORTS" + ) + endif() +endif() +target_compile_features(subchannel_args_test PUBLIC cxx_std_14) +target_include_directories(subchannel_args_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_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(subchannel_args_test + ${_gRPC_ALLTARGETS_LIBRARIES} + gtest + grpc_test_util +) + + endif() if(gRPC_BUILD_TESTS) diff --git a/Makefile b/Makefile index 2171dd14b33..fc3701d0415 100644 --- a/Makefile +++ b/Makefile @@ -670,6 +670,7 @@ LIBGRPC_SRC = \ src/core/channelz/channelz.cc \ src/core/channelz/channelz_registry.cc \ src/core/client_channel/backup_poller.cc \ + src/core/client_channel/client_channel.cc \ src/core/client_channel/client_channel_factory.cc \ src/core/client_channel/client_channel_filter.cc \ src/core/client_channel/client_channel_plugin.cc \ @@ -677,6 +678,7 @@ LIBGRPC_SRC = \ src/core/client_channel/config_selector.cc \ src/core/client_channel/dynamic_filters.cc \ src/core/client_channel/global_subchannel_pool.cc \ + src/core/client_channel/load_balanced_call_destination.cc \ src/core/client_channel/local_subchannel_pool.cc \ src/core/client_channel/retry_filter.cc \ src/core/client_channel/retry_filter_legacy_call_data.cc \ @@ -1137,6 +1139,7 @@ LIBGRPC_SRC = \ src/core/lib/experiments/config.cc \ src/core/lib/experiments/experiments.cc \ src/core/lib/gprpp/crash.cc \ + src/core/lib/gprpp/dump_args.cc \ src/core/lib/gprpp/examine_stack.cc \ src/core/lib/gprpp/fork.cc \ src/core/lib/gprpp/host_port.cc \ diff --git a/Package.swift b/Package.swift index 6f315ad9c90..6b411d73c85 100644 --- a/Package.swift +++ b/Package.swift @@ -126,6 +126,8 @@ let package = Package( "src/core/channelz/channelz_registry.h", "src/core/client_channel/backup_poller.cc", "src/core/client_channel/backup_poller.h", + "src/core/client_channel/client_channel.cc", + "src/core/client_channel/client_channel.h", "src/core/client_channel/client_channel_factory.cc", "src/core/client_channel/client_channel_factory.h", "src/core/client_channel/client_channel_filter.cc", @@ -141,6 +143,8 @@ let package = Package( "src/core/client_channel/dynamic_filters.h", "src/core/client_channel/global_subchannel_pool.cc", "src/core/client_channel/global_subchannel_pool.h", + "src/core/client_channel/load_balanced_call_destination.cc", + "src/core/client_channel/load_balanced_call_destination.h", "src/core/client_channel/local_subchannel_pool.cc", "src/core/client_channel/local_subchannel_pool.h", "src/core/client_channel/retry_filter.cc", @@ -1255,6 +1259,8 @@ let package = Package( "src/core/lib/gprpp/directory_reader.h", "src/core/lib/gprpp/down_cast.h", "src/core/lib/gprpp/dual_ref_counted.h", + "src/core/lib/gprpp/dump_args.cc", + "src/core/lib/gprpp/dump_args.h", "src/core/lib/gprpp/env.h", "src/core/lib/gprpp/examine_stack.cc", "src/core/lib/gprpp/examine_stack.h", @@ -1480,6 +1486,7 @@ let package = Package( "src/core/lib/promise/latch.h", "src/core/lib/promise/loop.h", "src/core/lib/promise/map.h", + "src/core/lib/promise/observable.h", "src/core/lib/promise/party.cc", "src/core/lib/promise/party.h", "src/core/lib/promise/pipe.h", diff --git a/bazel/experiments.bzl b/bazel/experiments.bzl index 7b41b29566a..8dffc68bf21 100644 --- a/bazel/experiments.bzl +++ b/bazel/experiments.bzl @@ -18,7 +18,6 @@ EXPERIMENT_ENABLES = { "call_status_override_on_cancellation": "call_status_override_on_cancellation", - "call_v3": "call_v3", "canary_client_privacy": "canary_client_privacy", "client_privacy": "client_privacy", "event_engine_client": "event_engine_client", @@ -45,6 +44,7 @@ EXPERIMENT_ENABLES = { "unconstrained_max_quota_buffer_size": "unconstrained_max_quota_buffer_size", "work_serializer_clears_time_cache": "work_serializer_clears_time_cache", "work_serializer_dispatch": "event_engine_client,work_serializer_dispatch", + "call_v3": "call_v3,event_engine_client,event_engine_listener,work_serializer_dispatch", } EXPERIMENT_POLLERS = [ diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index b2a80770454..3adafd444e6 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -227,6 +227,7 @@ libs: - src/core/channelz/channelz.h - src/core/channelz/channelz_registry.h - src/core/client_channel/backup_poller.h + - src/core/client_channel/client_channel.h - src/core/client_channel/client_channel_factory.h - src/core/client_channel/client_channel_filter.h - src/core/client_channel/client_channel_internal.h @@ -235,6 +236,7 @@ libs: - src/core/client_channel/connector.h - src/core/client_channel/dynamic_filters.h - src/core/client_channel/global_subchannel_pool.h + - src/core/client_channel/load_balanced_call_destination.h - src/core/client_channel/local_subchannel_pool.h - src/core/client_channel/retry_filter.h - src/core/client_channel/retry_filter_legacy_call_data.h @@ -883,6 +885,7 @@ libs: - src/core/lib/gprpp/directory_reader.h - src/core/lib/gprpp/down_cast.h - src/core/lib/gprpp/dual_ref_counted.h + - src/core/lib/gprpp/dump_args.h - src/core/lib/gprpp/if_list.h - src/core/lib/gprpp/load_file.h - src/core/lib/gprpp/manual_constructor.h @@ -991,6 +994,7 @@ libs: - src/core/lib/promise/latch.h - src/core/lib/promise/loop.h - src/core/lib/promise/map.h + - src/core/lib/promise/observable.h - src/core/lib/promise/party.h - src/core/lib/promise/pipe.h - src/core/lib/promise/poll.h @@ -1251,6 +1255,7 @@ libs: - src/core/channelz/channelz.cc - src/core/channelz/channelz_registry.cc - src/core/client_channel/backup_poller.cc + - src/core/client_channel/client_channel.cc - src/core/client_channel/client_channel_factory.cc - src/core/client_channel/client_channel_filter.cc - src/core/client_channel/client_channel_plugin.cc @@ -1258,6 +1263,7 @@ libs: - src/core/client_channel/config_selector.cc - src/core/client_channel/dynamic_filters.cc - src/core/client_channel/global_subchannel_pool.cc + - src/core/client_channel/load_balanced_call_destination.cc - src/core/client_channel/local_subchannel_pool.cc - src/core/client_channel/retry_filter.cc - src/core/client_channel/retry_filter_legacy_call_data.cc @@ -1713,6 +1719,7 @@ libs: - src/core/lib/event_engine/work_queue/basic_work_queue.cc - src/core/lib/experiments/config.cc - src/core/lib/experiments/experiments.cc + - src/core/lib/gprpp/dump_args.cc - src/core/lib/gprpp/load_file.cc - src/core/lib/gprpp/per_cpu.cc - src/core/lib/gprpp/posix/directory_reader.cc @@ -2215,6 +2222,7 @@ libs: - src/core/channelz/channelz.h - src/core/channelz/channelz_registry.h - src/core/client_channel/backup_poller.h + - src/core/client_channel/client_channel.h - src/core/client_channel/client_channel_factory.h - src/core/client_channel/client_channel_filter.h - src/core/client_channel/client_channel_internal.h @@ -2223,6 +2231,7 @@ libs: - src/core/client_channel/connector.h - src/core/client_channel/dynamic_filters.h - src/core/client_channel/global_subchannel_pool.h + - src/core/client_channel/load_balanced_call_destination.h - src/core/client_channel/local_subchannel_pool.h - src/core/client_channel/retry_filter.h - src/core/client_channel/retry_filter_legacy_call_data.h @@ -2420,6 +2429,7 @@ libs: - src/core/lib/gprpp/cpp_impl_of.h - src/core/lib/gprpp/down_cast.h - src/core/lib/gprpp/dual_ref_counted.h + - src/core/lib/gprpp/dump_args.h - src/core/lib/gprpp/if_list.h - src/core/lib/gprpp/load_file.h - src/core/lib/gprpp/manual_constructor.h @@ -2526,6 +2536,7 @@ libs: - src/core/lib/promise/latch.h - src/core/lib/promise/loop.h - src/core/lib/promise/map.h + - src/core/lib/promise/observable.h - src/core/lib/promise/party.h - src/core/lib/promise/pipe.h - src/core/lib/promise/poll.h @@ -2708,6 +2719,7 @@ libs: - src/core/channelz/channelz.cc - src/core/channelz/channelz_registry.cc - src/core/client_channel/backup_poller.cc + - src/core/client_channel/client_channel.cc - src/core/client_channel/client_channel_factory.cc - src/core/client_channel/client_channel_filter.cc - src/core/client_channel/client_channel_plugin.cc @@ -2715,6 +2727,7 @@ libs: - src/core/client_channel/config_selector.cc - src/core/client_channel/dynamic_filters.cc - src/core/client_channel/global_subchannel_pool.cc + - src/core/client_channel/load_balanced_call_destination.cc - src/core/client_channel/local_subchannel_pool.cc - src/core/client_channel/retry_filter.cc - src/core/client_channel/retry_filter_legacy_call_data.cc @@ -2866,6 +2879,7 @@ libs: - src/core/lib/event_engine/work_queue/basic_work_queue.cc - src/core/lib/experiments/config.cc - src/core/lib/experiments/experiments.cc + - src/core/lib/gprpp/dump_args.cc - src/core/lib/gprpp/load_file.cc - src/core/lib/gprpp/per_cpu.cc - src/core/lib/gprpp/ref_counted_string.cc @@ -4510,6 +4524,7 @@ libs: - src/core/lib/gprpp/cpp_impl_of.h - src/core/lib/gprpp/down_cast.h - src/core/lib/gprpp/dual_ref_counted.h + - src/core/lib/gprpp/dump_args.h - src/core/lib/gprpp/if_list.h - src/core/lib/gprpp/load_file.h - src/core/lib/gprpp/manual_constructor.h @@ -4618,6 +4633,7 @@ libs: - src/core/lib/promise/party.h - src/core/lib/promise/pipe.h - src/core/lib/promise/poll.h + - src/core/lib/promise/prioritized_race.h - src/core/lib/promise/promise.h - src/core/lib/promise/race.h - src/core/lib/promise/seq.h @@ -4833,6 +4849,7 @@ libs: - src/core/lib/event_engine/work_queue/basic_work_queue.cc - src/core/lib/experiments/config.cc - src/core/lib/experiments/experiments.cc + - src/core/lib/gprpp/dump_args.cc - src/core/lib/gprpp/load_file.cc - src/core/lib/gprpp/per_cpu.cc - src/core/lib/gprpp/ref_counted_string.cc @@ -6378,6 +6395,7 @@ targets: - src/core/lib/gprpp/chunked_vector.h - src/core/lib/gprpp/down_cast.h - src/core/lib/gprpp/dual_ref_counted.h + - src/core/lib/gprpp/dump_args.h - src/core/lib/gprpp/if_list.h - src/core/lib/gprpp/manual_constructor.h - src/core/lib/gprpp/orphanable.h @@ -6468,6 +6486,7 @@ targets: - src/core/lib/debug/trace.cc - src/core/lib/experiments/config.cc - src/core/lib/experiments/experiments.cc + - src/core/lib/gprpp/dump_args.cc - src/core/lib/gprpp/ref_counted_string.cc - src/core/lib/gprpp/status_helper.cc - src/core/lib/gprpp/time.cc @@ -7869,12 +7888,22 @@ targets: gtest: true build: test language: c++ - headers: [] + headers: + - test/core/call/yodel/yodel_test.h + - test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h src: + - test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.proto + - test/core/call/yodel/test_main.cc + - test/core/call/yodel/yodel_test.cc - test/core/client_channel/client_channel_test.cc + - test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc deps: - gtest + - protobuf - grpc_test_util + platforms: + - linux + - posix uses_polling: false - name: client_context_test_peer_test gtest: true @@ -8225,6 +8254,27 @@ targets: deps: - gtest - grpc_test_util +- name: connected_subchannel_test + gtest: true + build: test + language: c++ + headers: + - test/core/call/yodel/yodel_test.h + - test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h + src: + - test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.proto + - test/core/call/yodel/test_main.cc + - test/core/call/yodel/yodel_test.cc + - test/core/client_channel/connected_subchannel_test.cc + - test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc + deps: + - gtest + - protobuf + - grpc_test_util + platforms: + - linux + - posix + uses_polling: false - name: connection_prefix_bad_client_test gtest: true build: test @@ -11669,6 +11719,7 @@ targets: - src/core/lib/gprpp/cpp_impl_of.h - src/core/lib/gprpp/down_cast.h - src/core/lib/gprpp/dual_ref_counted.h + - src/core/lib/gprpp/dump_args.h - src/core/lib/gprpp/if_list.h - src/core/lib/gprpp/load_file.h - src/core/lib/gprpp/manual_constructor.h @@ -11776,6 +11827,7 @@ targets: - src/core/lib/promise/party.h - src/core/lib/promise/pipe.h - src/core/lib/promise/poll.h + - src/core/lib/promise/prioritized_race.h - src/core/lib/promise/promise.h - src/core/lib/promise/race.h - src/core/lib/promise/seq.h @@ -11961,6 +12013,7 @@ targets: - src/core/lib/event_engine/work_queue/basic_work_queue.cc - src/core/lib/experiments/config.cc - src/core/lib/experiments/experiments.cc + - src/core/lib/gprpp/dump_args.cc - src/core/lib/gprpp/load_file.cc - src/core/lib/gprpp/per_cpu.cc - src/core/lib/gprpp/ref_counted_string.cc @@ -12733,6 +12786,27 @@ targets: - gtest - grpc++ - grpc_test_util +- name: load_balanced_call_destination_test + gtest: true + build: test + language: c++ + headers: + - test/core/call/yodel/yodel_test.h + - test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h + src: + - test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.proto + - test/core/call/yodel/test_main.cc + - test/core/call/yodel/yodel_test.cc + - test/core/client_channel/load_balanced_call_destination_test.cc + - test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc + deps: + - gtest + - protobuf + - grpc_test_util + platforms: + - linux + - posix + uses_polling: false - name: load_config_test gtest: true build: test @@ -14639,6 +14713,7 @@ targets: - src/core/lib/promise/map.h - src/core/lib/promise/poll.h - src/core/lib/promise/promise.h + - test/core/promise/poll_matcher.h src: - test/core/promise/map_test.cc deps: @@ -18993,6 +19068,17 @@ targets: - gtest - grpc_test_util uses_polling: false +- name: subchannel_args_test + gtest: true + build: test + language: c++ + headers: [] + src: + - test/core/client_channel/subchannel_args_test.cc + deps: + - gtest + - grpc_test_util + uses_polling: false - name: switch_test gtest: true build: test diff --git a/config.m4 b/config.m4 index bcb4312e054..695063579c5 100644 --- a/config.m4 +++ b/config.m4 @@ -45,6 +45,7 @@ if test "$PHP_GRPC" != "no"; then src/core/channelz/channelz.cc \ src/core/channelz/channelz_registry.cc \ src/core/client_channel/backup_poller.cc \ + src/core/client_channel/client_channel.cc \ src/core/client_channel/client_channel_factory.cc \ src/core/client_channel/client_channel_filter.cc \ src/core/client_channel/client_channel_plugin.cc \ @@ -52,6 +53,7 @@ if test "$PHP_GRPC" != "no"; then src/core/client_channel/config_selector.cc \ src/core/client_channel/dynamic_filters.cc \ src/core/client_channel/global_subchannel_pool.cc \ + src/core/client_channel/load_balanced_call_destination.cc \ src/core/client_channel/local_subchannel_pool.cc \ src/core/client_channel/retry_filter.cc \ src/core/client_channel/retry_filter_legacy_call_data.cc \ @@ -512,6 +514,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/experiments/config.cc \ src/core/lib/experiments/experiments.cc \ src/core/lib/gprpp/crash.cc \ + src/core/lib/gprpp/dump_args.cc \ src/core/lib/gprpp/examine_stack.cc \ src/core/lib/gprpp/fork.cc \ src/core/lib/gprpp/host_port.cc \ diff --git a/config.w32 b/config.w32 index 08d8febee55..85a32dc6704 100644 --- a/config.w32 +++ b/config.w32 @@ -10,6 +10,7 @@ if (PHP_GRPC != "no") { "src\\core\\channelz\\channelz.cc " + "src\\core\\channelz\\channelz_registry.cc " + "src\\core\\client_channel\\backup_poller.cc " + + "src\\core\\client_channel\\client_channel.cc " + "src\\core\\client_channel\\client_channel_factory.cc " + "src\\core\\client_channel\\client_channel_filter.cc " + "src\\core\\client_channel\\client_channel_plugin.cc " + @@ -17,6 +18,7 @@ if (PHP_GRPC != "no") { "src\\core\\client_channel\\config_selector.cc " + "src\\core\\client_channel\\dynamic_filters.cc " + "src\\core\\client_channel\\global_subchannel_pool.cc " + + "src\\core\\client_channel\\load_balanced_call_destination.cc " + "src\\core\\client_channel\\local_subchannel_pool.cc " + "src\\core\\client_channel\\retry_filter.cc " + "src\\core\\client_channel\\retry_filter_legacy_call_data.cc " + @@ -477,6 +479,7 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\experiments\\config.cc " + "src\\core\\lib\\experiments\\experiments.cc " + "src\\core\\lib\\gprpp\\crash.cc " + + "src\\core\\lib\\gprpp\\dump_args.cc " + "src\\core\\lib\\gprpp\\examine_stack.cc " + "src\\core\\lib\\gprpp\\fork.cc " + "src\\core\\lib\\gprpp\\host_port.cc " + diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 5865f399235..90a2f3849fc 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -268,6 +268,7 @@ Pod::Spec.new do |s| 'src/core/channelz/channelz.h', 'src/core/channelz/channelz_registry.h', 'src/core/client_channel/backup_poller.h', + 'src/core/client_channel/client_channel.h', 'src/core/client_channel/client_channel_factory.h', 'src/core/client_channel/client_channel_filter.h', 'src/core/client_channel/client_channel_internal.h', @@ -276,6 +277,7 @@ Pod::Spec.new do |s| 'src/core/client_channel/connector.h', 'src/core/client_channel/dynamic_filters.h', 'src/core/client_channel/global_subchannel_pool.h', + 'src/core/client_channel/load_balanced_call_destination.h', 'src/core/client_channel/local_subchannel_pool.h', 'src/core/client_channel/retry_filter.h', 'src/core/client_channel/retry_filter_legacy_call_data.h', @@ -968,6 +970,7 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/directory_reader.h', 'src/core/lib/gprpp/down_cast.h', 'src/core/lib/gprpp/dual_ref_counted.h', + 'src/core/lib/gprpp/dump_args.h', 'src/core/lib/gprpp/env.h', 'src/core/lib/gprpp/examine_stack.h', 'src/core/lib/gprpp/fork.h', @@ -1089,6 +1092,7 @@ Pod::Spec.new do |s| 'src/core/lib/promise/latch.h', 'src/core/lib/promise/loop.h', 'src/core/lib/promise/map.h', + 'src/core/lib/promise/observable.h', 'src/core/lib/promise/party.h', 'src/core/lib/promise/pipe.h', 'src/core/lib/promise/poll.h', @@ -1557,6 +1561,7 @@ Pod::Spec.new do |s| 'src/core/channelz/channelz.h', 'src/core/channelz/channelz_registry.h', 'src/core/client_channel/backup_poller.h', + 'src/core/client_channel/client_channel.h', 'src/core/client_channel/client_channel_factory.h', 'src/core/client_channel/client_channel_filter.h', 'src/core/client_channel/client_channel_internal.h', @@ -1565,6 +1570,7 @@ Pod::Spec.new do |s| 'src/core/client_channel/connector.h', 'src/core/client_channel/dynamic_filters.h', 'src/core/client_channel/global_subchannel_pool.h', + 'src/core/client_channel/load_balanced_call_destination.h', 'src/core/client_channel/local_subchannel_pool.h', 'src/core/client_channel/retry_filter.h', 'src/core/client_channel/retry_filter_legacy_call_data.h', @@ -2239,6 +2245,7 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/directory_reader.h', 'src/core/lib/gprpp/down_cast.h', 'src/core/lib/gprpp/dual_ref_counted.h', + 'src/core/lib/gprpp/dump_args.h', 'src/core/lib/gprpp/env.h', 'src/core/lib/gprpp/examine_stack.h', 'src/core/lib/gprpp/fork.h', @@ -2360,6 +2367,7 @@ Pod::Spec.new do |s| 'src/core/lib/promise/latch.h', 'src/core/lib/promise/loop.h', 'src/core/lib/promise/map.h', + 'src/core/lib/promise/observable.h', 'src/core/lib/promise/party.h', 'src/core/lib/promise/pipe.h', 'src/core/lib/promise/poll.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 032a6bb22ff..a8cc8fdda1f 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -245,6 +245,8 @@ Pod::Spec.new do |s| 'src/core/channelz/channelz_registry.h', 'src/core/client_channel/backup_poller.cc', 'src/core/client_channel/backup_poller.h', + 'src/core/client_channel/client_channel.cc', + 'src/core/client_channel/client_channel.h', 'src/core/client_channel/client_channel_factory.cc', 'src/core/client_channel/client_channel_factory.h', 'src/core/client_channel/client_channel_filter.cc', @@ -260,6 +262,8 @@ Pod::Spec.new do |s| 'src/core/client_channel/dynamic_filters.h', 'src/core/client_channel/global_subchannel_pool.cc', 'src/core/client_channel/global_subchannel_pool.h', + 'src/core/client_channel/load_balanced_call_destination.cc', + 'src/core/client_channel/load_balanced_call_destination.h', 'src/core/client_channel/local_subchannel_pool.cc', 'src/core/client_channel/local_subchannel_pool.h', 'src/core/client_channel/retry_filter.cc', @@ -1374,6 +1378,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/directory_reader.h', 'src/core/lib/gprpp/down_cast.h', 'src/core/lib/gprpp/dual_ref_counted.h', + 'src/core/lib/gprpp/dump_args.cc', + 'src/core/lib/gprpp/dump_args.h', 'src/core/lib/gprpp/env.h', 'src/core/lib/gprpp/examine_stack.cc', 'src/core/lib/gprpp/examine_stack.h', @@ -1599,6 +1605,7 @@ Pod::Spec.new do |s| 'src/core/lib/promise/latch.h', 'src/core/lib/promise/loop.h', 'src/core/lib/promise/map.h', + 'src/core/lib/promise/observable.h', 'src/core/lib/promise/party.cc', 'src/core/lib/promise/party.h', 'src/core/lib/promise/pipe.h', @@ -2357,6 +2364,7 @@ Pod::Spec.new do |s| 'src/core/channelz/channelz.h', 'src/core/channelz/channelz_registry.h', 'src/core/client_channel/backup_poller.h', + 'src/core/client_channel/client_channel.h', 'src/core/client_channel/client_channel_factory.h', 'src/core/client_channel/client_channel_filter.h', 'src/core/client_channel/client_channel_internal.h', @@ -2365,6 +2373,7 @@ Pod::Spec.new do |s| 'src/core/client_channel/connector.h', 'src/core/client_channel/dynamic_filters.h', 'src/core/client_channel/global_subchannel_pool.h', + 'src/core/client_channel/load_balanced_call_destination.h', 'src/core/client_channel/local_subchannel_pool.h', 'src/core/client_channel/retry_filter.h', 'src/core/client_channel/retry_filter_legacy_call_data.h', @@ -3019,6 +3028,7 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/directory_reader.h', 'src/core/lib/gprpp/down_cast.h', 'src/core/lib/gprpp/dual_ref_counted.h', + 'src/core/lib/gprpp/dump_args.h', 'src/core/lib/gprpp/env.h', 'src/core/lib/gprpp/examine_stack.h', 'src/core/lib/gprpp/fork.h', @@ -3140,6 +3150,7 @@ Pod::Spec.new do |s| 'src/core/lib/promise/latch.h', 'src/core/lib/promise/loop.h', 'src/core/lib/promise/map.h', + 'src/core/lib/promise/observable.h', 'src/core/lib/promise/party.h', 'src/core/lib/promise/pipe.h', 'src/core/lib/promise/poll.h', diff --git a/grpc.gemspec b/grpc.gemspec index 5ce01c4fd1b..5b919662d11 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -132,6 +132,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/channelz/channelz_registry.h ) s.files += %w( src/core/client_channel/backup_poller.cc ) s.files += %w( src/core/client_channel/backup_poller.h ) + s.files += %w( src/core/client_channel/client_channel.cc ) + s.files += %w( src/core/client_channel/client_channel.h ) s.files += %w( src/core/client_channel/client_channel_factory.cc ) s.files += %w( src/core/client_channel/client_channel_factory.h ) s.files += %w( src/core/client_channel/client_channel_filter.cc ) @@ -147,6 +149,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/client_channel/dynamic_filters.h ) s.files += %w( src/core/client_channel/global_subchannel_pool.cc ) s.files += %w( src/core/client_channel/global_subchannel_pool.h ) + s.files += %w( src/core/client_channel/load_balanced_call_destination.cc ) + s.files += %w( src/core/client_channel/load_balanced_call_destination.h ) s.files += %w( src/core/client_channel/local_subchannel_pool.cc ) s.files += %w( src/core/client_channel/local_subchannel_pool.h ) s.files += %w( src/core/client_channel/retry_filter.cc ) @@ -1261,6 +1265,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/gprpp/directory_reader.h ) s.files += %w( src/core/lib/gprpp/down_cast.h ) s.files += %w( src/core/lib/gprpp/dual_ref_counted.h ) + s.files += %w( src/core/lib/gprpp/dump_args.cc ) + s.files += %w( src/core/lib/gprpp/dump_args.h ) s.files += %w( src/core/lib/gprpp/env.h ) s.files += %w( src/core/lib/gprpp/examine_stack.cc ) s.files += %w( src/core/lib/gprpp/examine_stack.h ) @@ -1486,6 +1492,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/promise/latch.h ) s.files += %w( src/core/lib/promise/loop.h ) s.files += %w( src/core/lib/promise/map.h ) + s.files += %w( src/core/lib/promise/observable.h ) s.files += %w( src/core/lib/promise/party.cc ) s.files += %w( src/core/lib/promise/party.h ) s.files += %w( src/core/lib/promise/pipe.h ) diff --git a/grpc.gyp b/grpc.gyp new file mode 100644 index 00000000000..2327e4ad03a --- /dev/null +++ b/grpc.gyp @@ -0,0 +1,2669 @@ +# GRPC GYP build file + +# This file has been automatically generated from a template file. +# Please look at the templates directory instead. +# This file can be regenerated from the template by running +# tools/buildgen/generate_projects.sh + +# 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. + +{ + 'variables': { + # The openssl and zlib dependencies must be passed in as variables + # defined in an included gypi file, usually common.gypi. + 'openssl_gyp_target%': 'Please Define openssl_gyp_target variable', + 'zlib_gyp_target%': 'Please Define zlib_gyp_target variable', + + 'grpc_gcov%': 'false', + 'grpc_alpine%': 'false', + }, + 'target_defaults': { + 'configurations': { + 'Debug': { + 'cflags': [ + '-O0', + ], + 'defines': [ + '_DEBUG', + 'DEBUG', + ], + }, + 'Release': { + 'cflags': [ + '-O2', + '-Wframe-larger-than=16384', + ], + 'defines': [ + 'NDEBUG', + ], + }, + }, + 'cflags': [ + '-g', + '-Wall', + '-Wextra', + '-DOSATOMIC_USE_INLINED=1', + '-Ithird_party/abseil-cpp', + '-Ithird_party/re2', + '-Ithird_party/upb', + '-Isrc/core/ext/upb-gen', + '-Isrc/core/ext/upbdefs-gen', + '-Ithird_party/utf8_range', + '-Ithird_party/xxhash', + ], + 'ldflags': [ + '-g', + ], + 'cflags_c': [ + '-Werror', + '-std=c11', + ], + 'cflags_cc': [ + '-Werror', + '-std=c++14', + ], + 'include_dirs': [ + '.', + '../..', + 'include', + ], + 'defines': [ + 'GRPC_ARES=0', + ], + 'dependencies': [ + '<(openssl_gyp_target)', + '<(zlib_gyp_target)', + ], + 'conditions': [ + ['grpc_gcov=="true"', { + 'cflags': [ + '-O0', + '-fprofile-arcs', + '-ftest-coverage', + '-Wno-return-type', + ], + 'defines': [ + '_DEBUG', + 'DEBUG', + 'GPR_GCOV', + ], + 'ldflags': [ + '-fprofile-arcs', + '-ftest-coverage', + '-rdynamic', + '-lstdc++', + ], + }], + ['grpc_alpine=="true"', { + 'defines': [ + 'GPR_MUSL_LIBC_COMPAT' + ] + }], + ['OS == "win"', { + 'defines': [ + '_WIN32_WINNT=0x0600', + 'WIN32_LEAN_AND_MEAN', + '_HAS_EXCEPTIONS=0', + 'UNICODE', + '_UNICODE', + 'NOMINMAX', + ], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': 1, # static debug + } + }, + "libraries": [ + "ws2_32" + ] + }], + ['OS == "mac"', { + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-g', + '-Wall', + '-Wextra', + '-DOSATOMIC_USE_INLINED=1', + '-Ithird_party/abseil-cpp', + '-Ithird_party/re2', + '-Ithird_party/upb', + '-Isrc/core/ext/upb-gen', + '-Isrc/core/ext/upbdefs-gen', + '-Ithird_party/utf8_range', + '-Ithird_party/xxhash', + ], + 'OTHER_CPLUSPLUSFLAGS': [ + '-g', + '-Wall', + '-Wextra', + '-DOSATOMIC_USE_INLINED=1', + '-Ithird_party/abseil-cpp', + '-Ithird_party/re2', + '-Ithird_party/upb', + '-Isrc/core/ext/upb-gen', + '-Isrc/core/ext/upbdefs-gen', + '-Ithird_party/utf8_range', + '-Ithird_party/xxhash', + '-stdlib=libc++', + '-std=c++14', + '-Wno-error=deprecated-declarations', + ], + }, + }] + ] + }, + 'targets': [ + { + 'target_name': 'address_sorting', + 'type': 'static_library', + 'dependencies': [ + ], + 'sources': [ + 'third_party/address_sorting/address_sorting.c', + 'third_party/address_sorting/address_sorting_posix.c', + 'third_party/address_sorting/address_sorting_windows.c', + ], + }, + { + 'target_name': 'gpr', + 'type': 'static_library', + 'dependencies': [ + 'absl/base:base', + 'absl/base:core_headers', + 'absl/flags:flag', + 'absl/flags:marshalling', + 'absl/functional:any_invocable', + 'absl/memory:memory', + 'absl/random:random', + 'absl/status:status', + 'absl/strings:cord', + 'absl/strings:str_format', + 'absl/strings:strings', + 'absl/synchronization:synchronization', + 'absl/time:time', + 'absl/types:optional', + 'absl/types:variant', + ], + 'sources': [ + 'src/core/lib/config/config_vars.cc', + 'src/core/lib/config/config_vars_non_generated.cc', + 'src/core/lib/config/load_config.cc', + 'src/core/lib/event_engine/thread_local.cc', + 'src/core/lib/gpr/alloc.cc', + 'src/core/lib/gpr/android/log.cc', + 'src/core/lib/gpr/atm.cc', + 'src/core/lib/gpr/iphone/cpu.cc', + 'src/core/lib/gpr/linux/cpu.cc', + 'src/core/lib/gpr/linux/log.cc', + 'src/core/lib/gpr/log.cc', + 'src/core/lib/gpr/msys/tmpfile.cc', + 'src/core/lib/gpr/posix/cpu.cc', + 'src/core/lib/gpr/posix/log.cc', + 'src/core/lib/gpr/posix/string.cc', + 'src/core/lib/gpr/posix/sync.cc', + 'src/core/lib/gpr/posix/time.cc', + 'src/core/lib/gpr/posix/tmpfile.cc', + 'src/core/lib/gpr/string.cc', + 'src/core/lib/gpr/sync.cc', + 'src/core/lib/gpr/sync_abseil.cc', + 'src/core/lib/gpr/time.cc', + 'src/core/lib/gpr/time_precise.cc', + 'src/core/lib/gpr/windows/cpu.cc', + 'src/core/lib/gpr/windows/log.cc', + 'src/core/lib/gpr/windows/string.cc', + 'src/core/lib/gpr/windows/string_util.cc', + 'src/core/lib/gpr/windows/sync.cc', + 'src/core/lib/gpr/windows/time.cc', + 'src/core/lib/gpr/windows/tmpfile.cc', + 'src/core/lib/gprpp/crash.cc', + 'src/core/lib/gprpp/examine_stack.cc', + 'src/core/lib/gprpp/fork.cc', + 'src/core/lib/gprpp/host_port.cc', + 'src/core/lib/gprpp/linux/env.cc', + 'src/core/lib/gprpp/mpscq.cc', + 'src/core/lib/gprpp/posix/env.cc', + 'src/core/lib/gprpp/posix/stat.cc', + 'src/core/lib/gprpp/posix/thd.cc', + 'src/core/lib/gprpp/strerror.cc', + 'src/core/lib/gprpp/tchar.cc', + 'src/core/lib/gprpp/time_util.cc', + 'src/core/lib/gprpp/windows/env.cc', + 'src/core/lib/gprpp/windows/stat.cc', + 'src/core/lib/gprpp/windows/thd.cc', + ], + }, + { + 'target_name': 'grpc', + 'type': 'static_library', + 'dependencies': [ + 'upb_json_lib', + 'upb_textformat_lib', + 're2', + 'z', + 'absl/algorithm:container', + 'absl/base:config', + 'absl/base:no_destructor', + 'absl/cleanup:cleanup', + 'absl/container:flat_hash_map', + 'absl/container:flat_hash_set', + 'absl/container:inlined_vector', + 'absl/functional:bind_front', + 'absl/functional:function_ref', + 'absl/hash:hash', + 'absl/meta:type_traits', + 'absl/random:bit_gen_ref', + 'absl/random:distributions', + 'absl/status:statusor', + 'absl/types:span', + 'absl/utility:utility', + 'cares', + 'gpr', + 'address_sorting', + ], + 'sources': [ + 'src/core/client_channel/backup_poller.cc', + 'src/core/client_channel/client_channel.cc', + 'src/core/client_channel/client_channel_channelz.cc', + 'src/core/client_channel/client_channel_factory.cc', + 'src/core/client_channel/client_channel_filter.cc', + 'src/core/client_channel/client_channel_plugin.cc', + 'src/core/client_channel/client_channel_service_config.cc', + 'src/core/client_channel/config_selector.cc', + 'src/core/client_channel/dynamic_filters.cc', + 'src/core/client_channel/global_subchannel_pool.cc', + 'src/core/client_channel/http_proxy_mapper.cc', + 'src/core/client_channel/local_subchannel_pool.cc', + 'src/core/client_channel/retry_filter.cc', + 'src/core/client_channel/retry_filter_legacy_call_data.cc', + 'src/core/client_channel/retry_service_config.cc', + 'src/core/client_channel/retry_throttle.cc', + 'src/core/client_channel/subchannel.cc', + 'src/core/client_channel/subchannel_pool_interface.cc', + 'src/core/client_channel/subchannel_stream_client.cc', + 'src/core/ext/filters/backend_metrics/backend_metric_filter.cc', + 'src/core/ext/filters/census/grpc_context.cc', + 'src/core/ext/filters/channel_idle/channel_idle_filter.cc', + 'src/core/ext/filters/channel_idle/idle_filter_state.cc', + 'src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc', + 'src/core/ext/filters/deadline/deadline_filter.cc', + 'src/core/ext/filters/fault_injection/fault_injection_filter.cc', + 'src/core/ext/filters/fault_injection/fault_injection_service_config_parser.cc', + '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/http/message_compress/compression_filter.cc', + 'src/core/ext/filters/http/message_compress/legacy_compression_filter.cc', + 'src/core/ext/filters/http/server/http_server_filter.cc', + 'src/core/ext/filters/message_size/message_size_filter.cc', + 'src/core/ext/filters/rbac/rbac_filter.cc', + 'src/core/ext/filters/rbac/rbac_service_config_parser.cc', + 'src/core/ext/filters/server_config_selector/server_config_selector_filter.cc', + 'src/core/ext/filters/stateful_session/stateful_session_filter.cc', + 'src/core/ext/filters/stateful_session/stateful_session_service_config_parser.cc', + 'src/core/ext/gcp/metadata_query.cc', + 'src/core/ext/transport/chttp2/alpn/alpn.cc', + 'src/core/ext/transport/chttp2/client/chttp2_connector.cc', + 'src/core/ext/transport/chttp2/server/chttp2_server.cc', + 'src/core/ext/transport/chttp2/transport/bin_decoder.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/decode_huff.cc', + 'src/core/ext/transport/chttp2/transport/flow_control.cc', + 'src/core/ext/transport/chttp2/transport/frame.cc', + 'src/core/ext/transport/chttp2/transport/frame_data.cc', + 'src/core/ext/transport/chttp2/transport/frame_goaway.cc', + 'src/core/ext/transport/chttp2/transport/frame_ping.cc', + 'src/core/ext/transport/chttp2/transport/frame_rst_stream.cc', + 'src/core/ext/transport/chttp2/transport/frame_settings.cc', + 'src/core/ext/transport/chttp2/transport/frame_window_update.cc', + 'src/core/ext/transport/chttp2/transport/hpack_encoder.cc', + 'src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc', + 'src/core/ext/transport/chttp2/transport/hpack_parse_result.cc', + 'src/core/ext/transport/chttp2/transport/hpack_parser.cc', + 'src/core/ext/transport/chttp2/transport/hpack_parser_table.cc', + 'src/core/ext/transport/chttp2/transport/http2_settings.cc', + 'src/core/ext/transport/chttp2/transport/http_trace.cc', + 'src/core/ext/transport/chttp2/transport/huffsyms.cc', + 'src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc', + 'src/core/ext/transport/chttp2/transport/parsing.cc', + 'src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc', + 'src/core/ext/transport/chttp2/transport/ping_callbacks.cc', + 'src/core/ext/transport/chttp2/transport/ping_rate_policy.cc', + 'src/core/ext/transport/chttp2/transport/stream_lists.cc', + 'src/core/ext/transport/chttp2/transport/varint.cc', + 'src/core/ext/transport/chttp2/transport/write_size_policy.cc', + 'src/core/ext/transport/chttp2/transport/writing.cc', + 'src/core/ext/transport/inproc/inproc_plugin.cc', + 'src/core/ext/transport/inproc/inproc_transport.cc', + 'src/core/ext/transport/inproc/legacy_inproc_transport.cc', + 'src/core/ext/upb-gen/envoy/admin/v3/certs.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/admin/v3/clusters.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/admin/v3/config_dump.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/admin/v3/config_dump_shared.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/admin/v3/init_dump.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/admin/v3/listeners.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/admin/v3/memory.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/admin/v3/metrics.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/admin/v3/mutex_stats.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/admin/v3/server_info.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/admin/v3/tap.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/annotations/deprecation.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/annotations/resource.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/accesslog/v3/accesslog.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/bootstrap/v3/bootstrap.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/cluster/v3/circuit_breaker.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/cluster/v3/cluster.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/cluster/v3/filter.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/cluster/v3/outlier_detection.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/common/matcher/v3/matcher.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/address.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/backoff.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/base.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/config_source.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/event_service_config.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/extension.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/grpc_method_list.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/grpc_service.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/health_check.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/http_service.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/http_uri.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/protocol.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/proxy_protocol.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/resolver.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/socket_option.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/substitution_format_string.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/core/v3/udp_socket_config.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/endpoint/v3/endpoint.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/endpoint/v3/endpoint_components.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/endpoint/v3/load_report.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/listener/v3/api_listener.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/listener/v3/listener.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/listener/v3/listener_components.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/listener/v3/quic_config.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/listener/v3/udp_listener_config.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/metrics/v3/metrics_service.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/metrics/v3/stats.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/overload/v3/overload.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/rbac/v3/rbac.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/route/v3/route.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/route/v3/route_components.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/route/v3/scoped_route.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/tap/v3/common.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/trace/v3/datadog.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/trace/v3/dynamic_ot.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/trace/v3/http_tracer.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/trace/v3/lightstep.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/trace/v3/opencensus.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/trace/v3/opentelemetry.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/trace/v3/service.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/trace/v3/skywalking.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/trace/v3/trace.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/trace/v3/xray.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/config/trace/v3/zipkin.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/data/accesslog/v3/accesslog.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/clusters/aggregate/v3/cluster.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/filters/common/fault/v3/fault.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/filters/http/fault/v3/fault.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/filters/http/rbac/v3/rbac.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/filters/http/router/v3/router.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/filters/http/stateful_session/v3/stateful_session.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/http/stateful_session/cookie/v3/cookie.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/common/v3/common.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/transport_sockets/tls/v3/cert.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/transport_sockets/tls/v3/common.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/transport_sockets/tls/v3/secret.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/transport_sockets/tls/v3/tls.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/extensions/upstreams/http/v3/http_protocol_options.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/service/discovery/v3/ads.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/service/discovery/v3/discovery.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/service/load_stats/v3/lrs.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/service/status/v3/csds.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/http/v3/cookie.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/http/v3/path_transformation.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/matcher/v3/filter_state.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/matcher/v3/http_inputs.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/matcher/v3/metadata.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/matcher/v3/node.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/matcher/v3/number.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/matcher/v3/path.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/matcher/v3/regex.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/matcher/v3/status_code_input.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/matcher/v3/string.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/matcher/v3/struct.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/matcher/v3/value.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/metadata/v3/metadata.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/tracing/v3/custom_tag.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/v3/hash_policy.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/v3/http.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/v3/http_status.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/v3/percent.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/v3/range.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/v3/ratelimit_strategy.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/v3/ratelimit_unit.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/v3/semantic_version.upb_minitable.c', + 'src/core/ext/upb-gen/envoy/type/v3/token_bucket.upb_minitable.c', + 'src/core/ext/upb-gen/google/api/annotations.upb_minitable.c', + 'src/core/ext/upb-gen/google/api/expr/v1alpha1/checked.upb_minitable.c', + 'src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb_minitable.c', + 'src/core/ext/upb-gen/google/api/http.upb_minitable.c', + 'src/core/ext/upb-gen/google/api/httpbody.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/any.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/descriptor.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/duration.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/empty.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/struct.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/timestamp.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/wrappers.upb_minitable.c', + 'src/core/ext/upb-gen/google/rpc/status.upb_minitable.c', + 'src/core/ext/upb-gen/opencensus/proto/trace/v1/trace_config.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/gcp/altscontext.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/gcp/handshaker.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/gcp/transport_security_common.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/health/v1/health.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/lb/v1/load_balancer.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/lookup/v1/rls.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/lookup/v1/rls_config.upb_minitable.c', + 'src/core/ext/upb-gen/udpa/annotations/migrate.upb_minitable.c', + 'src/core/ext/upb-gen/udpa/annotations/security.upb_minitable.c', + 'src/core/ext/upb-gen/udpa/annotations/sensitive.upb_minitable.c', + 'src/core/ext/upb-gen/udpa/annotations/status.upb_minitable.c', + 'src/core/ext/upb-gen/udpa/annotations/versioning.upb_minitable.c', + 'src/core/ext/upb-gen/validate/validate.upb_minitable.c', + 'src/core/ext/upb-gen/xds/annotations/v3/migrate.upb_minitable.c', + 'src/core/ext/upb-gen/xds/annotations/v3/security.upb_minitable.c', + 'src/core/ext/upb-gen/xds/annotations/v3/sensitive.upb_minitable.c', + 'src/core/ext/upb-gen/xds/annotations/v3/status.upb_minitable.c', + 'src/core/ext/upb-gen/xds/annotations/v3/versioning.upb_minitable.c', + 'src/core/ext/upb-gen/xds/core/v3/authority.upb_minitable.c', + 'src/core/ext/upb-gen/xds/core/v3/cidr.upb_minitable.c', + 'src/core/ext/upb-gen/xds/core/v3/collection_entry.upb_minitable.c', + 'src/core/ext/upb-gen/xds/core/v3/context_params.upb_minitable.c', + 'src/core/ext/upb-gen/xds/core/v3/extension.upb_minitable.c', + 'src/core/ext/upb-gen/xds/core/v3/resource.upb_minitable.c', + 'src/core/ext/upb-gen/xds/core/v3/resource_locator.upb_minitable.c', + 'src/core/ext/upb-gen/xds/core/v3/resource_name.upb_minitable.c', + 'src/core/ext/upb-gen/xds/data/orca/v3/orca_load_report.upb_minitable.c', + 'src/core/ext/upb-gen/xds/service/orca/v3/orca.upb_minitable.c', + 'src/core/ext/upb-gen/xds/type/matcher/v3/cel.upb_minitable.c', + 'src/core/ext/upb-gen/xds/type/matcher/v3/domain.upb_minitable.c', + 'src/core/ext/upb-gen/xds/type/matcher/v3/http_inputs.upb_minitable.c', + 'src/core/ext/upb-gen/xds/type/matcher/v3/ip.upb_minitable.c', + 'src/core/ext/upb-gen/xds/type/matcher/v3/matcher.upb_minitable.c', + 'src/core/ext/upb-gen/xds/type/matcher/v3/range.upb_minitable.c', + 'src/core/ext/upb-gen/xds/type/matcher/v3/regex.upb_minitable.c', + 'src/core/ext/upb-gen/xds/type/matcher/v3/string.upb_minitable.c', + 'src/core/ext/upb-gen/xds/type/v3/cel.upb_minitable.c', + 'src/core/ext/upb-gen/xds/type/v3/range.upb_minitable.c', + 'src/core/ext/upb-gen/xds/type/v3/typed_struct.upb_minitable.c', + 'src/core/ext/upbdefs-gen/envoy/admin/v3/certs.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/admin/v3/clusters.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/admin/v3/config_dump.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/admin/v3/config_dump_shared.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/admin/v3/init_dump.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/admin/v3/listeners.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/admin/v3/memory.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/admin/v3/metrics.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/admin/v3/mutex_stats.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/admin/v3/server_info.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/admin/v3/tap.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/annotations/deprecation.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/annotations/resource.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/accesslog/v3/accesslog.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/bootstrap/v3/bootstrap.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/cluster/v3/circuit_breaker.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/cluster/v3/cluster.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/cluster/v3/filter.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/cluster/v3/outlier_detection.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/common/matcher/v3/matcher.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/address.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/backoff.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/base.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/config_source.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/event_service_config.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/extension.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/grpc_method_list.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/grpc_service.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/health_check.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/http_service.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/http_uri.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/protocol.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/proxy_protocol.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/resolver.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/socket_option.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/substitution_format_string.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/core/v3/udp_socket_config.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/endpoint/v3/endpoint.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/endpoint/v3/endpoint_components.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/endpoint/v3/load_report.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/listener/v3/api_listener.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/listener/v3/listener.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/listener/v3/listener_components.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/listener/v3/quic_config.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/listener/v3/udp_listener_config.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/metrics/v3/metrics_service.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/metrics/v3/stats.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/overload/v3/overload.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/rbac/v3/rbac.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/route/v3/route.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/route/v3/route_components.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/route/v3/scoped_route.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/tap/v3/common.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/trace/v3/datadog.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/trace/v3/dynamic_ot.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/trace/v3/http_tracer.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/trace/v3/lightstep.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/trace/v3/opencensus.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/trace/v3/opentelemetry.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/trace/v3/service.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/trace/v3/skywalking.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/trace/v3/trace.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/trace/v3/xray.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/config/trace/v3/zipkin.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/data/accesslog/v3/accesslog.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/filters/http/router/v3/router.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/filters/http/stateful_session/v3/stateful_session.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/http/stateful_session/cookie/v3/cookie.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/transport_sockets/tls/v3/secret.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/extensions/upstreams/http/v3/http_protocol_options.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/service/discovery/v3/ads.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/service/discovery/v3/discovery.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/service/load_stats/v3/lrs.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/service/status/v3/csds.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/http/v3/cookie.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/http/v3/path_transformation.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/matcher/v3/filter_state.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/matcher/v3/http_inputs.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/matcher/v3/metadata.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/matcher/v3/node.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/matcher/v3/number.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/matcher/v3/path.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/matcher/v3/regex.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/matcher/v3/status_code_input.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/matcher/v3/string.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/matcher/v3/struct.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/matcher/v3/value.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/metadata/v3/metadata.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/tracing/v3/custom_tag.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/v3/hash_policy.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/v3/http.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/v3/http_status.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/v3/percent.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/v3/range.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/v3/ratelimit_strategy.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/v3/ratelimit_unit.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/v3/semantic_version.upbdefs.c', + 'src/core/ext/upbdefs-gen/envoy/type/v3/token_bucket.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/api/annotations.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/checked.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/syntax.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/api/http.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/api/httpbody.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/protobuf/any.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/protobuf/descriptor.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/protobuf/duration.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/protobuf/empty.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/protobuf/struct.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/protobuf/timestamp.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/protobuf/wrappers.upbdefs.c', + 'src/core/ext/upbdefs-gen/google/rpc/status.upbdefs.c', + 'src/core/ext/upbdefs-gen/opencensus/proto/trace/v1/trace_config.upbdefs.c', + 'src/core/ext/upbdefs-gen/src/proto/grpc/lookup/v1/rls_config.upbdefs.c', + 'src/core/ext/upbdefs-gen/udpa/annotations/migrate.upbdefs.c', + 'src/core/ext/upbdefs-gen/udpa/annotations/security.upbdefs.c', + 'src/core/ext/upbdefs-gen/udpa/annotations/sensitive.upbdefs.c', + 'src/core/ext/upbdefs-gen/udpa/annotations/status.upbdefs.c', + 'src/core/ext/upbdefs-gen/udpa/annotations/versioning.upbdefs.c', + 'src/core/ext/upbdefs-gen/validate/validate.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/annotations/v3/migrate.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/annotations/v3/security.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/annotations/v3/sensitive.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/annotations/v3/status.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/annotations/v3/versioning.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/core/v3/authority.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/core/v3/cidr.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/core/v3/collection_entry.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/core/v3/context_params.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/core/v3/extension.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/core/v3/resource.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/core/v3/resource_locator.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/core/v3/resource_name.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/type/matcher/v3/cel.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/type/matcher/v3/domain.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/type/matcher/v3/http_inputs.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/type/matcher/v3/ip.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/type/matcher/v3/matcher.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/type/matcher/v3/range.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/type/matcher/v3/regex.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/type/matcher/v3/string.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/type/v3/cel.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/type/v3/range.upbdefs.c', + 'src/core/ext/upbdefs-gen/xds/type/v3/typed_struct.upbdefs.c', + 'src/core/ext/xds/certificate_provider_store.cc', + 'src/core/ext/xds/file_watcher_certificate_provider_factory.cc', + 'src/core/ext/xds/xds_api.cc', + 'src/core/ext/xds/xds_audit_logger_registry.cc', + 'src/core/ext/xds/xds_bootstrap.cc', + 'src/core/ext/xds/xds_bootstrap_grpc.cc', + 'src/core/ext/xds/xds_certificate_provider.cc', + 'src/core/ext/xds/xds_channel_stack_modifier.cc', + 'src/core/ext/xds/xds_client.cc', + 'src/core/ext/xds/xds_client_grpc.cc', + 'src/core/ext/xds/xds_client_stats.cc', + 'src/core/ext/xds/xds_cluster.cc', + 'src/core/ext/xds/xds_cluster_specifier_plugin.cc', + 'src/core/ext/xds/xds_common_types.cc', + 'src/core/ext/xds/xds_endpoint.cc', + 'src/core/ext/xds/xds_health_status.cc', + 'src/core/ext/xds/xds_http_fault_filter.cc', + 'src/core/ext/xds/xds_http_filters.cc', + 'src/core/ext/xds/xds_http_rbac_filter.cc', + 'src/core/ext/xds/xds_http_stateful_session_filter.cc', + 'src/core/ext/xds/xds_lb_policy_registry.cc', + 'src/core/ext/xds/xds_listener.cc', + 'src/core/ext/xds/xds_route_config.cc', + 'src/core/ext/xds/xds_routing.cc', + 'src/core/ext/xds/xds_server_config_fetcher.cc', + 'src/core/ext/xds/xds_transport_grpc.cc', + 'src/core/lib/address_utils/parse_address.cc', + 'src/core/lib/address_utils/sockaddr_utils.cc', + 'src/core/lib/backoff/backoff.cc', + 'src/core/lib/backoff/random_early_detection.cc', + 'src/core/lib/channel/call_tracer.cc', + 'src/core/lib/channel/channel_args.cc', + 'src/core/lib/channel/channel_args_preconditioning.cc', + 'src/core/lib/channel/channel_stack.cc', + 'src/core/lib/channel/channel_stack_builder.cc', + 'src/core/lib/channel/channel_stack_builder_impl.cc', + 'src/core/lib/channel/channel_stack_trace.cc', + 'src/core/lib/channel/channel_trace.cc', + 'src/core/lib/channel/channelz.cc', + 'src/core/lib/channel/channelz_registry.cc', + 'src/core/lib/channel/connected_channel.cc', + 'src/core/lib/channel/metrics.cc', + 'src/core/lib/channel/promise_based_filter.cc', + 'src/core/lib/channel/server_call_tracer_filter.cc', + 'src/core/lib/channel/status_util.cc', + 'src/core/lib/compression/compression.cc', + 'src/core/lib/compression/compression_internal.cc', + 'src/core/lib/compression/message_compress.cc', + 'src/core/lib/config/core_configuration.cc', + 'src/core/lib/debug/event_log.cc', + 'src/core/lib/debug/histogram_view.cc', + 'src/core/lib/debug/stats.cc', + 'src/core/lib/debug/stats_data.cc', + 'src/core/lib/debug/trace.cc', + 'src/core/lib/event_engine/ares_resolver.cc', + 'src/core/lib/event_engine/cf_engine/cf_engine.cc', + 'src/core/lib/event_engine/cf_engine/cfstream_endpoint.cc', + 'src/core/lib/event_engine/cf_engine/dns_service_resolver.cc', + 'src/core/lib/event_engine/channel_args_endpoint_config.cc', + 'src/core/lib/event_engine/default_event_engine.cc', + 'src/core/lib/event_engine/default_event_engine_factory.cc', + 'src/core/lib/event_engine/event_engine.cc', + 'src/core/lib/event_engine/forkable.cc', + 'src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc', + 'src/core/lib/event_engine/posix_engine/ev_poll_posix.cc', + 'src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc', + 'src/core/lib/event_engine/posix_engine/internal_errqueue.cc', + 'src/core/lib/event_engine/posix_engine/lockfree_event.cc', + 'src/core/lib/event_engine/posix_engine/native_posix_dns_resolver.cc', + 'src/core/lib/event_engine/posix_engine/posix_endpoint.cc', + 'src/core/lib/event_engine/posix_engine/posix_engine.cc', + 'src/core/lib/event_engine/posix_engine/posix_engine_listener.cc', + 'src/core/lib/event_engine/posix_engine/posix_engine_listener_utils.cc', + 'src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc', + 'src/core/lib/event_engine/posix_engine/timer.cc', + 'src/core/lib/event_engine/posix_engine/timer_heap.cc', + 'src/core/lib/event_engine/posix_engine/timer_manager.cc', + 'src/core/lib/event_engine/posix_engine/traced_buffer_list.cc', + 'src/core/lib/event_engine/posix_engine/wakeup_fd_eventfd.cc', + 'src/core/lib/event_engine/posix_engine/wakeup_fd_pipe.cc', + 'src/core/lib/event_engine/posix_engine/wakeup_fd_posix_default.cc', + 'src/core/lib/event_engine/resolved_address.cc', + 'src/core/lib/event_engine/shim.cc', + 'src/core/lib/event_engine/slice.cc', + 'src/core/lib/event_engine/slice_buffer.cc', + 'src/core/lib/event_engine/tcp_socket_utils.cc', + 'src/core/lib/event_engine/thread_pool/thread_count.cc', + 'src/core/lib/event_engine/thread_pool/thread_pool_factory.cc', + 'src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc', + 'src/core/lib/event_engine/thready_event_engine/thready_event_engine.cc', + 'src/core/lib/event_engine/time_util.cc', + 'src/core/lib/event_engine/trace.cc', + 'src/core/lib/event_engine/utils.cc', + 'src/core/lib/event_engine/windows/grpc_polled_fd_windows.cc', + 'src/core/lib/event_engine/windows/iocp.cc', + 'src/core/lib/event_engine/windows/native_windows_dns_resolver.cc', + 'src/core/lib/event_engine/windows/win_socket.cc', + 'src/core/lib/event_engine/windows/windows_endpoint.cc', + 'src/core/lib/event_engine/windows/windows_engine.cc', + 'src/core/lib/event_engine/windows/windows_listener.cc', + 'src/core/lib/event_engine/work_queue/basic_work_queue.cc', + 'src/core/lib/experiments/config.cc', + 'src/core/lib/experiments/experiments.cc', + 'src/core/lib/gprpp/load_file.cc', + 'src/core/lib/gprpp/per_cpu.cc', + 'src/core/lib/gprpp/posix/directory_reader.cc', + 'src/core/lib/gprpp/ref_counted_string.cc', + 'src/core/lib/gprpp/status_helper.cc', + 'src/core/lib/gprpp/time.cc', + 'src/core/lib/gprpp/time_averaged_stats.cc', + 'src/core/lib/gprpp/validation_errors.cc', + 'src/core/lib/gprpp/windows/directory_reader.cc', + 'src/core/lib/gprpp/work_serializer.cc', + 'src/core/lib/handshaker/proxy_mapper_registry.cc', + 'src/core/lib/http/format_request.cc', + 'src/core/lib/http/httpcli.cc', + 'src/core/lib/http/httpcli_security_connector.cc', + 'src/core/lib/http/parser.cc', + 'src/core/lib/iomgr/buffer_list.cc', + 'src/core/lib/iomgr/call_combiner.cc', + 'src/core/lib/iomgr/cfstream_handle.cc', + 'src/core/lib/iomgr/closure.cc', + 'src/core/lib/iomgr/combiner.cc', + 'src/core/lib/iomgr/dualstack_socket_posix.cc', + 'src/core/lib/iomgr/endpoint.cc', + 'src/core/lib/iomgr/endpoint_cfstream.cc', + 'src/core/lib/iomgr/endpoint_pair_posix.cc', + 'src/core/lib/iomgr/endpoint_pair_windows.cc', + 'src/core/lib/iomgr/error.cc', + 'src/core/lib/iomgr/error_cfstream.cc', + 'src/core/lib/iomgr/ev_apple.cc', + 'src/core/lib/iomgr/ev_epoll1_linux.cc', + 'src/core/lib/iomgr/ev_poll_posix.cc', + 'src/core/lib/iomgr/ev_posix.cc', + 'src/core/lib/iomgr/ev_windows.cc', + 'src/core/lib/iomgr/event_engine_shims/closure.cc', + 'src/core/lib/iomgr/event_engine_shims/endpoint.cc', + 'src/core/lib/iomgr/event_engine_shims/tcp_client.cc', + 'src/core/lib/iomgr/exec_ctx.cc', + 'src/core/lib/iomgr/executor.cc', + 'src/core/lib/iomgr/fork_posix.cc', + 'src/core/lib/iomgr/fork_windows.cc', + 'src/core/lib/iomgr/gethostname_fallback.cc', + 'src/core/lib/iomgr/gethostname_host_name_max.cc', + 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_posix.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc', + 'src/core/lib/iomgr/internal_errqueue.cc', + 'src/core/lib/iomgr/iocp_windows.cc', + 'src/core/lib/iomgr/iomgr.cc', + 'src/core/lib/iomgr/iomgr_internal.cc', + 'src/core/lib/iomgr/iomgr_posix.cc', + 'src/core/lib/iomgr/iomgr_posix_cfstream.cc', + 'src/core/lib/iomgr/iomgr_windows.cc', + 'src/core/lib/iomgr/lockfree_event.cc', + 'src/core/lib/iomgr/polling_entity.cc', + 'src/core/lib/iomgr/pollset.cc', + 'src/core/lib/iomgr/pollset_set.cc', + 'src/core/lib/iomgr/pollset_set_windows.cc', + 'src/core/lib/iomgr/pollset_windows.cc', + 'src/core/lib/iomgr/resolve_address.cc', + 'src/core/lib/iomgr/resolve_address_posix.cc', + 'src/core/lib/iomgr/resolve_address_windows.cc', + 'src/core/lib/iomgr/sockaddr_utils_posix.cc', + 'src/core/lib/iomgr/socket_factory_posix.cc', + 'src/core/lib/iomgr/socket_mutator.cc', + 'src/core/lib/iomgr/socket_utils_common_posix.cc', + 'src/core/lib/iomgr/socket_utils_linux.cc', + 'src/core/lib/iomgr/socket_utils_posix.cc', + 'src/core/lib/iomgr/socket_utils_windows.cc', + 'src/core/lib/iomgr/socket_windows.cc', + 'src/core/lib/iomgr/systemd_utils.cc', + 'src/core/lib/iomgr/tcp_client.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_posix.cc', + 'src/core/lib/iomgr/tcp_server.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_server_utils_posix_noifaddrs.cc', + 'src/core/lib/iomgr/tcp_server_windows.cc', + 'src/core/lib/iomgr/tcp_windows.cc', + 'src/core/lib/iomgr/timer.cc', + 'src/core/lib/iomgr/timer_generic.cc', + 'src/core/lib/iomgr/timer_heap.cc', + 'src/core/lib/iomgr/timer_manager.cc', + 'src/core/lib/iomgr/unix_sockets_posix.cc', + 'src/core/lib/iomgr/unix_sockets_posix_noop.cc', + 'src/core/lib/iomgr/vsock.cc', + 'src/core/lib/iomgr/wakeup_fd_eventfd.cc', + 'src/core/lib/iomgr/wakeup_fd_nospecial.cc', + 'src/core/lib/iomgr/wakeup_fd_pipe.cc', + 'src/core/lib/iomgr/wakeup_fd_posix.cc', + 'src/core/lib/json/json_object_loader.cc', + 'src/core/lib/json/json_reader.cc', + 'src/core/lib/json/json_util.cc', + 'src/core/lib/json/json_writer.cc', + 'src/core/lib/matchers/matchers.cc', + 'src/core/lib/promise/activity.cc', + 'src/core/lib/promise/party.cc', + 'src/core/lib/promise/sleep.cc', + 'src/core/lib/promise/trace.cc', + 'src/core/lib/resource_quota/api.cc', + 'src/core/lib/resource_quota/arena.cc', + 'src/core/lib/resource_quota/memory_quota.cc', + 'src/core/lib/resource_quota/periodic_update.cc', + 'src/core/lib/resource_quota/resource_quota.cc', + 'src/core/lib/resource_quota/thread_quota.cc', + 'src/core/lib/resource_quota/trace.cc', + 'src/core/lib/security/authorization/audit_logging.cc', + 'src/core/lib/security/authorization/authorization_policy_provider_vtable.cc', + 'src/core/lib/security/authorization/evaluate_args.cc', + 'src/core/lib/security/authorization/grpc_authorization_engine.cc', + 'src/core/lib/security/authorization/grpc_server_authz_filter.cc', + 'src/core/lib/security/authorization/matchers.cc', + 'src/core/lib/security/authorization/rbac_policy.cc', + 'src/core/lib/security/authorization/stdout_logger.cc', + 'src/core/lib/security/certificate_provider/certificate_provider_registry.cc', + 'src/core/lib/security/context/security_context.cc', + 'src/core/lib/security/credentials/alts/alts_credentials.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc', + 'src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc', + 'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc', + 'src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc', + 'src/core/lib/security/credentials/call_creds_util.cc', + 'src/core/lib/security/credentials/channel_creds_registry_init.cc', + 'src/core/lib/security/credentials/composite/composite_credentials.cc', + 'src/core/lib/security/credentials/credentials.cc', + 'src/core/lib/security/credentials/external/aws_external_account_credentials.cc', + 'src/core/lib/security/credentials/external/aws_request_signer.cc', + 'src/core/lib/security/credentials/external/external_account_credentials.cc', + 'src/core/lib/security/credentials/external/file_external_account_credentials.cc', + 'src/core/lib/security/credentials/external/url_external_account_credentials.cc', + 'src/core/lib/security/credentials/fake/fake_credentials.cc', + 'src/core/lib/security/credentials/google_default/credentials_generic.cc', + 'src/core/lib/security/credentials/google_default/google_default_credentials.cc', + 'src/core/lib/security/credentials/iam/iam_credentials.cc', + 'src/core/lib/security/credentials/insecure/insecure_credentials.cc', + 'src/core/lib/security/credentials/jwt/json_token.cc', + 'src/core/lib/security/credentials/jwt/jwt_credentials.cc', + 'src/core/lib/security/credentials/jwt/jwt_verifier.cc', + 'src/core/lib/security/credentials/local/local_credentials.cc', + 'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc', + 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', + 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_certificate_match.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_crl_provider.cc', + 'src/core/lib/security/credentials/tls/tls_credentials.cc', + 'src/core/lib/security/credentials/tls/tls_utils.cc', + 'src/core/lib/security/credentials/xds/xds_credentials.cc', + 'src/core/lib/security/security_connector/alts/alts_security_connector.cc', + 'src/core/lib/security/security_connector/fake/fake_security_connector.cc', + 'src/core/lib/security/security_connector/insecure/insecure_security_connector.cc', + 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', + 'src/core/lib/security/security_connector/load_system_roots_supported.cc', + 'src/core/lib/security/security_connector/load_system_roots_windows.cc', + 'src/core/lib/security/security_connector/local/local_security_connector.cc', + 'src/core/lib/security/security_connector/security_connector.cc', + 'src/core/lib/security/security_connector/ssl/ssl_security_connector.cc', + 'src/core/lib/security/security_connector/ssl_utils.cc', + 'src/core/lib/security/security_connector/tls/tls_security_connector.cc', + 'src/core/lib/security/transport/client_auth_filter.cc', + 'src/core/lib/security/transport/legacy_server_auth_filter.cc', + 'src/core/lib/security/transport/secure_endpoint.cc', + 'src/core/lib/security/transport/security_handshaker.cc', + 'src/core/lib/security/transport/server_auth_filter.cc', + 'src/core/lib/security/transport/tsi_error.cc', + 'src/core/lib/security/util/json_util.cc', + 'src/core/lib/slice/b64.cc', + 'src/core/lib/slice/percent_encoding.cc', + 'src/core/lib/slice/slice.cc', + 'src/core/lib/slice/slice_buffer.cc', + 'src/core/lib/slice/slice_refcount.cc', + 'src/core/lib/slice/slice_string_helpers.cc', + 'src/core/lib/surface/api_trace.cc', + 'src/core/lib/surface/byte_buffer.cc', + 'src/core/lib/surface/byte_buffer_reader.cc', + 'src/core/lib/surface/call.cc', + 'src/core/lib/surface/call_details.cc', + 'src/core/lib/surface/call_log_batch.cc', + 'src/core/lib/surface/channel.cc', + 'src/core/lib/surface/channel_create.cc', + 'src/core/lib/surface/channel_init.cc', + 'src/core/lib/surface/channel_stack_type.cc', + 'src/core/lib/surface/completion_queue.cc', + 'src/core/lib/surface/completion_queue_factory.cc', + 'src/core/lib/surface/event_string.cc', + 'src/core/lib/surface/init.cc', + 'src/core/lib/surface/init_internally.cc', + 'src/core/lib/surface/lame_client.cc', + 'src/core/lib/surface/legacy_channel.cc', + 'src/core/lib/surface/metadata_array.cc', + 'src/core/lib/surface/server.cc', + 'src/core/lib/surface/validate_metadata.cc', + 'src/core/lib/surface/version.cc', + 'src/core/lib/surface/wait_for_cq_end_op.cc', + 'src/core/lib/transport/batch_builder.cc', + 'src/core/lib/transport/bdp_estimator.cc', + 'src/core/lib/transport/call_filters.cc', + 'src/core/lib/transport/call_final_info.cc', + 'src/core/lib/transport/call_size_estimator.cc', + 'src/core/lib/transport/call_spine.cc', + 'src/core/lib/transport/connectivity_state.cc', + 'src/core/lib/transport/error_utils.cc', + 'src/core/lib/transport/handshaker.cc', + 'src/core/lib/transport/handshaker_registry.cc', + 'src/core/lib/transport/http_connect_handshaker.cc', + 'src/core/lib/transport/message.cc', + 'src/core/lib/transport/metadata.cc', + 'src/core/lib/transport/metadata_batch.cc', + 'src/core/lib/transport/metadata_info.cc', + 'src/core/lib/transport/parsed_metadata.cc', + 'src/core/lib/transport/status_conversion.cc', + 'src/core/lib/transport/tcp_connect_handshaker.cc', + 'src/core/lib/transport/timeout_encoding.cc', + 'src/core/lib/transport/transport.cc', + 'src/core/lib/transport/transport_op_string.cc', + 'src/core/lib/uri/uri_parser.cc', + 'src/core/load_balancing/address_filtering.cc', + 'src/core/load_balancing/backend_metric_parser.cc', + 'src/core/load_balancing/child_policy_handler.cc', + 'src/core/load_balancing/endpoint_list.cc', + 'src/core/load_balancing/grpclb/client_load_reporting_filter.cc', + 'src/core/load_balancing/grpclb/grpclb.cc', + 'src/core/load_balancing/grpclb/grpclb_balancer_addresses.cc', + 'src/core/load_balancing/grpclb/grpclb_client_stats.cc', + 'src/core/load_balancing/grpclb/load_balancer_api.cc', + 'src/core/load_balancing/health_check_client.cc', + 'src/core/load_balancing/lb_policy.cc', + 'src/core/load_balancing/lb_policy_registry.cc', + 'src/core/load_balancing/oob_backend_metric.cc', + 'src/core/load_balancing/outlier_detection/outlier_detection.cc', + 'src/core/load_balancing/pick_first/pick_first.cc', + 'src/core/load_balancing/priority/priority.cc', + 'src/core/load_balancing/ring_hash/ring_hash.cc', + 'src/core/load_balancing/rls/rls.cc', + 'src/core/load_balancing/round_robin/round_robin.cc', + 'src/core/load_balancing/weighted_round_robin/static_stride_scheduler.cc', + 'src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc', + 'src/core/load_balancing/weighted_target/weighted_target.cc', + 'src/core/load_balancing/xds/cds.cc', + 'src/core/load_balancing/xds/xds_cluster_impl.cc', + 'src/core/load_balancing/xds/xds_cluster_manager.cc', + 'src/core/load_balancing/xds/xds_override_host.cc', + 'src/core/load_balancing/xds/xds_wrr_locality.cc', + 'src/core/plugin_registry/grpc_plugin_registry.cc', + 'src/core/plugin_registry/grpc_plugin_registry_extra.cc', + 'src/core/resolver/binder/binder_resolver.cc', + 'src/core/resolver/dns/c_ares/dns_resolver_ares.cc', + 'src/core/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', + 'src/core/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', + 'src/core/resolver/dns/c_ares/grpc_ares_wrapper.cc', + 'src/core/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', + 'src/core/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', + 'src/core/resolver/dns/dns_resolver_plugin.cc', + 'src/core/resolver/dns/event_engine/event_engine_client_channel_resolver.cc', + 'src/core/resolver/dns/event_engine/service_config_helper.cc', + 'src/core/resolver/dns/native/dns_resolver.cc', + 'src/core/resolver/endpoint_addresses.cc', + 'src/core/resolver/fake/fake_resolver.cc', + 'src/core/resolver/google_c2p/google_c2p_resolver.cc', + 'src/core/resolver/polling_resolver.cc', + 'src/core/resolver/resolver.cc', + 'src/core/resolver/resolver_registry.cc', + 'src/core/resolver/sockaddr/sockaddr_resolver.cc', + 'src/core/resolver/xds/xds_dependency_manager.cc', + 'src/core/resolver/xds/xds_resolver.cc', + 'src/core/resolver/xds/xds_resolver_trace.cc', + 'src/core/service_config/service_config_channel_arg_filter.cc', + 'src/core/service_config/service_config_impl.cc', + 'src/core/service_config/service_config_parser.cc', + 'src/core/tsi/alts/crypt/aes_gcm.cc', + 'src/core/tsi/alts/crypt/gsec.cc', + 'src/core/tsi/alts/frame_protector/alts_counter.cc', + 'src/core/tsi/alts/frame_protector/alts_crypter.cc', + 'src/core/tsi/alts/frame_protector/alts_frame_protector.cc', + 'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc', + 'src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc', + 'src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc', + 'src/core/tsi/alts/frame_protector/frame_handler.cc', + 'src/core/tsi/alts/handshaker/alts_handshaker_client.cc', + 'src/core/tsi/alts/handshaker/alts_shared_resource.cc', + 'src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc', + 'src/core/tsi/alts/handshaker/alts_tsi_utils.cc', + 'src/core/tsi/alts/handshaker/transport_security_common_api.cc', + 'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc', + 'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc', + 'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc', + 'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc', + 'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc', + 'src/core/tsi/fake_transport_security.cc', + 'src/core/tsi/local_transport_security.cc', + 'src/core/tsi/ssl/key_logging/ssl_key_logging.cc', + 'src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc', + 'src/core/tsi/ssl/session_cache/ssl_session_cache.cc', + 'src/core/tsi/ssl/session_cache/ssl_session_openssl.cc', + 'src/core/tsi/ssl_transport_security.cc', + 'src/core/tsi/ssl_transport_security_utils.cc', + 'src/core/tsi/transport_security.cc', + 'src/core/tsi/transport_security_grpc.cc', + ], + }, + { + 'target_name': 'grpc_test_util', + 'type': 'static_library', + 'dependencies': [ + 'absl/debugging:failure_signal_handler', + 'absl/debugging:stacktrace', + 'absl/debugging:symbolize', + 'grpc', + ], + 'sources': [ + 'test/core/event_engine/test_init.cc', + 'test/core/util/build.cc', + 'test/core/util/port.cc', + 'test/core/util/port_isolated_runtime_environment.cc', + 'test/core/util/port_server_client.cc', + 'test/core/util/reconnect_server.cc', + 'test/core/util/stack_tracer.cc', + 'test/core/util/test_config.cc', + 'test/core/util/test_tcp_server.cc', + 'test/core/util/tls_utils.cc', + ], + }, + { + 'target_name': 'grpc_test_util_unsecure', + 'type': 'static_library', + 'dependencies': [ + 'absl/debugging:failure_signal_handler', + 'absl/debugging:stacktrace', + 'absl/debugging:symbolize', + 'grpc_unsecure', + ], + 'sources': [ + 'test/core/event_engine/test_init.cc', + 'test/core/util/build.cc', + 'test/core/util/port.cc', + 'test/core/util/port_isolated_runtime_environment.cc', + 'test/core/util/port_server_client.cc', + 'test/core/util/reconnect_server.cc', + 'test/core/util/stack_tracer.cc', + 'test/core/util/test_config.cc', + 'test/core/util/test_tcp_server.cc', + ], + }, + { + 'target_name': 'grpc_unsecure', + 'type': 'static_library', + 'dependencies': [ + 'upb_message_lib', + 'utf8_range_lib', + 'z', + 'absl/algorithm:container', + 'absl/base:config', + 'absl/base:no_destructor', + 'absl/cleanup:cleanup', + 'absl/container:flat_hash_map', + 'absl/container:flat_hash_set', + 'absl/container:inlined_vector', + 'absl/functional:bind_front', + 'absl/functional:function_ref', + 'absl/hash:hash', + 'absl/meta:type_traits', + 'absl/random:bit_gen_ref', + 'absl/random:distributions', + 'absl/status:statusor', + 'absl/types:span', + 'absl/utility:utility', + 'cares', + 'gpr', + 'address_sorting', + ], + 'sources': [ + 'src/core/client_channel/backup_poller.cc', + 'src/core/client_channel/client_channel.cc', + 'src/core/client_channel/client_channel_channelz.cc', + 'src/core/client_channel/client_channel_factory.cc', + 'src/core/client_channel/client_channel_filter.cc', + 'src/core/client_channel/client_channel_plugin.cc', + 'src/core/client_channel/client_channel_service_config.cc', + 'src/core/client_channel/config_selector.cc', + 'src/core/client_channel/dynamic_filters.cc', + 'src/core/client_channel/global_subchannel_pool.cc', + 'src/core/client_channel/http_proxy_mapper.cc', + 'src/core/client_channel/local_subchannel_pool.cc', + 'src/core/client_channel/retry_filter.cc', + 'src/core/client_channel/retry_filter_legacy_call_data.cc', + 'src/core/client_channel/retry_service_config.cc', + 'src/core/client_channel/retry_throttle.cc', + 'src/core/client_channel/subchannel.cc', + 'src/core/client_channel/subchannel_pool_interface.cc', + 'src/core/client_channel/subchannel_stream_client.cc', + 'src/core/ext/filters/backend_metrics/backend_metric_filter.cc', + 'src/core/ext/filters/census/grpc_context.cc', + 'src/core/ext/filters/channel_idle/channel_idle_filter.cc', + 'src/core/ext/filters/channel_idle/idle_filter_state.cc', + 'src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc', + 'src/core/ext/filters/deadline/deadline_filter.cc', + 'src/core/ext/filters/fault_injection/fault_injection_filter.cc', + 'src/core/ext/filters/fault_injection/fault_injection_service_config_parser.cc', + '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/http/message_compress/compression_filter.cc', + 'src/core/ext/filters/http/message_compress/legacy_compression_filter.cc', + 'src/core/ext/filters/http/server/http_server_filter.cc', + 'src/core/ext/filters/message_size/message_size_filter.cc', + 'src/core/ext/transport/chttp2/client/chttp2_connector.cc', + 'src/core/ext/transport/chttp2/server/chttp2_server.cc', + 'src/core/ext/transport/chttp2/transport/bin_decoder.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/decode_huff.cc', + 'src/core/ext/transport/chttp2/transport/flow_control.cc', + 'src/core/ext/transport/chttp2/transport/frame.cc', + 'src/core/ext/transport/chttp2/transport/frame_data.cc', + 'src/core/ext/transport/chttp2/transport/frame_goaway.cc', + 'src/core/ext/transport/chttp2/transport/frame_ping.cc', + 'src/core/ext/transport/chttp2/transport/frame_rst_stream.cc', + 'src/core/ext/transport/chttp2/transport/frame_settings.cc', + 'src/core/ext/transport/chttp2/transport/frame_window_update.cc', + 'src/core/ext/transport/chttp2/transport/hpack_encoder.cc', + 'src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc', + 'src/core/ext/transport/chttp2/transport/hpack_parse_result.cc', + 'src/core/ext/transport/chttp2/transport/hpack_parser.cc', + 'src/core/ext/transport/chttp2/transport/hpack_parser_table.cc', + 'src/core/ext/transport/chttp2/transport/http2_settings.cc', + 'src/core/ext/transport/chttp2/transport/http_trace.cc', + 'src/core/ext/transport/chttp2/transport/huffsyms.cc', + 'src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc', + 'src/core/ext/transport/chttp2/transport/parsing.cc', + 'src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc', + 'src/core/ext/transport/chttp2/transport/ping_callbacks.cc', + 'src/core/ext/transport/chttp2/transport/ping_rate_policy.cc', + 'src/core/ext/transport/chttp2/transport/stream_lists.cc', + 'src/core/ext/transport/chttp2/transport/varint.cc', + 'src/core/ext/transport/chttp2/transport/write_size_policy.cc', + 'src/core/ext/transport/chttp2/transport/writing.cc', + 'src/core/ext/transport/inproc/inproc_plugin.cc', + 'src/core/ext/transport/inproc/inproc_transport.cc', + 'src/core/ext/transport/inproc/legacy_inproc_transport.cc', + 'src/core/ext/upb-gen/google/api/annotations.upb_minitable.c', + 'src/core/ext/upb-gen/google/api/http.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/any.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/descriptor.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/duration.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/empty.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/struct.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/timestamp.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/wrappers.upb_minitable.c', + 'src/core/ext/upb-gen/google/rpc/status.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/gcp/altscontext.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/gcp/handshaker.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/gcp/transport_security_common.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/health/v1/health.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/lb/v1/load_balancer.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/lookup/v1/rls.upb_minitable.c', + 'src/core/ext/upb-gen/validate/validate.upb_minitable.c', + 'src/core/ext/upb-gen/xds/data/orca/v3/orca_load_report.upb_minitable.c', + 'src/core/ext/upb-gen/xds/service/orca/v3/orca.upb_minitable.c', + 'src/core/lib/address_utils/parse_address.cc', + 'src/core/lib/address_utils/sockaddr_utils.cc', + 'src/core/lib/backoff/backoff.cc', + 'src/core/lib/backoff/random_early_detection.cc', + 'src/core/lib/channel/call_tracer.cc', + 'src/core/lib/channel/channel_args.cc', + 'src/core/lib/channel/channel_args_preconditioning.cc', + 'src/core/lib/channel/channel_stack.cc', + 'src/core/lib/channel/channel_stack_builder.cc', + 'src/core/lib/channel/channel_stack_builder_impl.cc', + 'src/core/lib/channel/channel_stack_trace.cc', + 'src/core/lib/channel/channel_trace.cc', + 'src/core/lib/channel/channelz.cc', + 'src/core/lib/channel/channelz_registry.cc', + 'src/core/lib/channel/connected_channel.cc', + 'src/core/lib/channel/metrics.cc', + 'src/core/lib/channel/promise_based_filter.cc', + 'src/core/lib/channel/server_call_tracer_filter.cc', + 'src/core/lib/channel/status_util.cc', + 'src/core/lib/compression/compression.cc', + 'src/core/lib/compression/compression_internal.cc', + 'src/core/lib/compression/message_compress.cc', + 'src/core/lib/config/core_configuration.cc', + 'src/core/lib/debug/event_log.cc', + 'src/core/lib/debug/histogram_view.cc', + 'src/core/lib/debug/stats.cc', + 'src/core/lib/debug/stats_data.cc', + 'src/core/lib/debug/trace.cc', + 'src/core/lib/event_engine/ares_resolver.cc', + 'src/core/lib/event_engine/cf_engine/cf_engine.cc', + 'src/core/lib/event_engine/cf_engine/cfstream_endpoint.cc', + 'src/core/lib/event_engine/cf_engine/dns_service_resolver.cc', + 'src/core/lib/event_engine/channel_args_endpoint_config.cc', + 'src/core/lib/event_engine/default_event_engine.cc', + 'src/core/lib/event_engine/default_event_engine_factory.cc', + 'src/core/lib/event_engine/event_engine.cc', + 'src/core/lib/event_engine/forkable.cc', + 'src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc', + 'src/core/lib/event_engine/posix_engine/ev_poll_posix.cc', + 'src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc', + 'src/core/lib/event_engine/posix_engine/internal_errqueue.cc', + 'src/core/lib/event_engine/posix_engine/lockfree_event.cc', + 'src/core/lib/event_engine/posix_engine/native_posix_dns_resolver.cc', + 'src/core/lib/event_engine/posix_engine/posix_endpoint.cc', + 'src/core/lib/event_engine/posix_engine/posix_engine.cc', + 'src/core/lib/event_engine/posix_engine/posix_engine_listener.cc', + 'src/core/lib/event_engine/posix_engine/posix_engine_listener_utils.cc', + 'src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc', + 'src/core/lib/event_engine/posix_engine/timer.cc', + 'src/core/lib/event_engine/posix_engine/timer_heap.cc', + 'src/core/lib/event_engine/posix_engine/timer_manager.cc', + 'src/core/lib/event_engine/posix_engine/traced_buffer_list.cc', + 'src/core/lib/event_engine/posix_engine/wakeup_fd_eventfd.cc', + 'src/core/lib/event_engine/posix_engine/wakeup_fd_pipe.cc', + 'src/core/lib/event_engine/posix_engine/wakeup_fd_posix_default.cc', + 'src/core/lib/event_engine/resolved_address.cc', + 'src/core/lib/event_engine/shim.cc', + 'src/core/lib/event_engine/slice.cc', + 'src/core/lib/event_engine/slice_buffer.cc', + 'src/core/lib/event_engine/tcp_socket_utils.cc', + 'src/core/lib/event_engine/thread_pool/thread_count.cc', + 'src/core/lib/event_engine/thread_pool/thread_pool_factory.cc', + 'src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc', + 'src/core/lib/event_engine/thready_event_engine/thready_event_engine.cc', + 'src/core/lib/event_engine/time_util.cc', + 'src/core/lib/event_engine/trace.cc', + 'src/core/lib/event_engine/utils.cc', + 'src/core/lib/event_engine/windows/grpc_polled_fd_windows.cc', + 'src/core/lib/event_engine/windows/iocp.cc', + 'src/core/lib/event_engine/windows/native_windows_dns_resolver.cc', + 'src/core/lib/event_engine/windows/win_socket.cc', + 'src/core/lib/event_engine/windows/windows_endpoint.cc', + 'src/core/lib/event_engine/windows/windows_engine.cc', + 'src/core/lib/event_engine/windows/windows_listener.cc', + 'src/core/lib/event_engine/work_queue/basic_work_queue.cc', + 'src/core/lib/experiments/config.cc', + 'src/core/lib/experiments/experiments.cc', + 'src/core/lib/gprpp/load_file.cc', + 'src/core/lib/gprpp/per_cpu.cc', + 'src/core/lib/gprpp/ref_counted_string.cc', + 'src/core/lib/gprpp/status_helper.cc', + 'src/core/lib/gprpp/time.cc', + 'src/core/lib/gprpp/time_averaged_stats.cc', + 'src/core/lib/gprpp/validation_errors.cc', + 'src/core/lib/gprpp/work_serializer.cc', + 'src/core/lib/handshaker/proxy_mapper_registry.cc', + 'src/core/lib/http/format_request.cc', + 'src/core/lib/http/httpcli.cc', + 'src/core/lib/http/parser.cc', + 'src/core/lib/iomgr/buffer_list.cc', + 'src/core/lib/iomgr/call_combiner.cc', + 'src/core/lib/iomgr/cfstream_handle.cc', + 'src/core/lib/iomgr/closure.cc', + 'src/core/lib/iomgr/combiner.cc', + 'src/core/lib/iomgr/dualstack_socket_posix.cc', + 'src/core/lib/iomgr/endpoint.cc', + 'src/core/lib/iomgr/endpoint_cfstream.cc', + 'src/core/lib/iomgr/endpoint_pair_posix.cc', + 'src/core/lib/iomgr/endpoint_pair_windows.cc', + 'src/core/lib/iomgr/error.cc', + 'src/core/lib/iomgr/error_cfstream.cc', + 'src/core/lib/iomgr/ev_apple.cc', + 'src/core/lib/iomgr/ev_epoll1_linux.cc', + 'src/core/lib/iomgr/ev_poll_posix.cc', + 'src/core/lib/iomgr/ev_posix.cc', + 'src/core/lib/iomgr/ev_windows.cc', + 'src/core/lib/iomgr/event_engine_shims/closure.cc', + 'src/core/lib/iomgr/event_engine_shims/endpoint.cc', + 'src/core/lib/iomgr/event_engine_shims/tcp_client.cc', + 'src/core/lib/iomgr/exec_ctx.cc', + 'src/core/lib/iomgr/executor.cc', + 'src/core/lib/iomgr/fork_posix.cc', + 'src/core/lib/iomgr/fork_windows.cc', + 'src/core/lib/iomgr/gethostname_fallback.cc', + 'src/core/lib/iomgr/gethostname_host_name_max.cc', + 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_posix.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc', + 'src/core/lib/iomgr/internal_errqueue.cc', + 'src/core/lib/iomgr/iocp_windows.cc', + 'src/core/lib/iomgr/iomgr.cc', + 'src/core/lib/iomgr/iomgr_internal.cc', + 'src/core/lib/iomgr/iomgr_posix.cc', + 'src/core/lib/iomgr/iomgr_posix_cfstream.cc', + 'src/core/lib/iomgr/iomgr_windows.cc', + 'src/core/lib/iomgr/lockfree_event.cc', + 'src/core/lib/iomgr/polling_entity.cc', + 'src/core/lib/iomgr/pollset.cc', + 'src/core/lib/iomgr/pollset_set.cc', + 'src/core/lib/iomgr/pollset_set_windows.cc', + 'src/core/lib/iomgr/pollset_windows.cc', + 'src/core/lib/iomgr/resolve_address.cc', + 'src/core/lib/iomgr/resolve_address_posix.cc', + 'src/core/lib/iomgr/resolve_address_windows.cc', + 'src/core/lib/iomgr/sockaddr_utils_posix.cc', + 'src/core/lib/iomgr/socket_factory_posix.cc', + 'src/core/lib/iomgr/socket_mutator.cc', + 'src/core/lib/iomgr/socket_utils_common_posix.cc', + 'src/core/lib/iomgr/socket_utils_linux.cc', + 'src/core/lib/iomgr/socket_utils_posix.cc', + 'src/core/lib/iomgr/socket_utils_windows.cc', + 'src/core/lib/iomgr/socket_windows.cc', + 'src/core/lib/iomgr/systemd_utils.cc', + 'src/core/lib/iomgr/tcp_client.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_posix.cc', + 'src/core/lib/iomgr/tcp_server.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_server_utils_posix_noifaddrs.cc', + 'src/core/lib/iomgr/tcp_server_windows.cc', + 'src/core/lib/iomgr/tcp_windows.cc', + 'src/core/lib/iomgr/timer.cc', + 'src/core/lib/iomgr/timer_generic.cc', + 'src/core/lib/iomgr/timer_heap.cc', + 'src/core/lib/iomgr/timer_manager.cc', + 'src/core/lib/iomgr/unix_sockets_posix.cc', + 'src/core/lib/iomgr/unix_sockets_posix_noop.cc', + 'src/core/lib/iomgr/vsock.cc', + 'src/core/lib/iomgr/wakeup_fd_eventfd.cc', + 'src/core/lib/iomgr/wakeup_fd_nospecial.cc', + 'src/core/lib/iomgr/wakeup_fd_pipe.cc', + 'src/core/lib/iomgr/wakeup_fd_posix.cc', + 'src/core/lib/json/json_object_loader.cc', + 'src/core/lib/json/json_reader.cc', + 'src/core/lib/json/json_writer.cc', + 'src/core/lib/promise/activity.cc', + 'src/core/lib/promise/party.cc', + 'src/core/lib/promise/sleep.cc', + 'src/core/lib/promise/trace.cc', + 'src/core/lib/resource_quota/api.cc', + 'src/core/lib/resource_quota/arena.cc', + 'src/core/lib/resource_quota/memory_quota.cc', + 'src/core/lib/resource_quota/periodic_update.cc', + 'src/core/lib/resource_quota/resource_quota.cc', + 'src/core/lib/resource_quota/thread_quota.cc', + 'src/core/lib/resource_quota/trace.cc', + 'src/core/lib/security/authorization/authorization_policy_provider_vtable.cc', + 'src/core/lib/security/authorization/evaluate_args.cc', + 'src/core/lib/security/authorization/grpc_server_authz_filter.cc', + 'src/core/lib/security/certificate_provider/certificate_provider_registry.cc', + 'src/core/lib/security/context/security_context.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc', + 'src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc', + 'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc', + 'src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc', + 'src/core/lib/security/credentials/call_creds_util.cc', + 'src/core/lib/security/credentials/composite/composite_credentials.cc', + 'src/core/lib/security/credentials/credentials.cc', + 'src/core/lib/security/credentials/fake/fake_credentials.cc', + 'src/core/lib/security/credentials/insecure/insecure_credentials.cc', + 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', + 'src/core/lib/security/credentials/tls/tls_utils.cc', + 'src/core/lib/security/security_connector/fake/fake_security_connector.cc', + 'src/core/lib/security/security_connector/insecure/insecure_security_connector.cc', + 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', + 'src/core/lib/security/security_connector/load_system_roots_supported.cc', + 'src/core/lib/security/security_connector/load_system_roots_windows.cc', + 'src/core/lib/security/security_connector/security_connector.cc', + 'src/core/lib/security/transport/client_auth_filter.cc', + 'src/core/lib/security/transport/legacy_server_auth_filter.cc', + 'src/core/lib/security/transport/secure_endpoint.cc', + 'src/core/lib/security/transport/security_handshaker.cc', + 'src/core/lib/security/transport/server_auth_filter.cc', + 'src/core/lib/security/transport/tsi_error.cc', + 'src/core/lib/security/util/json_util.cc', + 'src/core/lib/slice/b64.cc', + 'src/core/lib/slice/percent_encoding.cc', + 'src/core/lib/slice/slice.cc', + 'src/core/lib/slice/slice_buffer.cc', + 'src/core/lib/slice/slice_refcount.cc', + 'src/core/lib/slice/slice_string_helpers.cc', + 'src/core/lib/surface/api_trace.cc', + 'src/core/lib/surface/byte_buffer.cc', + 'src/core/lib/surface/byte_buffer_reader.cc', + 'src/core/lib/surface/call.cc', + 'src/core/lib/surface/call_details.cc', + 'src/core/lib/surface/call_log_batch.cc', + 'src/core/lib/surface/channel.cc', + 'src/core/lib/surface/channel_create.cc', + 'src/core/lib/surface/channel_init.cc', + 'src/core/lib/surface/channel_stack_type.cc', + 'src/core/lib/surface/completion_queue.cc', + 'src/core/lib/surface/completion_queue_factory.cc', + 'src/core/lib/surface/event_string.cc', + 'src/core/lib/surface/init.cc', + 'src/core/lib/surface/init_internally.cc', + 'src/core/lib/surface/lame_client.cc', + 'src/core/lib/surface/legacy_channel.cc', + 'src/core/lib/surface/metadata_array.cc', + 'src/core/lib/surface/server.cc', + 'src/core/lib/surface/validate_metadata.cc', + 'src/core/lib/surface/version.cc', + 'src/core/lib/surface/wait_for_cq_end_op.cc', + 'src/core/lib/transport/batch_builder.cc', + 'src/core/lib/transport/bdp_estimator.cc', + 'src/core/lib/transport/call_filters.cc', + 'src/core/lib/transport/call_final_info.cc', + 'src/core/lib/transport/call_size_estimator.cc', + 'src/core/lib/transport/call_spine.cc', + 'src/core/lib/transport/connectivity_state.cc', + 'src/core/lib/transport/error_utils.cc', + 'src/core/lib/transport/handshaker.cc', + 'src/core/lib/transport/handshaker_registry.cc', + 'src/core/lib/transport/http_connect_handshaker.cc', + 'src/core/lib/transport/message.cc', + 'src/core/lib/transport/metadata.cc', + 'src/core/lib/transport/metadata_batch.cc', + 'src/core/lib/transport/metadata_info.cc', + 'src/core/lib/transport/parsed_metadata.cc', + 'src/core/lib/transport/status_conversion.cc', + 'src/core/lib/transport/tcp_connect_handshaker.cc', + 'src/core/lib/transport/timeout_encoding.cc', + 'src/core/lib/transport/transport.cc', + 'src/core/lib/transport/transport_op_string.cc', + 'src/core/lib/uri/uri_parser.cc', + 'src/core/load_balancing/address_filtering.cc', + 'src/core/load_balancing/backend_metric_parser.cc', + 'src/core/load_balancing/child_policy_handler.cc', + 'src/core/load_balancing/endpoint_list.cc', + 'src/core/load_balancing/grpclb/client_load_reporting_filter.cc', + 'src/core/load_balancing/grpclb/grpclb.cc', + 'src/core/load_balancing/grpclb/grpclb_balancer_addresses.cc', + 'src/core/load_balancing/grpclb/grpclb_client_stats.cc', + 'src/core/load_balancing/grpclb/load_balancer_api.cc', + 'src/core/load_balancing/health_check_client.cc', + 'src/core/load_balancing/lb_policy.cc', + 'src/core/load_balancing/lb_policy_registry.cc', + 'src/core/load_balancing/oob_backend_metric.cc', + 'src/core/load_balancing/outlier_detection/outlier_detection.cc', + 'src/core/load_balancing/pick_first/pick_first.cc', + 'src/core/load_balancing/priority/priority.cc', + 'src/core/load_balancing/rls/rls.cc', + 'src/core/load_balancing/round_robin/round_robin.cc', + 'src/core/load_balancing/weighted_round_robin/static_stride_scheduler.cc', + 'src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc', + 'src/core/load_balancing/weighted_target/weighted_target.cc', + 'src/core/plugin_registry/grpc_plugin_registry.cc', + 'src/core/plugin_registry/grpc_plugin_registry_noextra.cc', + 'src/core/resolver/binder/binder_resolver.cc', + 'src/core/resolver/dns/c_ares/dns_resolver_ares.cc', + 'src/core/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', + 'src/core/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', + 'src/core/resolver/dns/c_ares/grpc_ares_wrapper.cc', + 'src/core/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', + 'src/core/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', + 'src/core/resolver/dns/dns_resolver_plugin.cc', + 'src/core/resolver/dns/event_engine/event_engine_client_channel_resolver.cc', + 'src/core/resolver/dns/event_engine/service_config_helper.cc', + 'src/core/resolver/dns/native/dns_resolver.cc', + 'src/core/resolver/endpoint_addresses.cc', + 'src/core/resolver/fake/fake_resolver.cc', + 'src/core/resolver/polling_resolver.cc', + 'src/core/resolver/resolver.cc', + 'src/core/resolver/resolver_registry.cc', + 'src/core/resolver/sockaddr/sockaddr_resolver.cc', + 'src/core/service_config/service_config_channel_arg_filter.cc', + 'src/core/service_config/service_config_impl.cc', + 'src/core/service_config/service_config_parser.cc', + 'src/core/tsi/alts/handshaker/transport_security_common_api.cc', + 'src/core/tsi/fake_transport_security.cc', + 'src/core/tsi/local_transport_security.cc', + 'src/core/tsi/transport_security.cc', + 'src/core/tsi/transport_security_grpc.cc', + 'third_party/upb/upb/message/accessors.c', + 'third_party/upb/upb/mini_descriptor/build_enum.c', + 'third_party/upb/upb/mini_descriptor/decode.c', + 'third_party/upb/upb/mini_descriptor/internal/base92.c', + 'third_party/upb/upb/mini_descriptor/internal/encode.c', + 'third_party/upb/upb/mini_descriptor/link.c', + 'third_party/upb/upb/wire/decode.c', + 'third_party/upb/upb/wire/decode_fast.c', + 'third_party/upb/upb/wire/encode.c', + 'third_party/upb/upb/wire/eps_copy_input_stream.c', + 'third_party/upb/upb/wire/reader.c', + ], + }, + { + 'target_name': 'gtest', + 'type': 'static_library', + 'dependencies': [ + 're2', + 'absl/container:flat_hash_set', + 'absl/debugging:failure_signal_handler', + 'absl/debugging:stacktrace', + 'absl/debugging:symbolize', + 'absl/flags:flag', + 'absl/flags:parse', + 'absl/flags:reflection', + 'absl/flags:usage', + 'absl/strings:strings', + 'absl/types:any', + 'absl/types:optional', + 'absl/types:variant', + ], + 'sources': [ + 'third_party/googletest/googlemock/src/gmock-cardinalities.cc', + 'third_party/googletest/googlemock/src/gmock-internal-utils.cc', + 'third_party/googletest/googlemock/src/gmock-matchers.cc', + 'third_party/googletest/googlemock/src/gmock-spec-builders.cc', + 'third_party/googletest/googlemock/src/gmock.cc', + 'third_party/googletest/googletest/src/gtest-assertion-result.cc', + 'third_party/googletest/googletest/src/gtest-death-test.cc', + 'third_party/googletest/googletest/src/gtest-filepath.cc', + 'third_party/googletest/googletest/src/gtest-matchers.cc', + 'third_party/googletest/googletest/src/gtest-port.cc', + 'third_party/googletest/googletest/src/gtest-printers.cc', + 'third_party/googletest/googletest/src/gtest-test-part.cc', + 'third_party/googletest/googletest/src/gtest-typed-test.cc', + 'third_party/googletest/googletest/src/gtest.cc', + ], + }, + { + 'target_name': 're2', + 'type': 'static_library', + 'dependencies': [ + ], + 'sources': [ + 'third_party/re2/re2/bitstate.cc', + 'third_party/re2/re2/compile.cc', + 'third_party/re2/re2/dfa.cc', + 'third_party/re2/re2/filtered_re2.cc', + 'third_party/re2/re2/mimics_pcre.cc', + 'third_party/re2/re2/nfa.cc', + 'third_party/re2/re2/onepass.cc', + 'third_party/re2/re2/parse.cc', + 'third_party/re2/re2/perl_groups.cc', + 'third_party/re2/re2/prefilter.cc', + 'third_party/re2/re2/prefilter_tree.cc', + 'third_party/re2/re2/prog.cc', + 'third_party/re2/re2/re2.cc', + 'third_party/re2/re2/regexp.cc', + 'third_party/re2/re2/set.cc', + 'third_party/re2/re2/simplify.cc', + 'third_party/re2/re2/stringpiece.cc', + 'third_party/re2/re2/tostring.cc', + 'third_party/re2/re2/unicode_casefold.cc', + 'third_party/re2/re2/unicode_groups.cc', + 'third_party/re2/util/rune.cc', + 'third_party/re2/util/strutil.cc', + ], + }, + { + 'target_name': 'upb_base_lib', + 'type': 'static_library', + 'dependencies': [ + ], + 'sources': [ + 'third_party/upb/upb/base/status.c', + ], + }, + { + 'target_name': 'upb_json_lib', + 'type': 'static_library', + 'dependencies': [ + 'upb_message_lib', + 'utf8_range_lib', + ], + 'sources': [ + 'src/core/ext/upb-gen/google/protobuf/descriptor.upb_minitable.c', + 'third_party/upb/upb/json/decode.c', + 'third_party/upb/upb/json/encode.c', + 'third_party/upb/upb/lex/atoi.c', + 'third_party/upb/upb/lex/round_trip.c', + 'third_party/upb/upb/lex/strtod.c', + 'third_party/upb/upb/lex/unicode.c', + 'third_party/upb/upb/message/accessors.c', + 'third_party/upb/upb/mini_descriptor/build_enum.c', + 'third_party/upb/upb/mini_descriptor/decode.c', + 'third_party/upb/upb/mini_descriptor/internal/base92.c', + 'third_party/upb/upb/mini_descriptor/internal/encode.c', + 'third_party/upb/upb/mini_descriptor/link.c', + 'third_party/upb/upb/reflection/def_pool.c', + 'third_party/upb/upb/reflection/def_type.c', + 'third_party/upb/upb/reflection/desc_state.c', + 'third_party/upb/upb/reflection/enum_def.c', + 'third_party/upb/upb/reflection/enum_reserved_range.c', + 'third_party/upb/upb/reflection/enum_value_def.c', + 'third_party/upb/upb/reflection/extension_range.c', + 'third_party/upb/upb/reflection/field_def.c', + 'third_party/upb/upb/reflection/file_def.c', + 'third_party/upb/upb/reflection/internal/def_builder.c', + 'third_party/upb/upb/reflection/internal/strdup2.c', + 'third_party/upb/upb/reflection/message.c', + 'third_party/upb/upb/reflection/message_def.c', + 'third_party/upb/upb/reflection/message_reserved_range.c', + 'third_party/upb/upb/reflection/method_def.c', + 'third_party/upb/upb/reflection/oneof_def.c', + 'third_party/upb/upb/reflection/service_def.c', + 'third_party/upb/upb/wire/decode.c', + 'third_party/upb/upb/wire/decode_fast.c', + 'third_party/upb/upb/wire/encode.c', + 'third_party/upb/upb/wire/eps_copy_input_stream.c', + 'third_party/upb/upb/wire/reader.c', + ], + }, + { + 'target_name': 'upb_mem_lib', + 'type': 'static_library', + 'dependencies': [ + ], + 'sources': [ + 'third_party/upb/upb/mem/alloc.c', + 'third_party/upb/upb/mem/arena.c', + ], + }, + { + 'target_name': 'upb_message_lib', + 'type': 'static_library', + 'dependencies': [ + 'upb_base_lib', + 'upb_mem_lib', + ], + 'sources': [ + 'third_party/upb/upb/hash/common.c', + 'third_party/upb/upb/message/array.c', + 'third_party/upb/upb/message/map.c', + 'third_party/upb/upb/message/map_sorter.c', + 'third_party/upb/upb/message/message.c', + 'third_party/upb/upb/mini_table/extension_registry.c', + 'third_party/upb/upb/mini_table/internal/message.c', + 'third_party/upb/upb/mini_table/message.c', + ], + }, + { + 'target_name': 'upb_textformat_lib', + 'type': 'static_library', + 'dependencies': [ + 'upb_message_lib', + 'utf8_range_lib', + ], + 'sources': [ + 'src/core/ext/upb-gen/google/protobuf/descriptor.upb_minitable.c', + 'third_party/upb/upb/lex/atoi.c', + 'third_party/upb/upb/lex/round_trip.c', + 'third_party/upb/upb/lex/strtod.c', + 'third_party/upb/upb/lex/unicode.c', + 'third_party/upb/upb/message/accessors.c', + 'third_party/upb/upb/mini_descriptor/build_enum.c', + 'third_party/upb/upb/mini_descriptor/decode.c', + 'third_party/upb/upb/mini_descriptor/internal/base92.c', + 'third_party/upb/upb/mini_descriptor/internal/encode.c', + 'third_party/upb/upb/mini_descriptor/link.c', + 'third_party/upb/upb/reflection/def_pool.c', + 'third_party/upb/upb/reflection/def_type.c', + 'third_party/upb/upb/reflection/desc_state.c', + 'third_party/upb/upb/reflection/enum_def.c', + 'third_party/upb/upb/reflection/enum_reserved_range.c', + 'third_party/upb/upb/reflection/enum_value_def.c', + 'third_party/upb/upb/reflection/extension_range.c', + 'third_party/upb/upb/reflection/field_def.c', + 'third_party/upb/upb/reflection/file_def.c', + 'third_party/upb/upb/reflection/internal/def_builder.c', + 'third_party/upb/upb/reflection/internal/strdup2.c', + 'third_party/upb/upb/reflection/message.c', + 'third_party/upb/upb/reflection/message_def.c', + 'third_party/upb/upb/reflection/message_reserved_range.c', + 'third_party/upb/upb/reflection/method_def.c', + 'third_party/upb/upb/reflection/oneof_def.c', + 'third_party/upb/upb/reflection/service_def.c', + 'third_party/upb/upb/text/encode.c', + 'third_party/upb/upb/wire/decode.c', + 'third_party/upb/upb/wire/decode_fast.c', + 'third_party/upb/upb/wire/encode.c', + 'third_party/upb/upb/wire/eps_copy_input_stream.c', + 'third_party/upb/upb/wire/reader.c', + ], + }, + { + 'target_name': 'utf8_range_lib', + 'type': 'static_library', + 'dependencies': [ + ], + 'sources': [ + 'third_party/utf8_range/naive.c', + 'third_party/utf8_range/range2-neon.c', + 'third_party/utf8_range/range2-sse.c', + ], + }, + { + 'target_name': 'z', + 'type': 'static_library', + 'dependencies': [ + ], + 'sources': [ + 'third_party/zlib/adler32.c', + 'third_party/zlib/compress.c', + 'third_party/zlib/crc32.c', + 'third_party/zlib/deflate.c', + 'third_party/zlib/infback.c', + 'third_party/zlib/inffast.c', + 'third_party/zlib/inflate.c', + 'third_party/zlib/inftrees.c', + 'third_party/zlib/trees.c', + 'third_party/zlib/uncompr.c', + 'third_party/zlib/zutil.c', + ], + }, + { + 'target_name': 'benchmark_helpers', + 'type': 'static_library', + 'dependencies': [ + 'benchmark', + 'grpc++_unsecure', + 'grpc_test_util_unsecure', + 'grpc++_test_config', + ], + 'sources': [ + 'src/proto/grpc/testing/echo.proto', + 'src/proto/grpc/testing/echo_messages.proto', + 'src/proto/grpc/testing/simple_messages.proto', + 'src/proto/grpc/testing/xds/v3/orca_load_report.proto', + 'test/core/util/cmdline.cc', + 'test/core/util/fuzzer_util.cc', + 'test/core/util/grpc_profiler.cc', + 'test/core/util/histogram.cc', + 'test/core/util/mock_endpoint.cc', + 'test/core/util/parse_hexstring.cc', + 'test/core/util/resolve_localhost_ip46.cc', + 'test/core/util/slice_splitter.cc', + 'test/core/util/tracer_util.cc', + 'test/cpp/microbenchmarks/helpers.cc', + ], + }, + { + 'target_name': 'grpc++', + 'type': 'static_library', + 'dependencies': [ + 'grpc', + 'protobuf', + ], + 'sources': [ + 'src/core/ext/transport/binder/client/binder_connector.cc', + 'src/core/ext/transport/binder/client/channel_create.cc', + 'src/core/ext/transport/binder/client/channel_create_impl.cc', + 'src/core/ext/transport/binder/client/connection_id_generator.cc', + 'src/core/ext/transport/binder/client/endpoint_binder_pool.cc', + 'src/core/ext/transport/binder/client/jni_utils.cc', + 'src/core/ext/transport/binder/client/security_policy_setting.cc', + 'src/core/ext/transport/binder/security_policy/binder_security_policy.cc', + 'src/core/ext/transport/binder/server/binder_server.cc', + 'src/core/ext/transport/binder/server/binder_server_credentials.cc', + 'src/core/ext/transport/binder/transport/binder_transport.cc', + 'src/core/ext/transport/binder/utils/ndk_binder.cc', + 'src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc', + 'src/core/ext/transport/binder/wire_format/binder_android.cc', + 'src/core/ext/transport/binder/wire_format/binder_constants.cc', + 'src/core/ext/transport/binder/wire_format/transaction.cc', + 'src/core/ext/transport/binder/wire_format/wire_reader_impl.cc', + 'src/core/ext/transport/binder/wire_format/wire_writer.cc', + 'src/cpp/client/channel_cc.cc', + 'src/cpp/client/client_callback.cc', + 'src/cpp/client/client_context.cc', + 'src/cpp/client/client_interceptor.cc', + 'src/cpp/client/client_stats_interceptor.cc', + 'src/cpp/client/create_channel.cc', + 'src/cpp/client/create_channel_internal.cc', + 'src/cpp/client/create_channel_posix.cc', + 'src/cpp/client/insecure_credentials.cc', + 'src/cpp/client/secure_credentials.cc', + 'src/cpp/client/xds_credentials.cc', + 'src/cpp/common/alarm.cc', + 'src/cpp/common/auth_property_iterator.cc', + 'src/cpp/common/channel_arguments.cc', + 'src/cpp/common/completion_queue_cc.cc', + 'src/cpp/common/resource_quota_cc.cc', + 'src/cpp/common/rpc_method.cc', + 'src/cpp/common/secure_auth_context.cc', + 'src/cpp/common/secure_channel_arguments.cc', + 'src/cpp/common/secure_create_auth_context.cc', + 'src/cpp/common/tls_certificate_provider.cc', + 'src/cpp/common/tls_certificate_verifier.cc', + 'src/cpp/common/tls_credentials_options.cc', + 'src/cpp/common/validate_service_config.cc', + 'src/cpp/common/version_cc.cc', + 'src/cpp/server/async_generic_service.cc', + 'src/cpp/server/backend_metric_recorder.cc', + 'src/cpp/server/channel_argument_option.cc', + 'src/cpp/server/create_default_thread_pool.cc', + 'src/cpp/server/external_connection_acceptor_impl.cc', + 'src/cpp/server/health/default_health_check_service.cc', + 'src/cpp/server/health/health_check_service.cc', + 'src/cpp/server/health/health_check_service_server_builder_option.cc', + 'src/cpp/server/insecure_server_credentials.cc', + 'src/cpp/server/secure_server_credentials.cc', + 'src/cpp/server/server_builder.cc', + 'src/cpp/server/server_callback.cc', + 'src/cpp/server/server_cc.cc', + 'src/cpp/server/server_context.cc', + 'src/cpp/server/server_posix.cc', + 'src/cpp/server/xds_server_builder.cc', + 'src/cpp/server/xds_server_credentials.cc', + 'src/cpp/thread_manager/thread_manager.cc', + 'src/cpp/util/byte_buffer_cc.cc', + 'src/cpp/util/status.cc', + 'src/cpp/util/string_ref.cc', + 'src/cpp/util/time_cc.cc', + ], + }, + { + 'target_name': 'grpc++_alts', + 'type': 'static_library', + 'dependencies': [ + 'grpc++', + ], + 'sources': [ + 'src/cpp/common/alts_context.cc', + 'src/cpp/common/alts_util.cc', + ], + }, + { + 'target_name': 'grpc++_error_details', + 'type': 'static_library', + 'dependencies': [ + 'grpc++', + ], + 'sources': [ + 'src/cpp/util/error_details.cc', + ], + }, + { + 'target_name': 'grpc++_reflection', + 'type': 'static_library', + 'dependencies': [ + 'grpc++', + ], + 'sources': [ + 'src/proto/grpc/reflection/v1/reflection.proto', + 'src/proto/grpc/reflection/v1alpha/reflection.proto', + 'src/cpp/ext/proto_server_reflection.cc', + 'src/cpp/ext/proto_server_reflection_plugin.cc', + ], + }, + { + 'target_name': 'grpc++_test', + 'type': 'static_library', + 'dependencies': [ + 'gtest', + 'grpc++', + ], + 'sources': [ + 'src/cpp/client/channel_test_peer.cc', + ], + }, + { + 'target_name': 'grpc++_test_config', + 'type': 'static_library', + 'dependencies': [ + 'absl/flags:parse', + 'gpr', + ], + 'sources': [ + 'test/cpp/util/test_config_cc.cc', + ], + }, + { + 'target_name': 'grpc++_test_util', + 'type': 'static_library', + 'dependencies': [ + 'grpc++', + 'grpc_test_util', + ], + 'sources': [ + 'src/core/lib/gpr/subprocess_posix.cc', + 'src/core/lib/gpr/subprocess_windows.cc', + '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/util/cmdline.cc', + 'test/core/util/fuzzer_util.cc', + 'test/core/util/grpc_profiler.cc', + 'test/core/util/histogram.cc', + 'test/core/util/mock_endpoint.cc', + 'test/core/util/parse_hexstring.cc', + 'test/core/util/resolve_localhost_ip46.cc', + 'test/core/util/slice_splitter.cc', + 'test/core/util/tracer_util.cc', + 'test/cpp/util/byte_buffer_proto_helper.cc', + 'test/cpp/util/create_test_channel.cc', + 'test/cpp/util/string_ref_helper.cc', + 'test/cpp/util/subprocess.cc', + 'test/cpp/util/test_credentials_provider.cc', + ], + }, + { + 'target_name': 'grpc++_unsecure', + 'type': 'static_library', + 'dependencies': [ + 'grpc_unsecure', + 'protobuf', + ], + 'sources': [ + 'src/cpp/client/channel_cc.cc', + 'src/cpp/client/client_callback.cc', + 'src/cpp/client/client_context.cc', + 'src/cpp/client/client_interceptor.cc', + 'src/cpp/client/client_stats_interceptor.cc', + 'src/cpp/client/create_channel.cc', + 'src/cpp/client/create_channel_internal.cc', + 'src/cpp/client/create_channel_posix.cc', + 'src/cpp/client/insecure_credentials.cc', + 'src/cpp/common/alarm.cc', + 'src/cpp/common/channel_arguments.cc', + 'src/cpp/common/completion_queue_cc.cc', + 'src/cpp/common/insecure_create_auth_context.cc', + 'src/cpp/common/resource_quota_cc.cc', + 'src/cpp/common/rpc_method.cc', + 'src/cpp/common/validate_service_config.cc', + 'src/cpp/common/version_cc.cc', + 'src/cpp/server/async_generic_service.cc', + 'src/cpp/server/backend_metric_recorder.cc', + 'src/cpp/server/channel_argument_option.cc', + 'src/cpp/server/create_default_thread_pool.cc', + 'src/cpp/server/external_connection_acceptor_impl.cc', + 'src/cpp/server/health/default_health_check_service.cc', + 'src/cpp/server/health/health_check_service.cc', + 'src/cpp/server/health/health_check_service_server_builder_option.cc', + 'src/cpp/server/insecure_server_credentials.cc', + 'src/cpp/server/server_builder.cc', + 'src/cpp/server/server_callback.cc', + 'src/cpp/server/server_cc.cc', + 'src/cpp/server/server_context.cc', + 'src/cpp/server/server_posix.cc', + 'src/cpp/thread_manager/thread_manager.cc', + 'src/cpp/util/byte_buffer_cc.cc', + 'src/cpp/util/status.cc', + 'src/cpp/util/string_ref.cc', + 'src/cpp/util/time_cc.cc', + ], + }, + { + 'target_name': 'grpc_authorization_provider', + 'type': 'static_library', + 'dependencies': [ + 'upb_message_lib', + 're2', + 'utf8_range_lib', + 'z', + 'absl/base:config', + 'absl/base:no_destructor', + 'absl/cleanup:cleanup', + 'absl/container:flat_hash_map', + 'absl/container:flat_hash_set', + 'absl/container:inlined_vector', + 'absl/functional:function_ref', + 'absl/hash:hash', + 'absl/meta:type_traits', + 'absl/random:bit_gen_ref', + 'absl/random:distributions', + 'absl/status:statusor', + 'absl/types:span', + 'absl/utility:utility', + 'cares', + 'gpr', + 'address_sorting', + ], + 'sources': [ + 'src/core/ext/upb-gen/google/protobuf/any.upb_minitable.c', + 'src/core/ext/upb-gen/google/protobuf/descriptor.upb_minitable.c', + 'src/core/ext/upb-gen/google/rpc/status.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/gcp/altscontext.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/gcp/handshaker.upb_minitable.c', + 'src/core/ext/upb-gen/src/proto/grpc/gcp/transport_security_common.upb_minitable.c', + 'src/core/lib/address_utils/parse_address.cc', + 'src/core/lib/address_utils/sockaddr_utils.cc', + 'src/core/lib/backoff/backoff.cc', + 'src/core/lib/backoff/random_early_detection.cc', + 'src/core/lib/channel/call_tracer.cc', + 'src/core/lib/channel/channel_args.cc', + 'src/core/lib/channel/channel_args_preconditioning.cc', + 'src/core/lib/channel/channel_stack.cc', + 'src/core/lib/channel/channel_stack_builder.cc', + 'src/core/lib/channel/channel_stack_builder_impl.cc', + 'src/core/lib/channel/channel_stack_trace.cc', + 'src/core/lib/channel/channel_trace.cc', + 'src/core/lib/channel/channelz.cc', + 'src/core/lib/channel/channelz_registry.cc', + 'src/core/lib/channel/connected_channel.cc', + 'src/core/lib/channel/metrics.cc', + 'src/core/lib/channel/promise_based_filter.cc', + 'src/core/lib/channel/status_util.cc', + 'src/core/lib/compression/compression.cc', + 'src/core/lib/compression/compression_internal.cc', + 'src/core/lib/compression/message_compress.cc', + 'src/core/lib/config/core_configuration.cc', + 'src/core/lib/debug/event_log.cc', + 'src/core/lib/debug/histogram_view.cc', + 'src/core/lib/debug/stats.cc', + 'src/core/lib/debug/stats_data.cc', + 'src/core/lib/debug/trace.cc', + 'src/core/lib/event_engine/ares_resolver.cc', + 'src/core/lib/event_engine/cf_engine/cf_engine.cc', + 'src/core/lib/event_engine/cf_engine/cfstream_endpoint.cc', + 'src/core/lib/event_engine/cf_engine/dns_service_resolver.cc', + 'src/core/lib/event_engine/channel_args_endpoint_config.cc', + 'src/core/lib/event_engine/default_event_engine.cc', + 'src/core/lib/event_engine/default_event_engine_factory.cc', + 'src/core/lib/event_engine/event_engine.cc', + 'src/core/lib/event_engine/forkable.cc', + 'src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc', + 'src/core/lib/event_engine/posix_engine/ev_poll_posix.cc', + 'src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc', + 'src/core/lib/event_engine/posix_engine/internal_errqueue.cc', + 'src/core/lib/event_engine/posix_engine/lockfree_event.cc', + 'src/core/lib/event_engine/posix_engine/native_posix_dns_resolver.cc', + 'src/core/lib/event_engine/posix_engine/posix_endpoint.cc', + 'src/core/lib/event_engine/posix_engine/posix_engine.cc', + 'src/core/lib/event_engine/posix_engine/posix_engine_listener.cc', + 'src/core/lib/event_engine/posix_engine/posix_engine_listener_utils.cc', + 'src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc', + 'src/core/lib/event_engine/posix_engine/timer.cc', + 'src/core/lib/event_engine/posix_engine/timer_heap.cc', + 'src/core/lib/event_engine/posix_engine/timer_manager.cc', + 'src/core/lib/event_engine/posix_engine/traced_buffer_list.cc', + 'src/core/lib/event_engine/posix_engine/wakeup_fd_eventfd.cc', + 'src/core/lib/event_engine/posix_engine/wakeup_fd_pipe.cc', + 'src/core/lib/event_engine/posix_engine/wakeup_fd_posix_default.cc', + 'src/core/lib/event_engine/resolved_address.cc', + 'src/core/lib/event_engine/shim.cc', + 'src/core/lib/event_engine/slice.cc', + 'src/core/lib/event_engine/slice_buffer.cc', + 'src/core/lib/event_engine/tcp_socket_utils.cc', + 'src/core/lib/event_engine/thread_pool/thread_count.cc', + 'src/core/lib/event_engine/thread_pool/thread_pool_factory.cc', + 'src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc', + 'src/core/lib/event_engine/thready_event_engine/thready_event_engine.cc', + 'src/core/lib/event_engine/time_util.cc', + 'src/core/lib/event_engine/trace.cc', + 'src/core/lib/event_engine/utils.cc', + 'src/core/lib/event_engine/windows/grpc_polled_fd_windows.cc', + 'src/core/lib/event_engine/windows/iocp.cc', + 'src/core/lib/event_engine/windows/native_windows_dns_resolver.cc', + 'src/core/lib/event_engine/windows/win_socket.cc', + 'src/core/lib/event_engine/windows/windows_endpoint.cc', + 'src/core/lib/event_engine/windows/windows_engine.cc', + 'src/core/lib/event_engine/windows/windows_listener.cc', + 'src/core/lib/event_engine/work_queue/basic_work_queue.cc', + 'src/core/lib/experiments/config.cc', + 'src/core/lib/experiments/experiments.cc', + 'src/core/lib/gprpp/load_file.cc', + 'src/core/lib/gprpp/per_cpu.cc', + 'src/core/lib/gprpp/ref_counted_string.cc', + 'src/core/lib/gprpp/status_helper.cc', + 'src/core/lib/gprpp/time.cc', + 'src/core/lib/gprpp/time_averaged_stats.cc', + 'src/core/lib/gprpp/validation_errors.cc', + 'src/core/lib/gprpp/work_serializer.cc', + 'src/core/lib/handshaker/proxy_mapper_registry.cc', + 'src/core/lib/iomgr/buffer_list.cc', + 'src/core/lib/iomgr/call_combiner.cc', + 'src/core/lib/iomgr/cfstream_handle.cc', + 'src/core/lib/iomgr/closure.cc', + 'src/core/lib/iomgr/combiner.cc', + 'src/core/lib/iomgr/dualstack_socket_posix.cc', + 'src/core/lib/iomgr/endpoint.cc', + 'src/core/lib/iomgr/endpoint_cfstream.cc', + 'src/core/lib/iomgr/endpoint_pair_posix.cc', + 'src/core/lib/iomgr/endpoint_pair_windows.cc', + 'src/core/lib/iomgr/error.cc', + 'src/core/lib/iomgr/error_cfstream.cc', + 'src/core/lib/iomgr/ev_apple.cc', + 'src/core/lib/iomgr/ev_epoll1_linux.cc', + 'src/core/lib/iomgr/ev_poll_posix.cc', + 'src/core/lib/iomgr/ev_posix.cc', + 'src/core/lib/iomgr/ev_windows.cc', + 'src/core/lib/iomgr/event_engine_shims/closure.cc', + 'src/core/lib/iomgr/event_engine_shims/endpoint.cc', + 'src/core/lib/iomgr/event_engine_shims/tcp_client.cc', + 'src/core/lib/iomgr/exec_ctx.cc', + 'src/core/lib/iomgr/executor.cc', + 'src/core/lib/iomgr/fork_posix.cc', + 'src/core/lib/iomgr/fork_windows.cc', + 'src/core/lib/iomgr/gethostname_fallback.cc', + 'src/core/lib/iomgr/gethostname_host_name_max.cc', + 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_posix.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc', + 'src/core/lib/iomgr/internal_errqueue.cc', + 'src/core/lib/iomgr/iocp_windows.cc', + 'src/core/lib/iomgr/iomgr.cc', + 'src/core/lib/iomgr/iomgr_internal.cc', + 'src/core/lib/iomgr/iomgr_posix.cc', + 'src/core/lib/iomgr/iomgr_posix_cfstream.cc', + 'src/core/lib/iomgr/iomgr_windows.cc', + 'src/core/lib/iomgr/lockfree_event.cc', + 'src/core/lib/iomgr/polling_entity.cc', + 'src/core/lib/iomgr/pollset.cc', + 'src/core/lib/iomgr/pollset_set.cc', + 'src/core/lib/iomgr/pollset_set_windows.cc', + 'src/core/lib/iomgr/pollset_windows.cc', + 'src/core/lib/iomgr/resolve_address.cc', + 'src/core/lib/iomgr/resolve_address_posix.cc', + 'src/core/lib/iomgr/resolve_address_windows.cc', + 'src/core/lib/iomgr/sockaddr_utils_posix.cc', + 'src/core/lib/iomgr/socket_factory_posix.cc', + 'src/core/lib/iomgr/socket_mutator.cc', + 'src/core/lib/iomgr/socket_utils_common_posix.cc', + 'src/core/lib/iomgr/socket_utils_linux.cc', + 'src/core/lib/iomgr/socket_utils_posix.cc', + 'src/core/lib/iomgr/socket_utils_windows.cc', + 'src/core/lib/iomgr/socket_windows.cc', + 'src/core/lib/iomgr/systemd_utils.cc', + 'src/core/lib/iomgr/tcp_client.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_posix.cc', + 'src/core/lib/iomgr/tcp_server.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_server_utils_posix_noifaddrs.cc', + 'src/core/lib/iomgr/tcp_server_windows.cc', + 'src/core/lib/iomgr/tcp_windows.cc', + 'src/core/lib/iomgr/timer.cc', + 'src/core/lib/iomgr/timer_generic.cc', + 'src/core/lib/iomgr/timer_heap.cc', + 'src/core/lib/iomgr/timer_manager.cc', + 'src/core/lib/iomgr/unix_sockets_posix.cc', + 'src/core/lib/iomgr/unix_sockets_posix_noop.cc', + 'src/core/lib/iomgr/vsock.cc', + 'src/core/lib/iomgr/wakeup_fd_eventfd.cc', + 'src/core/lib/iomgr/wakeup_fd_nospecial.cc', + 'src/core/lib/iomgr/wakeup_fd_pipe.cc', + 'src/core/lib/iomgr/wakeup_fd_posix.cc', + 'src/core/lib/json/json_reader.cc', + 'src/core/lib/json/json_writer.cc', + 'src/core/lib/matchers/matchers.cc', + 'src/core/lib/promise/activity.cc', + 'src/core/lib/promise/party.cc', + 'src/core/lib/promise/trace.cc', + 'src/core/lib/resource_quota/api.cc', + 'src/core/lib/resource_quota/arena.cc', + 'src/core/lib/resource_quota/memory_quota.cc', + 'src/core/lib/resource_quota/periodic_update.cc', + 'src/core/lib/resource_quota/resource_quota.cc', + 'src/core/lib/resource_quota/thread_quota.cc', + 'src/core/lib/resource_quota/trace.cc', + 'src/core/lib/security/authorization/audit_logging.cc', + 'src/core/lib/security/authorization/authorization_policy_provider_vtable.cc', + 'src/core/lib/security/authorization/evaluate_args.cc', + 'src/core/lib/security/authorization/grpc_authorization_engine.cc', + 'src/core/lib/security/authorization/grpc_authorization_policy_provider.cc', + 'src/core/lib/security/authorization/grpc_server_authz_filter.cc', + 'src/core/lib/security/authorization/matchers.cc', + 'src/core/lib/security/authorization/rbac_policy.cc', + 'src/core/lib/security/authorization/rbac_translator.cc', + 'src/core/lib/security/authorization/stdout_logger.cc', + 'src/core/lib/security/certificate_provider/certificate_provider_registry.cc', + 'src/core/lib/security/context/security_context.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc', + 'src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc', + 'src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc', + 'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc', + 'src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc', + 'src/core/lib/security/credentials/call_creds_util.cc', + 'src/core/lib/security/credentials/composite/composite_credentials.cc', + 'src/core/lib/security/credentials/credentials.cc', + 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', + 'src/core/lib/security/credentials/tls/tls_utils.cc', + 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', + 'src/core/lib/security/security_connector/load_system_roots_supported.cc', + 'src/core/lib/security/security_connector/load_system_roots_windows.cc', + 'src/core/lib/security/security_connector/security_connector.cc', + 'src/core/lib/security/transport/client_auth_filter.cc', + 'src/core/lib/security/transport/legacy_server_auth_filter.cc', + 'src/core/lib/security/transport/secure_endpoint.cc', + 'src/core/lib/security/transport/security_handshaker.cc', + 'src/core/lib/security/transport/server_auth_filter.cc', + 'src/core/lib/security/transport/tsi_error.cc', + 'src/core/lib/security/util/json_util.cc', + 'src/core/lib/slice/b64.cc', + 'src/core/lib/slice/percent_encoding.cc', + 'src/core/lib/slice/slice.cc', + 'src/core/lib/slice/slice_buffer.cc', + 'src/core/lib/slice/slice_refcount.cc', + 'src/core/lib/slice/slice_string_helpers.cc', + 'src/core/lib/surface/api_trace.cc', + 'src/core/lib/surface/byte_buffer.cc', + 'src/core/lib/surface/byte_buffer_reader.cc', + 'src/core/lib/surface/call.cc', + 'src/core/lib/surface/call_details.cc', + 'src/core/lib/surface/call_log_batch.cc', + 'src/core/lib/surface/channel.cc', + 'src/core/lib/surface/channel_init.cc', + 'src/core/lib/surface/channel_stack_type.cc', + 'src/core/lib/surface/completion_queue.cc', + 'src/core/lib/surface/completion_queue_factory.cc', + 'src/core/lib/surface/event_string.cc', + 'src/core/lib/surface/init_internally.cc', + 'src/core/lib/surface/lame_client.cc', + 'src/core/lib/surface/metadata_array.cc', + 'src/core/lib/surface/validate_metadata.cc', + 'src/core/lib/surface/version.cc', + 'src/core/lib/surface/wait_for_cq_end_op.cc', + 'src/core/lib/transport/batch_builder.cc', + 'src/core/lib/transport/call_filters.cc', + 'src/core/lib/transport/call_final_info.cc', + 'src/core/lib/transport/call_size_estimator.cc', + 'src/core/lib/transport/call_spine.cc', + 'src/core/lib/transport/connectivity_state.cc', + 'src/core/lib/transport/error_utils.cc', + 'src/core/lib/transport/handshaker.cc', + 'src/core/lib/transport/handshaker_registry.cc', + 'src/core/lib/transport/message.cc', + 'src/core/lib/transport/metadata.cc', + 'src/core/lib/transport/metadata_batch.cc', + 'src/core/lib/transport/parsed_metadata.cc', + 'src/core/lib/transport/status_conversion.cc', + 'src/core/lib/transport/timeout_encoding.cc', + 'src/core/lib/transport/transport.cc', + 'src/core/lib/transport/transport_op_string.cc', + 'src/core/lib/uri/uri_parser.cc', + 'src/core/load_balancing/lb_policy.cc', + 'src/core/load_balancing/lb_policy_registry.cc', + 'src/core/resolver/endpoint_addresses.cc', + 'src/core/resolver/resolver.cc', + 'src/core/resolver/resolver_registry.cc', + 'src/core/service_config/service_config_parser.cc', + 'src/core/tsi/alts/handshaker/transport_security_common_api.cc', + 'src/core/tsi/transport_security.cc', + 'src/core/tsi/transport_security_grpc.cc', + 'third_party/upb/upb/message/accessors.c', + 'third_party/upb/upb/mini_descriptor/build_enum.c', + 'third_party/upb/upb/mini_descriptor/decode.c', + 'third_party/upb/upb/mini_descriptor/internal/base92.c', + 'third_party/upb/upb/mini_descriptor/internal/encode.c', + 'third_party/upb/upb/mini_descriptor/link.c', + 'third_party/upb/upb/wire/decode.c', + 'third_party/upb/upb/wire/decode_fast.c', + 'third_party/upb/upb/wire/encode.c', + 'third_party/upb/upb/wire/eps_copy_input_stream.c', + 'third_party/upb/upb/wire/reader.c', + ], + }, + { + 'target_name': 'grpc_plugin_support', + 'type': 'static_library', + 'dependencies': [ + 'protobuf', + 'protoc', + ], + 'sources': [ + 'src/compiler/cpp_generator.cc', + 'src/compiler/csharp_generator.cc', + 'src/compiler/node_generator.cc', + 'src/compiler/objective_c_generator.cc', + 'src/compiler/php_generator.cc', + 'src/compiler/proto_parser_helper.cc', + 'src/compiler/python_generator.cc', + 'src/compiler/ruby_generator.cc', + ], + }, + { + 'target_name': 'grpcpp_channelz', + 'type': 'static_library', + 'dependencies': [ + 'grpc++', + ], + 'sources': [ + 'src/proto/grpc/channelz/channelz.proto', + 'src/cpp/server/channelz/channelz_service.cc', + 'src/cpp/server/channelz/channelz_service_plugin.cc', + ], + }, + { + 'target_name': 'boringssl', + 'type': 'static_library', + 'dependencies': [ + ], + 'sources': [ + 'third_party/boringssl-with-bazel/err_data.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_bitstr.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_bool.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_d2i_fp.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_dup.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_gentm.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_i2d_fp.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_int.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_mbstr.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_object.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_octet.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_strex.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_strnid.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_time.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_type.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/a_utctm.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/asn1_lib.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/asn1_par.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/asn_pack.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/f_int.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/f_string.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/posix_time.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/tasn_dec.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/tasn_enc.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/tasn_fre.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/tasn_new.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/tasn_typ.c', + 'third_party/boringssl-with-bazel/src/crypto/asn1/tasn_utl.c', + 'third_party/boringssl-with-bazel/src/crypto/base64/base64.c', + 'third_party/boringssl-with-bazel/src/crypto/bio/bio.c', + 'third_party/boringssl-with-bazel/src/crypto/bio/bio_mem.c', + 'third_party/boringssl-with-bazel/src/crypto/bio/connect.c', + 'third_party/boringssl-with-bazel/src/crypto/bio/errno.c', + 'third_party/boringssl-with-bazel/src/crypto/bio/fd.c', + 'third_party/boringssl-with-bazel/src/crypto/bio/file.c', + 'third_party/boringssl-with-bazel/src/crypto/bio/hexdump.c', + 'third_party/boringssl-with-bazel/src/crypto/bio/pair.c', + 'third_party/boringssl-with-bazel/src/crypto/bio/printf.c', + 'third_party/boringssl-with-bazel/src/crypto/bio/socket.c', + 'third_party/boringssl-with-bazel/src/crypto/bio/socket_helper.c', + 'third_party/boringssl-with-bazel/src/crypto/blake2/blake2.c', + 'third_party/boringssl-with-bazel/src/crypto/bn_extra/bn_asn1.c', + 'third_party/boringssl-with-bazel/src/crypto/bn_extra/convert.c', + 'third_party/boringssl-with-bazel/src/crypto/buf/buf.c', + 'third_party/boringssl-with-bazel/src/crypto/bytestring/asn1_compat.c', + 'third_party/boringssl-with-bazel/src/crypto/bytestring/ber.c', + 'third_party/boringssl-with-bazel/src/crypto/bytestring/cbb.c', + 'third_party/boringssl-with-bazel/src/crypto/bytestring/cbs.c', + 'third_party/boringssl-with-bazel/src/crypto/bytestring/unicode.c', + 'third_party/boringssl-with-bazel/src/crypto/chacha/chacha.c', + 'third_party/boringssl-with-bazel/src/crypto/cipher_extra/cipher_extra.c', + 'third_party/boringssl-with-bazel/src/crypto/cipher_extra/derive_key.c', + 'third_party/boringssl-with-bazel/src/crypto/cipher_extra/e_aesctrhmac.c', + 'third_party/boringssl-with-bazel/src/crypto/cipher_extra/e_aesgcmsiv.c', + 'third_party/boringssl-with-bazel/src/crypto/cipher_extra/e_chacha20poly1305.c', + 'third_party/boringssl-with-bazel/src/crypto/cipher_extra/e_des.c', + 'third_party/boringssl-with-bazel/src/crypto/cipher_extra/e_null.c', + 'third_party/boringssl-with-bazel/src/crypto/cipher_extra/e_rc2.c', + 'third_party/boringssl-with-bazel/src/crypto/cipher_extra/e_rc4.c', + 'third_party/boringssl-with-bazel/src/crypto/cipher_extra/e_tls.c', + 'third_party/boringssl-with-bazel/src/crypto/cipher_extra/tls_cbc.c', + 'third_party/boringssl-with-bazel/src/crypto/conf/conf.c', + 'third_party/boringssl-with-bazel/src/crypto/cpu_aarch64_apple.c', + 'third_party/boringssl-with-bazel/src/crypto/cpu_aarch64_fuchsia.c', + 'third_party/boringssl-with-bazel/src/crypto/cpu_aarch64_linux.c', + 'third_party/boringssl-with-bazel/src/crypto/cpu_aarch64_openbsd.c', + 'third_party/boringssl-with-bazel/src/crypto/cpu_aarch64_sysreg.c', + 'third_party/boringssl-with-bazel/src/crypto/cpu_aarch64_win.c', + 'third_party/boringssl-with-bazel/src/crypto/cpu_arm_freebsd.c', + 'third_party/boringssl-with-bazel/src/crypto/cpu_arm_linux.c', + 'third_party/boringssl-with-bazel/src/crypto/cpu_intel.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/curve25519_64_adx.c', + 'third_party/boringssl-with-bazel/src/crypto/curve25519/spake25519.c', + 'third_party/boringssl-with-bazel/src/crypto/des/des.c', + 'third_party/boringssl-with-bazel/src/crypto/dh_extra/dh_asn1.c', + 'third_party/boringssl-with-bazel/src/crypto/dh_extra/params.c', + 'third_party/boringssl-with-bazel/src/crypto/digest_extra/digest_extra.c', + 'third_party/boringssl-with-bazel/src/crypto/dsa/dsa.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/err/err.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/evp.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/evp_asn1.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/evp_ctx.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/p_dsa_asn1.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/p_ec.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/p_ec_asn1.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/p_ed25519.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/p_ed25519_asn1.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/p_hkdf.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/p_rsa.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/p_rsa_asn1.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/p_x25519.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/p_x25519_asn1.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/pbkdf.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/print.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/scrypt.c', + 'third_party/boringssl-with-bazel/src/crypto/evp/sign.c', + 'third_party/boringssl-with-bazel/src/crypto/ex_data.c', + 'third_party/boringssl-with-bazel/src/crypto/fipsmodule/bcm.c', + 'third_party/boringssl-with-bazel/src/crypto/fipsmodule/fips_shared_support.c', + 'third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c', + 'third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c', + 'third_party/boringssl-with-bazel/src/crypto/keccak/keccak.c', + 'third_party/boringssl-with-bazel/src/crypto/kyber/kyber.c', + 'third_party/boringssl-with-bazel/src/crypto/lhash/lhash.c', + 'third_party/boringssl-with-bazel/src/crypto/mem.c', + 'third_party/boringssl-with-bazel/src/crypto/obj/obj.c', + 'third_party/boringssl-with-bazel/src/crypto/obj/obj_xref.c', + 'third_party/boringssl-with-bazel/src/crypto/pem/pem_all.c', + 'third_party/boringssl-with-bazel/src/crypto/pem/pem_info.c', + 'third_party/boringssl-with-bazel/src/crypto/pem/pem_lib.c', + 'third_party/boringssl-with-bazel/src/crypto/pem/pem_oth.c', + 'third_party/boringssl-with-bazel/src/crypto/pem/pem_pk8.c', + 'third_party/boringssl-with-bazel/src/crypto/pem/pem_pkey.c', + 'third_party/boringssl-with-bazel/src/crypto/pem/pem_x509.c', + 'third_party/boringssl-with-bazel/src/crypto/pem/pem_xaux.c', + 'third_party/boringssl-with-bazel/src/crypto/pkcs7/pkcs7.c', + 'third_party/boringssl-with-bazel/src/crypto/pkcs7/pkcs7_x509.c', + 'third_party/boringssl-with-bazel/src/crypto/pkcs8/p5_pbev2.c', + 'third_party/boringssl-with-bazel/src/crypto/pkcs8/pkcs8.c', + 'third_party/boringssl-with-bazel/src/crypto/pkcs8/pkcs8_x509.c', + 'third_party/boringssl-with-bazel/src/crypto/poly1305/poly1305.c', + 'third_party/boringssl-with-bazel/src/crypto/poly1305/poly1305_arm.c', + 'third_party/boringssl-with-bazel/src/crypto/poly1305/poly1305_vec.c', + 'third_party/boringssl-with-bazel/src/crypto/pool/pool.c', + 'third_party/boringssl-with-bazel/src/crypto/rand_extra/deterministic.c', + 'third_party/boringssl-with-bazel/src/crypto/rand_extra/forkunsafe.c', + 'third_party/boringssl-with-bazel/src/crypto/rand_extra/getentropy.c', + 'third_party/boringssl-with-bazel/src/crypto/rand_extra/ios.c', + 'third_party/boringssl-with-bazel/src/crypto/rand_extra/passive.c', + 'third_party/boringssl-with-bazel/src/crypto/rand_extra/rand_extra.c', + 'third_party/boringssl-with-bazel/src/crypto/rand_extra/trusty.c', + 'third_party/boringssl-with-bazel/src/crypto/rand_extra/windows.c', + 'third_party/boringssl-with-bazel/src/crypto/rc4/rc4.c', + 'third_party/boringssl-with-bazel/src/crypto/refcount.c', + 'third_party/boringssl-with-bazel/src/crypto/rsa_extra/rsa_asn1.c', + 'third_party/boringssl-with-bazel/src/crypto/rsa_extra/rsa_crypt.c', + 'third_party/boringssl-with-bazel/src/crypto/rsa_extra/rsa_print.c', + 'third_party/boringssl-with-bazel/src/crypto/siphash/siphash.c', + 'third_party/boringssl-with-bazel/src/crypto/spx/address.c', + 'third_party/boringssl-with-bazel/src/crypto/spx/fors.c', + 'third_party/boringssl-with-bazel/src/crypto/spx/merkle.c', + 'third_party/boringssl-with-bazel/src/crypto/spx/spx.c', + 'third_party/boringssl-with-bazel/src/crypto/spx/spx_util.c', + 'third_party/boringssl-with-bazel/src/crypto/spx/thash.c', + 'third_party/boringssl-with-bazel/src/crypto/spx/wots.c', + 'third_party/boringssl-with-bazel/src/crypto/stack/stack.c', + 'third_party/boringssl-with-bazel/src/crypto/thread.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/trust_token/voprf.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_verify.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/algorithm.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/asn1_gen.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/by_dir.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/by_file.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/i2d_pr.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/name_print.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/policy.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/rsa_pss.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/t_crl.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/t_req.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/t_x509.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/t_x509a.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_akey.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_akeya.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_alt.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_bcons.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_bitst.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_conf.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_cpols.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_crld.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_enum.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_extku.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_genn.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_ia5.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_info.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_int.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_lib.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_ncons.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_ocsp.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_pcons.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_pmaps.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_prn.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_purp.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_skey.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/v3_utl.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_att.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_cmp.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_d2.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_def.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_ext.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_lu.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_obj.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_req.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_trs.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_txt.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_v3.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_vfy.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509_vpm.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509cset.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509name.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509rset.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x509spki.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_algor.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_all.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_attrib.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_crl.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_exten.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_name.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_pubkey.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_req.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_sig.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_spki.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_val.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_x509.c', + 'third_party/boringssl-with-bazel/src/crypto/x509/x_x509a.c', + 'third_party/boringssl-with-bazel/src/ssl/bio_ssl.cc', + 'third_party/boringssl-with-bazel/src/ssl/d1_both.cc', + 'third_party/boringssl-with-bazel/src/ssl/d1_lib.cc', + 'third_party/boringssl-with-bazel/src/ssl/d1_pkt.cc', + 'third_party/boringssl-with-bazel/src/ssl/d1_srtp.cc', + 'third_party/boringssl-with-bazel/src/ssl/dtls_method.cc', + 'third_party/boringssl-with-bazel/src/ssl/dtls_record.cc', + 'third_party/boringssl-with-bazel/src/ssl/encrypted_client_hello.cc', + 'third_party/boringssl-with-bazel/src/ssl/extensions.cc', + 'third_party/boringssl-with-bazel/src/ssl/handoff.cc', + 'third_party/boringssl-with-bazel/src/ssl/handshake.cc', + 'third_party/boringssl-with-bazel/src/ssl/handshake_client.cc', + 'third_party/boringssl-with-bazel/src/ssl/handshake_server.cc', + 'third_party/boringssl-with-bazel/src/ssl/s3_both.cc', + 'third_party/boringssl-with-bazel/src/ssl/s3_lib.cc', + 'third_party/boringssl-with-bazel/src/ssl/s3_pkt.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_aead_ctx.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_asn1.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_buffer.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_cert.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_cipher.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_file.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_key_share.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_lib.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_privkey.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_session.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_stat.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_transcript.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_versions.cc', + 'third_party/boringssl-with-bazel/src/ssl/ssl_x509.cc', + 'third_party/boringssl-with-bazel/src/ssl/t1_enc.cc', + 'third_party/boringssl-with-bazel/src/ssl/tls13_both.cc', + 'third_party/boringssl-with-bazel/src/ssl/tls13_client.cc', + 'third_party/boringssl-with-bazel/src/ssl/tls13_enc.cc', + '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', + ], + }, + { + 'target_name': 'boringssl_test_util', + 'type': 'static_library', + 'dependencies': [ + ], + 'sources': [ + 'third_party/boringssl-with-bazel/src/crypto/test/abi_test.cc', + 'third_party/boringssl-with-bazel/src/crypto/test/file_test.cc', + 'third_party/boringssl-with-bazel/src/crypto/test/test_util.cc', + 'third_party/boringssl-with-bazel/src/crypto/test/wycheproof_util.cc', + ], + }, + { + 'target_name': 'benchmark', + 'type': 'static_library', + 'dependencies': [ + ], + 'sources': [ + 'third_party/benchmark/src/benchmark.cc', + 'third_party/benchmark/src/benchmark_api_internal.cc', + 'third_party/benchmark/src/benchmark_main.cc', + 'third_party/benchmark/src/benchmark_name.cc', + 'third_party/benchmark/src/benchmark_register.cc', + 'third_party/benchmark/src/benchmark_runner.cc', + 'third_party/benchmark/src/check.cc', + 'third_party/benchmark/src/colorprint.cc', + 'third_party/benchmark/src/commandlineflags.cc', + 'third_party/benchmark/src/complexity.cc', + 'third_party/benchmark/src/console_reporter.cc', + 'third_party/benchmark/src/counter.cc', + 'third_party/benchmark/src/csv_reporter.cc', + 'third_party/benchmark/src/json_reporter.cc', + 'third_party/benchmark/src/perf_counters.cc', + 'third_party/benchmark/src/reporter.cc', + 'third_party/benchmark/src/statistics.cc', + 'third_party/benchmark/src/string_util.cc', + 'third_party/benchmark/src/sysinfo.cc', + 'third_party/benchmark/src/timers.cc', + ], + }, + ] +} diff --git a/package.xml b/package.xml index 23357d455f1..d1778bf0607 100644 --- a/package.xml +++ b/package.xml @@ -114,6 +114,8 @@ + + @@ -129,6 +131,8 @@ + + @@ -1243,6 +1247,8 @@ + + @@ -1468,6 +1474,7 @@ + diff --git a/src/core/BUILD b/src/core/BUILD index 56aa4f03aa8..830376847ef 100644 --- a/src/core/BUILD +++ b/src/core/BUILD @@ -3281,12 +3281,12 @@ grpc_cc_library( language = "c++", deps = [ "arena", + "call_destination", "grpc_service_config", "lb_policy", "unique_type_name", "//:call_tracer", - "//:gpr_public_hdrs", - "//:grpc_base", + "//:gpr", "//:legacy_context", ], ) @@ -7509,12 +7509,10 @@ grpc_cc_library( hdrs = [ "lib/transport/call_filters.h", ], - external_deps = [ - "absl/log:check", - "absl/log:log", - ], + external_deps = ["absl/log:check"], deps = [ "call_final_info", + "dump_args", "latch", "map", "message", @@ -7620,20 +7618,19 @@ grpc_cc_library( hdrs = [ "lib/transport/call_spine.h", ], - external_deps = [ - "absl/log:check", - "absl/log:log", - ], + external_deps = ["absl/log:check"], deps = [ "1999", "call_arena_allocator", "call_filters", + "dual_ref_counted", "for_each", "if", "latch", "message", "metadata", "pipe", + "prioritized_race", "promise_status", "status_flag", "try_seq", diff --git a/src/core/client_channel/client_channel.cc b/src/core/client_channel/client_channel.cc new file mode 100644 index 00000000000..77de1ab121d --- /dev/null +++ b/src/core/client_channel/client_channel.cc @@ -0,0 +1,1392 @@ +// 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 + +#include "src/core/client_channel/client_channel.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "absl/cleanup/cleanup.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/cord.h" +#include "absl/strings/numbers.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_join.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "absl/types/variant.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/client_channel/backup_poller.h" +#include "src/core/client_channel/client_channel_internal.h" +#include "src/core/client_channel/client_channel_service_config.h" +#include "src/core/client_channel/config_selector.h" +#include "src/core/client_channel/dynamic_filters.h" +#include "src/core/client_channel/global_subchannel_pool.h" +#include "src/core/client_channel/local_subchannel_pool.h" +#include "src/core/client_channel/retry_filter.h" +#include "src/core/client_channel/subchannel.h" +#include "src/core/client_channel/subchannel_interface_internal.h" +#include "src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/promise_based_filter.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/config/core_configuration.h" +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/experiments/experiments.h" +#include "src/core/lib/gprpp/crash.h" +#include "src/core/lib/gprpp/debug_location.h" +#include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/unique_type_name.h" +#include "src/core/lib/gprpp/work_serializer.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/iomgr/resolved_address.h" +#include "src/core/lib/promise/cancel_callback.h" +#include "src/core/lib/promise/context.h" +#include "src/core/lib/promise/exec_ctx_wakeup_scheduler.h" +#include "src/core/lib/promise/latch.h" +#include "src/core/lib/promise/loop.h" +#include "src/core/lib/promise/map.h" +#include "src/core/lib/promise/pipe.h" +#include "src/core/lib/promise/poll.h" +#include "src/core/lib/promise/promise.h" +#include "src/core/lib/promise/sleep.h" +#include "src/core/lib/promise/status_flag.h" +#include "src/core/lib/promise/try_seq.h" +#include "src/core/lib/resource_quota/resource_quota.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/slice/slice.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/surface/call.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/completion_queue.h" +#include "src/core/lib/transport/call_spine.h" +#include "src/core/lib/transport/connectivity_state.h" +#include "src/core/lib/transport/error_utils.h" +#include "src/core/lib/transport/metadata_batch.h" +#include "src/core/load_balancing/backend_metric_parser.h" +#include "src/core/load_balancing/child_policy_handler.h" +#include "src/core/load_balancing/lb_policy.h" +#include "src/core/load_balancing/lb_policy_registry.h" +#include "src/core/load_balancing/subchannel_interface.h" +#include "src/core/resolver/endpoint_addresses.h" +#include "src/core/resolver/resolver_registry.h" +#include "src/core/service_config/service_config_call_data.h" +#include "src/core/service_config/service_config_impl.h" +#include "src/core/telemetry/metrics.h" +#include "src/core/util/json/json.h" +#include "src/core/util/useful.h" + +namespace grpc_core { + +using grpc_event_engine::experimental::EventEngine; + +using internal::ClientChannelMethodParsedConfig; + +// Defined in legacy client channel filter. +// TODO(roth): Move these here when we remove the legacy filter. +extern TraceFlag grpc_client_channel_trace; +extern TraceFlag grpc_client_channel_call_trace; +extern TraceFlag grpc_client_channel_lb_call_trace; + +// +// ClientChannel::ResolverResultHandler +// + +class ClientChannel::ResolverResultHandler : public Resolver::ResultHandler { + public: + explicit ResolverResultHandler(RefCountedPtr client_channel) + : client_channel_(std::move(client_channel)) {} + + ~ResolverResultHandler() override { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: resolver shutdown complete", + client_channel_.get()); + } + } + + void ReportResult(Resolver::Result result) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*client_channel_->work_serializer_) { + client_channel_->OnResolverResultChangedLocked(std::move(result)); + } + + private: + RefCountedPtr client_channel_; +}; + +// +// ClientChannel::SubchannelWrapper +// + +// This class is a wrapper for Subchannel that hides details of the +// channel's implementation (such as the connected subchannel) from the +// LB policy API. +// +// 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 work_serializer. +class ClientChannel::SubchannelWrapper + : public SubchannelInterfaceWithCallDestination { + public: + SubchannelWrapper(RefCountedPtr client_channel, + RefCountedPtr subchannel); + ~SubchannelWrapper() override; + + void Orphaned() override; + void WatchConnectivityState( + std::unique_ptr watcher) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*client_channel_->work_serializer_); + void CancelConnectivityStateWatch( + ConnectivityStateWatcherInterface* watcher) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*client_channel_->work_serializer_); + + RefCountedPtr call_destination() override { + return subchannel_->call_destination(); + } + + void RequestConnection() override { subchannel_->RequestConnection(); } + + void ResetBackoff() override { subchannel_->ResetBackoff(); } + + void AddDataWatcher(std::unique_ptr watcher) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*client_channel_->work_serializer_); + void CancelDataWatcher(DataWatcherInterface* watcher) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*client_channel_->work_serializer_); + void ThrottleKeepaliveTime(int new_keepalive_time); + + private: + class WatcherWrapper; + + // A heterogenous lookup comparator for data watchers that allows + // unique_ptr keys to be looked up as raw pointers. + struct DataWatcherLessThan { + using is_transparent = void; + bool operator()(const std::unique_ptr& p1, + const std::unique_ptr& p2) const { + return p1 < p2; + } + bool operator()(const std::unique_ptr& p1, + const DataWatcherInterface* p2) const { + return p1.get() < p2; + } + bool operator()(const DataWatcherInterface* p1, + const std::unique_ptr& p2) const { + return p1 < p2.get(); + } + }; + + RefCountedPtr client_channel_; + RefCountedPtr subchannel_; + // Maps from the address of the watcher passed to us by the LB policy + // to the address of the WrapperWatcher that we passed to the underlying + // subchannel. This is needed so that when the LB policy calls + // CancelConnectivityStateWatch() with its watcher, we know the + // corresponding WrapperWatcher to cancel on the underlying subchannel. + std::map watcher_map_ + ABSL_GUARDED_BY(*client_channel_->work_serializer_); + std::set, DataWatcherLessThan> + data_watchers_ ABSL_GUARDED_BY(*client_channel_->work_serializer_); +}; + +// This wrapper provides a bridge between the internal Subchannel API +// and the SubchannelInterface API that we expose to LB policies. +// It implements Subchannel::ConnectivityStateWatcherInterface and wraps +// the instance of SubchannelInterface::ConnectivityStateWatcherInterface +// that was passed in by the LB policy. We pass an instance of this +// class to the underlying Subchannel, and when we get updates from +// the subchannel, we pass those on to the wrapped watcher to return +// the update to the LB policy. +// +// This class handles things like hopping into the WorkSerializer +// before passing notifications to the LB policy and propagating +// keepalive information betwen subchannels. +class ClientChannel::SubchannelWrapper::WatcherWrapper + : public Subchannel::ConnectivityStateWatcherInterface { + public: + WatcherWrapper( + std::unique_ptr + watcher, + RefCountedPtr subchannel_wrapper) + : watcher_(std::move(watcher)), + subchannel_wrapper_(std::move(subchannel_wrapper)) {} + + ~WatcherWrapper() override { + subchannel_wrapper_.reset(DEBUG_LOCATION, "WatcherWrapper"); + } + + void OnConnectivityStateChange( + RefCountedPtr self, + grpc_connectivity_state state, const absl::Status& status) override { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, + "client_channel=%p: connectivity change for subchannel " + "wrapper %p subchannel %p; hopping into work_serializer", + subchannel_wrapper_->client_channel_.get(), + subchannel_wrapper_.get(), + subchannel_wrapper_->subchannel_.get()); + } + self.release(); // Held by callback. + subchannel_wrapper_->client_channel_->work_serializer_->Run( + [this, state, status]() ABSL_EXCLUSIVE_LOCKS_REQUIRED( + *subchannel_wrapper_->client_channel_->work_serializer_) { + ApplyUpdateInControlPlaneWorkSerializer(state, status); + Unref(); + }, + DEBUG_LOCATION); + } + + grpc_pollset_set* interested_parties() override { return nullptr; } + + private: + void ApplyUpdateInControlPlaneWorkSerializer(grpc_connectivity_state state, + const absl::Status& status) + ABSL_EXCLUSIVE_LOCKS_REQUIRED( + *subchannel_wrapper_->client_channel_->work_serializer_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, + "client_channel=%p: processing connectivity change in work " + "serializer for subchannel wrapper %p subchannel %p watcher=%p " + "state=%s status=%s", + subchannel_wrapper_->client_channel_.get(), + subchannel_wrapper_.get(), subchannel_wrapper_->subchannel_.get(), + watcher_.get(), ConnectivityStateName(state), + status.ToString().c_str()); + } + absl::optional keepalive_throttling = + status.GetPayload(kKeepaliveThrottlingKey); + if (keepalive_throttling.has_value()) { + int new_keepalive_time = -1; + if (absl::SimpleAtoi(std::string(keepalive_throttling.value()), + &new_keepalive_time)) { + if (new_keepalive_time > + subchannel_wrapper_->client_channel_->keepalive_time_) { + subchannel_wrapper_->client_channel_->keepalive_time_ = + new_keepalive_time; + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, + "client_channel=%p: throttling keepalive time to %d", + subchannel_wrapper_->client_channel_.get(), + subchannel_wrapper_->client_channel_->keepalive_time_); + } + // Propagate the new keepalive time to all subchannels. This is so + // that new transports created by any subchannel (and not just the + // subchannel that received the GOAWAY), use the new keepalive time. + for (auto* subchannel_wrapper : + subchannel_wrapper_->client_channel_->subchannel_wrappers_) { + subchannel_wrapper->ThrottleKeepaliveTime(new_keepalive_time); + } + } + } else { + gpr_log(GPR_ERROR, + "client_channel=%p: Illegal keepalive throttling value %s", + subchannel_wrapper_->client_channel_.get(), + std::string(keepalive_throttling.value()).c_str()); + } + } + // Propagate status only in state TF. + // We specifically want to avoid propagating the status for + // state IDLE that the real subchannel gave us only for the + // purpose of keepalive propagation. + watcher_->OnConnectivityStateChange( + state, + state == GRPC_CHANNEL_TRANSIENT_FAILURE ? status : absl::OkStatus()); + } + + std::unique_ptr + watcher_; + RefCountedPtr subchannel_wrapper_; +}; + +ClientChannel::SubchannelWrapper::SubchannelWrapper( + RefCountedPtr client_channel, + RefCountedPtr subchannel) + : SubchannelInterfaceWithCallDestination( + GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace) + ? "SubchannelWrapper" + : nullptr), + client_channel_(std::move(client_channel)), + subchannel_(std::move(subchannel)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log( + GPR_INFO, + "client_channel=%p: creating subchannel wrapper %p for subchannel %p", + client_channel_.get(), this, subchannel_.get()); + } +#ifndef NDEBUG + DCHECK(client_channel_->work_serializer_->RunningInWorkSerializer()); +#endif + if (client_channel_->channelz_node_ != nullptr) { + auto* subchannel_node = subchannel_->channelz_node(); + if (subchannel_node != nullptr) { + auto it = + client_channel_->subchannel_refcount_map_.find(subchannel_.get()); + if (it == client_channel_->subchannel_refcount_map_.end()) { + client_channel_->channelz_node_->AddChildSubchannel( + subchannel_node->uuid()); + it = client_channel_->subchannel_refcount_map_ + .emplace(subchannel_.get(), 0) + .first; + } + ++it->second; + } + } + client_channel_->subchannel_wrappers_.insert(this); +} + +ClientChannel::SubchannelWrapper::~SubchannelWrapper() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, + "client_channel=%p: destroying subchannel wrapper %p " + "for subchannel %p", + client_channel_.get(), this, subchannel_.get()); + } +} + +void ClientChannel::SubchannelWrapper::Orphaned() { + // Make sure we clean up the channel's subchannel maps inside the + // WorkSerializer. + auto self = WeakRefAsSubclass(DEBUG_LOCATION, + "subchannel map cleanup"); + client_channel_->work_serializer_->Run( + [self]() ABSL_EXCLUSIVE_LOCKS_REQUIRED( + *self->client_channel_->work_serializer_) { + self->client_channel_->subchannel_wrappers_.erase(self.get()); + if (self->client_channel_->channelz_node_ != nullptr) { + auto* subchannel_node = self->subchannel_->channelz_node(); + if (subchannel_node != nullptr) { + auto it = self->client_channel_->subchannel_refcount_map_.find( + self->subchannel_.get()); + CHECK(it != self->client_channel_->subchannel_refcount_map_.end()); + --it->second; + if (it->second == 0) { + self->client_channel_->channelz_node_->RemoveChildSubchannel( + subchannel_node->uuid()); + self->client_channel_->subchannel_refcount_map_.erase(it); + } + } + } + }, + DEBUG_LOCATION); +} + +void ClientChannel::SubchannelWrapper::WatchConnectivityState( + std::unique_ptr watcher) { + auto& watcher_wrapper = watcher_map_[watcher.get()]; + CHECK(watcher_wrapper == nullptr); + watcher_wrapper = new WatcherWrapper( + std::move(watcher), + RefAsSubclass(DEBUG_LOCATION, "WatcherWrapper")); + subchannel_->WatchConnectivityState( + RefCountedPtr( + watcher_wrapper)); +} + +void ClientChannel::SubchannelWrapper::CancelConnectivityStateWatch( + ConnectivityStateWatcherInterface* watcher) { + auto it = watcher_map_.find(watcher); + CHECK(it != watcher_map_.end()); + subchannel_->CancelConnectivityStateWatch(it->second); + watcher_map_.erase(it); +} + +void ClientChannel::SubchannelWrapper::AddDataWatcher( + std::unique_ptr watcher) { + static_cast(watcher.get()) + ->SetSubchannel(subchannel_.get()); + CHECK(data_watchers_.insert(std::move(watcher)).second); +} + +void ClientChannel::SubchannelWrapper::CancelDataWatcher( + DataWatcherInterface* watcher) { + auto it = data_watchers_.find(watcher); + if (it != data_watchers_.end()) data_watchers_.erase(it); +} + +void ClientChannel::SubchannelWrapper::ThrottleKeepaliveTime( + int new_keepalive_time) { + subchannel_->ThrottleKeepaliveTime(new_keepalive_time); +} + +// +// ClientChannel::ClientChannelControlHelper +// + +class ClientChannel::ClientChannelControlHelper + : public LoadBalancingPolicy::ChannelControlHelper { + public: + explicit ClientChannelControlHelper( + RefCountedPtr client_channel) + : client_channel_(std::move(client_channel)) {} + + ~ClientChannelControlHelper() override { + client_channel_.reset(DEBUG_LOCATION, "ClientChannelControlHelper"); + } + + RefCountedPtr CreateSubchannel( + const grpc_resolved_address& address, const ChannelArgs& per_address_args, + const ChannelArgs& args) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*client_channel_->work_serializer_) { + // If shutting down, do nothing. + if (client_channel_->resolver_ == nullptr) return nullptr; + ChannelArgs subchannel_args = Subchannel::MakeSubchannelArgs( + args, per_address_args, client_channel_->subchannel_pool_, + client_channel_->default_authority_); + // Create subchannel. + RefCountedPtr subchannel = + client_channel_->client_channel_factory_->CreateSubchannel( + address, subchannel_args); + if (subchannel == nullptr) return nullptr; + // Make sure the subchannel has updated keepalive time. + subchannel->ThrottleKeepaliveTime(client_channel_->keepalive_time_); + // Create and return wrapper for the subchannel. + return MakeRefCounted(client_channel_, + std::move(subchannel)); + } + + void UpdateState( + grpc_connectivity_state state, const absl::Status& status, + RefCountedPtr picker) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*client_channel_->work_serializer_) { + if (client_channel_->resolver_ == nullptr) return; // Shutting down. + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + const char* extra = client_channel_->disconnect_error_.ok() + ? "" + : " (ignoring -- channel shutting down)"; + gpr_log(GPR_INFO, + "client_channel=%p: update: state=%s status=(%s) picker=%p%s", + client_channel_.get(), ConnectivityStateName(state), + status.ToString().c_str(), picker.get(), extra); + } + // Do update only if not shutting down. + if (client_channel_->disconnect_error_.ok()) { + client_channel_->UpdateStateAndPickerLocked(state, status, "helper", + std::move(picker)); + } + } + + void RequestReresolution() override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*client_channel_->work_serializer_) { + if (client_channel_->resolver_ == nullptr) return; // Shutting down. + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: started name re-resolving", + client_channel_.get()); + } + client_channel_->resolver_->RequestReresolutionLocked(); + } + + absl::string_view GetTarget() override { return client_channel_->target(); } + + absl::string_view GetAuthority() override { + return client_channel_->default_authority_; + } + + RefCountedPtr GetChannelCredentials() override { + return client_channel_->channel_args_.GetObject() + ->duplicate_without_call_credentials(); + } + + RefCountedPtr GetUnsafeChannelCredentials() + override { + return client_channel_->channel_args_.GetObject() + ->Ref(); + } + + EventEngine* GetEventEngine() override { + return client_channel_->event_engine(); + } + + GlobalStatsPluginRegistry::StatsPluginGroup& GetStatsPluginGroup() override { + return client_channel_->stats_plugin_group_; + } + + void AddTraceEvent(TraceSeverity severity, absl::string_view message) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*client_channel_->work_serializer_) { + if (client_channel_->resolver_ == nullptr) return; // Shutting down. + if (client_channel_->channelz_node_ != nullptr) { + client_channel_->channelz_node_->AddTraceEvent( + ConvertSeverityEnum(severity), + grpc_slice_from_copied_buffer(message.data(), message.size())); + } + } + + private: + static channelz::ChannelTrace::Severity ConvertSeverityEnum( + TraceSeverity severity) { + if (severity == TRACE_INFO) return channelz::ChannelTrace::Info; + if (severity == TRACE_WARNING) return channelz::ChannelTrace::Warning; + return channelz::ChannelTrace::Error; + } + + RefCountedPtr client_channel_; +}; + +// +// ClientChannel implementation +// + +namespace { + +RefCountedPtr GetSubchannelPool( + const ChannelArgs& args) { + if (args.GetBool(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL).value_or(false)) { + return MakeRefCounted(); + } + return GlobalSubchannelPool::instance(); +} + +} // namespace + +absl::StatusOr> ClientChannel::Create( + std::string target, ChannelArgs channel_args) { + gpr_log(GPR_ERROR, "ARGS: %s", channel_args.ToString().c_str()); + // Get URI to resolve, using proxy mapper if needed. + if (target.empty()) { + return absl::InternalError("target URI is empty in client channel"); + } + std::string uri_to_resolve = CoreConfiguration::Get() + .proxy_mapper_registry() + .MapName(target, &channel_args) + .value_or(target); + // Make sure the URI to resolve is valid, so that we know that + // resolver creation will succeed later. + if (!CoreConfiguration::Get().resolver_registry().IsValidTarget( + uri_to_resolve)) { + return absl::InvalidArgumentError( + absl::StrCat("invalid target URI: ", uri_to_resolve)); + } + // Get default service config. If none is specified via the client API, + // we use an empty config. + absl::optional service_config_json = + channel_args.GetString(GRPC_ARG_SERVICE_CONFIG); + if (!service_config_json.has_value()) service_config_json = "{}"; + auto default_service_config = + ServiceConfigImpl::Create(channel_args, *service_config_json); + if (!default_service_config.ok()) return default_service_config.status(); + // Strip out service config channel arg, so that it doesn't affect + // subchannel uniqueness when the args flow down to that layer. + channel_args = channel_args.Remove(GRPC_ARG_SERVICE_CONFIG); + // Check client channel factory. + auto* client_channel_factory = channel_args.GetObject(); + if (client_channel_factory == nullptr) { + return absl::InternalError( + "Missing client channel factory in args for client channel"); + } + auto* call_destination_factory = + channel_args.GetObject(); + if (call_destination_factory == nullptr) { + return absl::InternalError( + "Missing call destination factory in args for client channel"); + } + if (channel_args.GetObject() == nullptr) { + return absl::InternalError( + "Missing event engine in args for client channel"); + } + // Success. Construct channel. + return MakeOrphanable( + std::move(target), std::move(channel_args), std::move(uri_to_resolve), + std::move(*default_service_config), client_channel_factory, + call_destination_factory); +} + +namespace { +std::string GetDefaultAuthorityFromChannelArgs(const ChannelArgs& channel_args, + absl::string_view target) { + absl::optional default_authority = + channel_args.GetOwnedString(GRPC_ARG_DEFAULT_AUTHORITY); + if (!default_authority.has_value()) { + return CoreConfiguration::Get().resolver_registry().GetDefaultAuthority( + target); + } else { + return std::move(*default_authority); + } +} +} // namespace + +ClientChannel::ClientChannel( + std::string target, ChannelArgs channel_args, std::string uri_to_resolve, + RefCountedPtr default_service_config, + ClientChannelFactory* client_channel_factory, + CallDestinationFactory* call_destination_factory) + : Channel(std::move(target), channel_args), + channel_args_(std::move(channel_args)), + event_engine_(channel_args_.GetObjectRef()), + uri_to_resolve_(std::move(uri_to_resolve)), + service_config_parser_index_( + internal::ClientChannelServiceConfigParser::ParserIndex()), + default_service_config_(std::move(default_service_config)), + client_channel_factory_(client_channel_factory), + default_authority_( + GetDefaultAuthorityFromChannelArgs(channel_args_, this->target())), + channelz_node_(channel_args_.GetObject()), + call_arena_allocator_(MakeRefCounted( + channel_args_.GetObject() + ->memory_quota() + ->CreateMemoryAllocator("client_channel"), + 1024)), + idle_timeout_(GetClientIdleTimeout(channel_args_)), + resolver_data_for_calls_(ResolverDataForCalls{}), + picker_(nullptr), + call_destination_( + call_destination_factory->CreateCallDestination(picker_)), + work_serializer_(std::make_shared(event_engine_)), + state_tracker_("client_channel", GRPC_CHANNEL_IDLE), + subchannel_pool_(GetSubchannelPool(channel_args_)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: creating client_channel", this); + } + // Set initial keepalive time. + auto keepalive_arg = channel_args_.GetInt(GRPC_ARG_KEEPALIVE_TIME_MS); + if (keepalive_arg.has_value()) { + keepalive_time_ = Clamp(*keepalive_arg, 1, INT_MAX); + } else { + keepalive_time_ = -1; // unset + } + // Get stats plugins for channel. + experimental::StatsPluginChannelScope scope(this->target(), + default_authority_); + stats_plugin_group_ = + GlobalStatsPluginRegistry::GetStatsPluginsForChannel(scope); +} + +ClientChannel::~ClientChannel() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: destroying", this); + } +} + +void ClientChannel::Orphan() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: shutting down", this); + } + auto self = RefAsSubclass(); + work_serializer_->Run( + [self]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*self->work_serializer_) { + self->DestroyResolverAndLbPolicyLocked(); + }, + DEBUG_LOCATION); + // IncreaseCallCount() introduces a phony call and prevents the idle + // timer from being reset by other threads. + idle_state_.IncreaseCallCount(); + idle_activity_.Reset(); + Unref(); +} + +grpc_connectivity_state ClientChannel::CheckConnectivityState( + bool try_to_connect) { + // state_tracker_ is guarded by work_serializer_, which we're not + // holding here. But the one method of state_tracker_ that *is* + // thread-safe to call without external synchronization is the state() + // method, so we can disable thread-safety analysis for this one read. + grpc_connectivity_state state = + ABSL_TS_UNCHECKED_READ(state_tracker_).state(); + if (state == GRPC_CHANNEL_IDLE && try_to_connect) { + auto self = RefAsSubclass(); // Held by callback. + work_serializer_->Run( + [self]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*self->work_serializer_) { + self->TryToConnectLocked(); + }, + DEBUG_LOCATION); + } + return state; +} + +void ClientChannel::WatchConnectivityState(grpc_connectivity_state, Timestamp, + grpc_completion_queue*, void*) { + // TODO(ctiller): implement + Crash("not implemented"); +} + +void ClientChannel::AddConnectivityWatcher( + grpc_connectivity_state, + OrphanablePtr) { + Crash("not implemented"); + // TODO(ctiller): to make this work, need to change WorkSerializer to use + // absl::AnyInvocable<> instead of std::function<> + // work_serializer_->Run( + // [self = RefAsSubclass(), initial_state, + // watcher = std::move(watcher)]() + // ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_) { + // self->state_tracker_.AddWatcher(initial_state, std::move(watcher)); + // }, + // DEBUG_LOCATION); +} + +void ClientChannel::RemoveConnectivityWatcher( + AsyncConnectivityStateWatcherInterface* watcher) { + auto self = RefAsSubclass(); // Held by callback. + work_serializer_->Run( + [self, watcher]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*self->work_serializer_) { + self->state_tracker_.RemoveWatcher(watcher); + }, + DEBUG_LOCATION); +} + +void ClientChannel::GetInfo(const grpc_channel_info* info) { + MutexLock lock(&info_mu_); + if (info->lb_policy_name != nullptr) { + *info->lb_policy_name = gpr_strdup(info_lb_policy_name_.c_str()); + } + if (info->service_config_json != nullptr) { + *info->service_config_json = gpr_strdup(info_service_config_json_.c_str()); + } +} + +void ClientChannel::ResetConnectionBackoff() { + auto self = RefAsSubclass(); + work_serializer_->Run( + [self]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*self->work_serializer_) { + if (self->lb_policy_ != nullptr) self->lb_policy_->ResetBackoffLocked(); + }, + DEBUG_LOCATION); +} + +namespace { + +// A class to handle CQ completion for a ping. +class PingRequest { + public: + PingRequest(grpc_completion_queue* cq, void* tag) : cq_(cq), tag_(tag) { + grpc_cq_begin_op(cq, tag); + } + + // Triggers CQ completion and eventually deletes the PingRequest object. + void Complete(grpc_error_handle error) { + grpc_cq_end_op(cq_, tag_, error, Destroy, this, &completion_storage_); + } + + private: + static void Destroy(void* arg, grpc_cq_completion* /*storage*/) { + delete static_cast(arg); + } + + grpc_completion_queue* cq_; + void* tag_; + grpc_cq_completion completion_storage_; +}; + +} // namespace + +void ClientChannel::Ping(grpc_completion_queue*, void*) { + // TODO(ctiller): implement + Crash("not implemented"); +} + +grpc_call* ClientChannel::CreateCall(grpc_call*, uint32_t, + grpc_completion_queue*, grpc_pollset_set*, + Slice, absl::optional, Timestamp, + bool) { + // TODO(ctiller): code to convert from C-core batch API to v3 call, then + // invoke CreateCall(client_initial_metadata, arena) + // TODO(ctiller): make sure call holds a ref to ClientChannel for its entire + // lifetime + Crash("not implemented"); + return nullptr; +} + +CallInitiator ClientChannel::CreateCall( + ClientMetadataHandle client_initial_metadata) { + // Increment call count. + if (idle_timeout_ != Duration::Zero()) idle_state_.IncreaseCallCount(); + // Exit IDLE if needed. + CheckConnectivityState(/*try_to_connect=*/true); + // Create an initiator/unstarted-handler pair. + auto call = MakeCallPair( + std::move(client_initial_metadata), event_engine_.get(), + call_arena_allocator_->MakeArena(), call_arena_allocator_, nullptr); + // Spawn a promise to wait for the resolver result. + // This will eventually start the call. + call.initiator.SpawnGuardedUntilCallCompletes( + "wait-for-name-resolution", + [self = RefAsSubclass(), + unstarted_handler = std::move(call.handler)]() mutable { + const bool wait_for_ready = + unstarted_handler.UnprocessedClientInitialMetadata() + .GetOrCreatePointer(WaitForReady()) + ->value; + return Map( + // Wait for the resolver result. + CheckDelayed(self->resolver_data_for_calls_.NextWhen( + [wait_for_ready]( + const absl::StatusOr result) { + bool got_result = false; + // If the resolver reports an error but the call is + // wait_for_ready, keep waiting for the next result + // instead of failing the call. + if (!result.ok()) { + got_result = !wait_for_ready; + } else { + // Not an error. Make sure we actually have a result. + got_result = result->config_selector != nullptr; + } + return got_result; + })), + // Handle resolver result. + [self, unstarted_handler]( + std::tuple, bool> + result_and_delayed) mutable { + auto& resolver_data = std::get<0>(result_and_delayed); + const bool was_queued = std::get<1>(result_and_delayed); + if (!resolver_data.ok()) return resolver_data.status(); + // Apply service config to call. + absl::Status status = self->ApplyServiceConfigToCall( + *resolver_data->config_selector, + unstarted_handler.UnprocessedClientInitialMetadata()); + if (!status.ok()) return status; + // If the call was queued, add trace annotation. + if (was_queued) { + auto* call_tracer = + MaybeGetContext(); + if (call_tracer != nullptr) { + call_tracer->RecordAnnotation( + "Delayed name resolution complete."); + } + } + // Start the call on the destination provided by the + // resolver. + resolver_data->call_destination->StartCall( + std::move(unstarted_handler)); + return absl::OkStatus(); + }); + }); + // Return the initiator. + return std::move(call.initiator); +} + +void ClientChannel::CreateResolverLocked() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: starting name resolution for %s", + this, uri_to_resolve_.c_str()); + } + resolver_ = CoreConfiguration::Get().resolver_registry().CreateResolver( + uri_to_resolve_, channel_args_, nullptr, work_serializer_, + std::make_unique(RefAsSubclass())); + // Since the validity of the args was checked when the channel was created, + // CreateResolver() must return a non-null result. + CHECK(resolver_ != nullptr); + UpdateStateLocked(GRPC_CHANNEL_CONNECTING, absl::Status(), + "started resolving"); + resolver_->StartLocked(); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: created resolver=%p", this, + resolver_.get()); + } +} + +void ClientChannel::DestroyResolverAndLbPolicyLocked() { + if (resolver_ != nullptr) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: shutting down resolver=%p", this, + resolver_.get()); + } + resolver_.reset(); + saved_service_config_.reset(); + saved_config_selector_.reset(); + resolver_data_for_calls_.Set(ResolverDataForCalls{nullptr, nullptr}); + // Clear LB policy if set. + if (lb_policy_ != nullptr) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: shutting down lb_policy=%p", this, + lb_policy_.get()); + } + lb_policy_.reset(); + picker_.Set(nullptr); + } + } +} + +void ClientChannel::TryToConnectLocked() { + if (disconnect_error_.ok()) { + if (lb_policy_ != nullptr) { + lb_policy_->ExitIdleLocked(); + } else if (resolver_ == nullptr) { + CreateResolverLocked(); + } + } +} + +namespace { + +RefCountedPtr ChooseLbPolicy( + const Resolver::Result& resolver_result, + const internal::ClientChannelGlobalParsedConfig* parsed_service_config) { + // Prefer the LB policy config found in the service config. + if (parsed_service_config->parsed_lb_config() != nullptr) { + return parsed_service_config->parsed_lb_config(); + } + // Try the deprecated LB policy name from the service config. + // If not, try the setting from channel args. + absl::optional policy_name; + if (!parsed_service_config->parsed_deprecated_lb_policy().empty()) { + policy_name = parsed_service_config->parsed_deprecated_lb_policy(); + } else { + policy_name = resolver_result.args.GetString(GRPC_ARG_LB_POLICY_NAME); + bool requires_config = false; + if (policy_name.has_value() && + (!CoreConfiguration::Get() + .lb_policy_registry() + .LoadBalancingPolicyExists(*policy_name, &requires_config) || + requires_config)) { + if (requires_config) { + gpr_log(GPR_ERROR, + "LB policy: %s passed through channel_args must not " + "require a config. Using pick_first instead.", + std::string(*policy_name).c_str()); + } else { + gpr_log(GPR_ERROR, + "LB policy: %s passed through channel_args does not exist. " + "Using pick_first instead.", + std::string(*policy_name).c_str()); + } + policy_name = "pick_first"; + } + } + // Use pick_first if nothing was specified and we didn't select grpclb + // above. + if (!policy_name.has_value()) policy_name = "pick_first"; + // Now that we have the policy name, construct an empty config for it. + Json config_json = Json::FromArray({Json::FromObject({ + {std::string(*policy_name), Json::FromObject({})}, + })}); + auto lb_policy_config = + CoreConfiguration::Get().lb_policy_registry().ParseLoadBalancingConfig( + config_json); + // The policy name came from one of three places: + // - The deprecated loadBalancingPolicy field in the service config, + // in which case the code in ClientChannelServiceConfigParser + // already verified that the policy does not require a config. + // - One of the hard-coded values here, all of which are known to not + // require a config. + // - A channel arg, in which case we check that the specified policy exists + // and accepts an empty config. If not, we revert to using pick_first + // lb_policy + CHECK_OK(lb_policy_config); + return std::move(*lb_policy_config); +} + +} // namespace + +void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { + // Handle race conditions. + if (resolver_ == nullptr) return; + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: got resolver result", this); + } + // Grab resolver result health callback. + auto resolver_callback = std::move(result.result_health_callback); + absl::Status resolver_result_status; + // We only want to trace the address resolution in the follow cases: + // (a) Address resolution resulted in service config change. + // (b) Address resolution that causes number of backends to go from + // zero to non-zero. + // (c) Address resolution that causes number of backends to go from + // non-zero to zero. + // (d) Address resolution that causes a new LB policy to be created. + // + // We track a list of strings to eventually be concatenated and traced. + std::vector trace_strings; + const bool resolution_contains_addresses = + result.addresses.ok() && !result.addresses->empty(); + if (!resolution_contains_addresses && + previous_resolution_contained_addresses_) { + trace_strings.push_back("Address list became empty"); + } else if (resolution_contains_addresses && + !previous_resolution_contained_addresses_) { + trace_strings.push_back("Address list became non-empty"); + } + previous_resolution_contained_addresses_ = resolution_contains_addresses; + std::string service_config_error_string_storage; + if (!result.service_config.ok()) { + service_config_error_string_storage = + result.service_config.status().ToString(); + trace_strings.push_back(service_config_error_string_storage.c_str()); + } + // Choose the service config. + RefCountedPtr service_config; + RefCountedPtr config_selector; + if (!result.service_config.ok()) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, + "client_channel=%p: resolver returned service config error: %s", + this, result.service_config.status().ToString().c_str()); + } + // If the service config was invalid, then fallback to the + // previously returned service config, if any. + if (saved_service_config_ != nullptr) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, + "client_channel=%p: resolver returned invalid service config; " + "continuing to use previous service config", + this); + } + service_config = saved_service_config_; + config_selector = saved_config_selector_; + } else { + // We received a service config error and we don't have a + // previous service config to fall back to. Put the channel into + // TRANSIENT_FAILURE. + OnResolverErrorLocked(result.service_config.status()); + trace_strings.push_back("no valid service config"); + resolver_result_status = + absl::UnavailableError("no valid service config"); + } + } else if (*result.service_config == nullptr) { + // Resolver did not return any service config. + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, + "client_channel=%p: resolver returned no service config; " + "using default service config for channel", + this); + } + service_config = default_service_config_; + } else { + // Use ServiceConfig and ConfigSelector returned by resolver. + service_config = std::move(*result.service_config); + config_selector = result.args.GetObjectRef(); + } + // Note: The only case in which service_config is null here is if the + // resolver returned a service config error and we don't have a previous + // service config to fall back to. + if (service_config != nullptr) { + // Extract global config for client channel. + const internal::ClientChannelGlobalParsedConfig* parsed_service_config = + static_cast( + service_config->GetGlobalParsedConfig( + service_config_parser_index_)); + // Choose LB policy config. + RefCountedPtr lb_policy_config = + ChooseLbPolicy(result, parsed_service_config); + // Check if the ServiceConfig has changed. + const bool service_config_changed = + saved_service_config_ == nullptr || + service_config->json_string() != saved_service_config_->json_string(); + // Check if the ConfigSelector has changed. + const bool config_selector_changed = !ConfigSelector::Equals( + saved_config_selector_.get(), config_selector.get()); + // If either has changed, apply the global parameters now. + if (service_config_changed || config_selector_changed) { + // Update service config in control plane. + UpdateServiceConfigInControlPlaneLocked( + std::move(service_config), std::move(config_selector), + std::string(lb_policy_config->name())); + // 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("Service config changed"); + } else if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: service config not changed", this); + } + // Create or update LB policy, as needed. + resolver_result_status = CreateOrUpdateLbPolicyLocked( + std::move(lb_policy_config), + parsed_service_config->health_check_service_name(), std::move(result)); + // Start using new service config for calls. + // This needs to happen after the LB policy has been updated, since + // the ConfigSelector may need the LB policy to know about new + // destinations before it can send RPCs to those destinations. + if (service_config_changed || config_selector_changed) { + UpdateServiceConfigInDataPlaneLocked(); + } + } + // Invoke resolver callback if needed. + if (resolver_callback != nullptr) { + resolver_callback(std::move(resolver_result_status)); + } + // Add channel trace event. + if (!trace_strings.empty()) { + std::string message = + absl::StrCat("Resolution event: ", absl::StrJoin(trace_strings, ", ")); + if (channelz_node_ != nullptr) { + channelz_node_->AddTraceEvent(channelz::ChannelTrace::Severity::Info, + grpc_slice_from_cpp_string(message)); + } + } +} + +void ClientChannel::OnResolverErrorLocked(absl::Status status) { + if (resolver_ == nullptr) return; + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: resolver transient failure: %s", this, + status.ToString().c_str()); + } + // If we already have an LB policy from a previous resolution + // result, then we continue to let it set the connectivity state. + // Otherwise, we go into TRANSIENT_FAILURE. + if (lb_policy_ == nullptr) { + // Update connectivity state. + UpdateStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, status, + "resolver failure"); + // Send updated resolver result. + resolver_data_for_calls_.Set( + MaybeRewriteIllegalStatusCode(status, "resolver")); + } +} + +absl::Status ClientChannel::CreateOrUpdateLbPolicyLocked( + RefCountedPtr lb_policy_config, + const absl::optional& health_check_service_name, + Resolver::Result result) { + // Construct update. + LoadBalancingPolicy::UpdateArgs update_args; + if (!result.addresses.ok()) { + update_args.addresses = result.addresses.status(); + } else { + update_args.addresses = std::make_shared( + std::move(*result.addresses)); + } + update_args.config = std::move(lb_policy_config); + update_args.resolution_note = std::move(result.resolution_note); + // Remove the config selector from channel args so that we're not holding + // unnecessary refs that cause it to be destroyed somewhere other than in the + // WorkSerializer. + update_args.args = result.args.Remove(GRPC_ARG_CONFIG_SELECTOR); + // Add health check service name to channel args. + if (health_check_service_name.has_value()) { + update_args.args = update_args.args.Set(GRPC_ARG_HEALTH_CHECK_SERVICE_NAME, + *health_check_service_name); + } + // Create policy if needed. + if (lb_policy_ == nullptr) { + lb_policy_ = CreateLbPolicyLocked(update_args.args); + } + // Update the policy. + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: Updating child policy %p", this, + lb_policy_.get()); + } + return lb_policy_->UpdateLocked(std::move(update_args)); +} + +// Creates a new LB policy. +OrphanablePtr ClientChannel::CreateLbPolicyLocked( + const ChannelArgs& args) { + // The LB policy will start in state CONNECTING but will not + // necessarily send us an update synchronously, so set state to + // CONNECTING (in case the resolver had previously failed and put the + // channel into TRANSIENT_FAILURE) and make sure we have a queueing picker. + UpdateStateAndPickerLocked( + GRPC_CHANNEL_CONNECTING, absl::Status(), "started resolving", + MakeRefCounted(nullptr)); + // Now create the LB policy. + LoadBalancingPolicy::Args lb_policy_args; + lb_policy_args.work_serializer = work_serializer_; + lb_policy_args.channel_control_helper = + std::make_unique( + RefAsSubclass()); + lb_policy_args.args = args; + OrphanablePtr lb_policy = + MakeOrphanable(std::move(lb_policy_args), + &grpc_client_channel_trace); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: created new LB policy %p", this, + lb_policy.get()); + } + return lb_policy; +} + +void ClientChannel::UpdateServiceConfigInControlPlaneLocked( + RefCountedPtr service_config, + RefCountedPtr config_selector, std::string lb_policy_name) { + std::string service_config_json(service_config->json_string()); + // Update service config. + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: using service config: \"%s\"", this, + service_config_json.c_str()); + } + saved_service_config_ = std::move(service_config); + // Update config selector. + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: using ConfigSelector %p", this, + config_selector.get()); + } + saved_config_selector_ = std::move(config_selector); + // Update the data used by GetChannelInfo(). + { + MutexLock lock(&info_mu_); + info_lb_policy_name_ = std::move(lb_policy_name); + info_service_config_json_ = std::move(service_config_json); + } +} + +void ClientChannel::UpdateServiceConfigInDataPlaneLocked() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: switching to ConfigSelector %p", this, + saved_config_selector_.get()); + } + // Use default config selector if resolver didn't supply one. + RefCountedPtr config_selector = saved_config_selector_; + if (config_selector == nullptr) { + config_selector = + MakeRefCounted(saved_service_config_); + } + // Construct filter stack. + InterceptionChainBuilder builder(channel_args_.SetObject(this)); + if (idle_timeout_ != Duration::Zero()) { + builder.AddOnServerTrailingMetadata([this](ServerMetadata&) { + if (idle_state_.DecreaseCallCount()) StartIdleTimer(); + }); + } + CoreConfiguration::Get().channel_init().AddToInterceptionChainBuilder( + GRPC_CLIENT_CHANNEL, builder); + // TODO(roth): add filters returned by config selector + // Create call destination. + const bool enable_retries = + !channel_args_.WantMinimalStack() && + channel_args_.GetBool(GRPC_ARG_ENABLE_RETRIES).value_or(true); + if (enable_retries) { + Crash("call v3 stack does not yet support retries"); + } + auto top_of_stack_call_destination = builder.Build(call_destination_); + // Send result to data plane. + if (!top_of_stack_call_destination.ok()) { + resolver_data_for_calls_.Set(MaybeRewriteIllegalStatusCode( + top_of_stack_call_destination.status(), "channel construction")); + } else { + resolver_data_for_calls_.Set(ResolverDataForCalls{ + std::move(config_selector), std::move(*top_of_stack_call_destination)}); + } +} + +void ClientChannel::UpdateStateLocked(grpc_connectivity_state state, + const absl::Status& status, + const char* reason) { + if (state != GRPC_CHANNEL_SHUTDOWN && + state_tracker_.state() == GRPC_CHANNEL_SHUTDOWN) { + Crash("Illegal transition SHUTDOWN -> anything"); + } + state_tracker_.SetState(state, status, reason); + if (channelz_node_ != nullptr) { + channelz_node_->SetConnectivityState(state); + channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string( + channelz::ChannelNode::GetChannelConnectivityStateChangeString( + state))); + } +} + +void ClientChannel::UpdateStateAndPickerLocked( + grpc_connectivity_state state, const absl::Status& status, + const char* reason, + RefCountedPtr picker) { + UpdateStateLocked(state, status, reason); + picker_.Set(std::move(picker)); +} + +void ClientChannel::StartIdleTimer() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: idle timer started", this); + } + auto self = RefAsSubclass(); + auto promise = Loop([self]() { + return TrySeq(Sleep(Timestamp::Now() + self->idle_timeout_), + [self]() -> Poll> { + if (self->idle_state_.CheckTimer()) { + return Continue{}; + } else { + return absl::OkStatus(); + } + }); + }); + idle_activity_.Set(MakeActivity( + std::move(promise), ExecCtxWakeupScheduler{}, + [self = std::move(self)](absl::Status status) mutable { + if (status.ok()) { + self->work_serializer_->Run( + [self]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*self->work_serializer_) { + self->DestroyResolverAndLbPolicyLocked(); + self->UpdateStateAndPickerLocked( + GRPC_CHANNEL_IDLE, absl::OkStatus(), + "channel entering IDLE", nullptr); + // TODO(roth): In case there's a race condition, we + // might need to check for any calls that are queued + // waiting for a resolver result or an LB pick. + }, + DEBUG_LOCATION); + } + }, + GetContext())); +} + +absl::Status ClientChannel::ApplyServiceConfigToCall( + ConfigSelector& config_selector, + ClientMetadata& client_initial_metadata) const { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + gpr_log(GPR_INFO, "client_channel=%p: %sapplying service config to call", + this, GetContext()->DebugTag().c_str()); + } + // Create a ClientChannelServiceConfigCallData for the call. This stores + // a ref to the ServiceConfig and caches the right set of parsed configs + // to use for the call. The ClientChannelServiceConfigCallData will store + // itself in the call context, so that it can be accessed by filters + // below us in the stack, and it will be cleaned up when the call ends. + auto* service_config_call_data = + GetContext()->New( + GetContext(), GetContext()); + // Use the ConfigSelector to determine the config for the call. + absl::Status call_config_status = config_selector.GetCallConfig( + {&client_initial_metadata, GetContext(), + service_config_call_data}); + if (!call_config_status.ok()) { + return MaybeRewriteIllegalStatusCode(call_config_status, "ConfigSelector"); + } + // Apply our own method params to the call. + auto* method_params = static_cast( + service_config_call_data->GetMethodParsedConfig( + service_config_parser_index_)); + if (method_params != nullptr) { + // If the service config specifies a deadline, update the call's + // deadline timer. + if (method_params->timeout() != Duration::Zero()) { + Call* call = GetContext(); + const Timestamp per_method_deadline = + Timestamp::FromCycleCounterRoundUp(call->start_time()) + + method_params->timeout(); + call->UpdateDeadline(per_method_deadline); + } + // If the service config set wait_for_ready and the application + // did not explicitly set it, use the value from the service config. + auto* wait_for_ready = + client_initial_metadata.GetOrCreatePointer(WaitForReady()); + if (method_params->wait_for_ready().has_value() && + !wait_for_ready->explicitly_set) { + wait_for_ready->value = method_params->wait_for_ready().value(); + } + } + return absl::OkStatus(); +} + +} // namespace grpc_core diff --git a/src/core/client_channel/client_channel.h b/src/core/client_channel/client_channel.h new file mode 100644 index 00000000000..77d26f34e95 --- /dev/null +++ b/src/core/client_channel/client_channel.h @@ -0,0 +1,245 @@ +// +// 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. +// + +#ifndef GRPC_SRC_CORE_CLIENT_CHANNEL_CLIENT_CHANNEL_H +#define GRPC_SRC_CORE_CLIENT_CHANNEL_CLIENT_CHANNEL_H + +#include + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" + +#include "src/core/client_channel/client_channel_factory.h" +#include "src/core/client_channel/config_selector.h" +#include "src/core/client_channel/subchannel.h" +#include "src/core/ext/filters/channel_idle/idle_filter_state.h" +#include "src/core/lib/gprpp/single_set_ptr.h" +#include "src/core/lib/promise/observable.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/transport/metadata.h" +#include "src/core/load_balancing/lb_policy.h" +#include "src/core/resolver/resolver.h" +#include "src/core/service_config/service_config.h" + +namespace grpc_core { + +class ClientChannel : public Channel { + public: + using PickerObservable = + Observable>; + + class CallDestinationFactory { + public: + struct RawPointerChannelArgTag {}; + + static absl::string_view ChannelArgName() { + return "grpc.internal.client_channel_call_destination"; + } + + virtual RefCountedPtr CreateCallDestination( + PickerObservable) = 0; + + protected: + ~CallDestinationFactory() = default; + }; + + static absl::StatusOr> Create( + std::string target, ChannelArgs channel_args); + + // Do not instantiate directly -- use Create() instead. + ClientChannel(std::string target_uri, ChannelArgs args, + std::string uri_to_resolve, + RefCountedPtr default_service_config, + ClientChannelFactory* client_channel_factory, + CallDestinationFactory* call_destination_factory); + + ~ClientChannel() override; + + void Orphan() override; + + grpc_call* CreateCall(grpc_call* parent_call, uint32_t propagation_mask, + grpc_completion_queue* cq, + grpc_pollset_set* /*pollset_set_alternative*/, + Slice path, absl::optional authority, + Timestamp deadline, bool registered_method) override; + + CallInitiator CreateCall(ClientMetadataHandle client_initial_metadata); + + grpc_event_engine::experimental::EventEngine* event_engine() const override { + return event_engine_.get(); + } + + // TODO(ctiller): lame channels + bool IsLame() const override { return false; } + + bool SupportsConnectivityWatcher() const override { return true; } + + // Returns the current connectivity state. If try_to_connect is true, + // triggers a connection attempt if not already connected. + grpc_connectivity_state CheckConnectivityState(bool try_to_connect) override; + + void WatchConnectivityState(grpc_connectivity_state last_observed_state, + Timestamp deadline, grpc_completion_queue* cq, + void* tag) override; + + // Starts and stops a connectivity watch. The watcher will be initially + // notified as soon as the state changes from initial_state and then on + // every subsequent state change until either the watch is stopped or + // it is notified that the state has changed to SHUTDOWN. + // + // This is intended to be used when starting watches from code inside of + // C-core (e.g., for a nested control plane channel for things like xds). + void AddConnectivityWatcher( + grpc_connectivity_state initial_state, + OrphanablePtr watcher) override; + void RemoveConnectivityWatcher( + AsyncConnectivityStateWatcherInterface* watcher) override; + + void GetInfo(const grpc_channel_info* channel_info) override; + + void ResetConnectionBackoff() override; + + void Ping(grpc_completion_queue* cq, void* tag) override; + + // Flag that this object gets stored in channel args as a raw pointer. + struct RawPointerChannelArgTag {}; + static absl::string_view ChannelArgName() { + return "grpc.internal.client_channel"; + } + + private: + class ClientChannelControlHelper; + class ResolverResultHandler; + class SubchannelWrapper; + + void CreateResolverLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); + void DestroyResolverAndLbPolicyLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); + + void TryToConnectLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); + + void OnResolverResultChangedLocked(Resolver::Result result) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); + void OnResolverErrorLocked(absl::Status status) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); + + absl::Status CreateOrUpdateLbPolicyLocked( + RefCountedPtr lb_policy_config, + const absl::optional& health_check_service_name, + Resolver::Result result) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); + OrphanablePtr CreateLbPolicyLocked( + const ChannelArgs& args) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); + + void UpdateServiceConfigInControlPlaneLocked( + RefCountedPtr service_config, + RefCountedPtr config_selector, std::string lb_policy_name) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); + + void UpdateServiceConfigInDataPlaneLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); + + void UpdateStateLocked(grpc_connectivity_state state, + const absl::Status& status, const char* reason) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); + + void UpdateStateAndPickerLocked( + grpc_connectivity_state state, const absl::Status& status, + const char* reason, + RefCountedPtr picker) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); + + void StartIdleTimer(); + + // Applies service config settings from config_selector to the call. + // May modify call context and client_initial_metadata. + absl::Status ApplyServiceConfigToCall( + ConfigSelector& config_selector, + ClientMetadata& client_initial_metadata) const; + + const ChannelArgs channel_args_; + const std::shared_ptr + event_engine_; + const std::string uri_to_resolve_; + const size_t service_config_parser_index_; + const RefCountedPtr default_service_config_; + ClientChannelFactory* const client_channel_factory_; + const std::string default_authority_; + channelz::ChannelNode* const channelz_node_; + // TODO(ctiller): unify with Channel + const RefCountedPtr call_arena_allocator_; + GlobalStatsPluginRegistry::StatsPluginGroup stats_plugin_group_; + + // + // Idleness state. + // + const Duration idle_timeout_; + IdleFilterState idle_state_{false}; + SingleSetPtr idle_activity_; + + // + // Fields related to name resolution. + // + struct ResolverDataForCalls { + RefCountedPtr config_selector; + RefCountedPtr call_destination; + }; + Observable> resolver_data_for_calls_; + + // + // Fields related to LB picks. + // + PickerObservable picker_; + const RefCountedPtr call_destination_; + + // + // Fields used in the control plane. Guarded by work_serializer. + // + std::shared_ptr work_serializer_; + ConnectivityStateTracker state_tracker_ ABSL_GUARDED_BY(*work_serializer_); + OrphanablePtr resolver_ ABSL_GUARDED_BY(*work_serializer_); + bool previous_resolution_contained_addresses_ + ABSL_GUARDED_BY(*work_serializer_) = false; + RefCountedPtr saved_service_config_ + ABSL_GUARDED_BY(*work_serializer_); + RefCountedPtr saved_config_selector_ + ABSL_GUARDED_BY(*work_serializer_); + OrphanablePtr lb_policy_ + ABSL_GUARDED_BY(*work_serializer_); + RefCountedPtr subchannel_pool_ + ABSL_GUARDED_BY(*work_serializer_); + // The number of SubchannelWrapper instances referencing a given Subchannel. + std::map subchannel_refcount_map_ + ABSL_GUARDED_BY(*work_serializer_); + // The set of SubchannelWrappers that currently exist. + // No need to hold a ref, since the set is updated in the control-plane + // work_serializer when the SubchannelWrappers are created and destroyed. + absl::flat_hash_set subchannel_wrappers_ + ABSL_GUARDED_BY(*work_serializer_); + int keepalive_time_ ABSL_GUARDED_BY(*work_serializer_) = -1; + absl::Status disconnect_error_ ABSL_GUARDED_BY(*work_serializer_); + + // + // Fields accessed via GetChannelInfo(). + // + Mutex info_mu_; + std::string info_lb_policy_name_ ABSL_GUARDED_BY(info_mu_); + std::string info_service_config_json_ ABSL_GUARDED_BY(info_mu_); +}; + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_CLIENT_CHANNEL_CLIENT_CHANNEL_H diff --git a/src/core/client_channel/client_channel_filter.cc b/src/core/client_channel/client_channel_filter.cc index 3cb76ff8409..f0c58c1580f 100644 --- a/src/core/client_channel/client_channel_filter.cc +++ b/src/core/client_channel/client_channel_filter.cc @@ -1109,7 +1109,7 @@ class ClientChannelFilter::ClientChannelControlHelper final const ChannelArgs& args) override ABSL_EXCLUSIVE_LOCKS_REQUIRED(*chand_->work_serializer_) { if (chand_->resolver_ == nullptr) return nullptr; // Shutting down. - ChannelArgs subchannel_args = ClientChannelFilter::MakeSubchannelArgs( + ChannelArgs subchannel_args = Subchannel::MakeSubchannelArgs( args, per_address_args, chand_->subchannel_pool_, chand_->default_authority_); // Create subchannel. @@ -1359,31 +1359,6 @@ ClientChannelFilter::CreateLoadBalancedCallPromise( return call_ptr->MakeCallPromise(std::move(call_args), std::move(lb_call)); } -ChannelArgs ClientChannelFilter::MakeSubchannelArgs( - const ChannelArgs& channel_args, const ChannelArgs& address_args, - const RefCountedPtr& subchannel_pool, - const std::string& channel_default_authority) { - // Note that we start with the channel-level args and then apply the - // per-address args, so that if a value is present in both, the one - // in the channel-level args is used. This is particularly important - // for the GRPC_ARG_DEFAULT_AUTHORITY arg, which we want to allow - // resolvers to set on a per-address basis only if the application - // did not explicitly set it at the channel level. - return channel_args.UnionWith(address_args) - .SetObject(subchannel_pool) - // If we haven't already set the default authority arg (i.e., it - // was not explicitly set by the application nor overridden by - // the resolver), add it from the channel's default. - .SetIfUnset(GRPC_ARG_DEFAULT_AUTHORITY, channel_default_authority) - // Remove channel args that should not affect subchannel - // uniqueness. - .Remove(GRPC_ARG_HEALTH_CHECK_SERVICE_NAME) - .Remove(GRPC_ARG_INHIBIT_HEALTH_CHECKING) - .Remove(GRPC_ARG_CHANNELZ_CHANNEL_NODE) - // Remove all keys with the no-subchannel prefix. - .RemoveAllKeysWithPrefix(GRPC_ARG_NO_SUBCHANNEL_PREFIX); -} - void ClientChannelFilter::ReprocessQueuedResolverCalls() { for (CallData* calld : resolver_queued_calls_) { calld->RemoveCallFromResolverQueuedCallsLocked(); diff --git a/src/core/client_channel/client_channel_filter.h b/src/core/client_channel/client_channel_filter.h index 5bbafc68d68..9233c846c6f 100644 --- a/src/core/client_channel/client_channel_filter.h +++ b/src/core/client_channel/client_channel_filter.h @@ -86,9 +86,6 @@ // Channel arg key for server URI string. #define GRPC_ARG_SERVER_URI "grpc.server_uri" -// Channel arg containing a pointer to the ClientChannelFilter object. -#define GRPC_ARG_CLIENT_CHANNEL "grpc.internal.client_channel_filter" - // Max number of batches that can be pending on a call at any given // time. This includes one batch for each of the following ops: // recv_initial_metadata @@ -112,7 +109,9 @@ class ClientChannelFilter final { // Flag that this object gets stored in channel args as a raw pointer. struct RawPointerChannelArgTag {}; - static absl::string_view ChannelArgName() { return GRPC_ARG_CLIENT_CHANNEL; } + static absl::string_view ChannelArgName() { + return "grpc.internal.client_channel_filter"; + } static ArenaPromise MakeCallPromise( grpc_channel_element* elem, CallArgs call_args, @@ -166,12 +165,6 @@ class ClientChannelFilter final { CallArgs call_args, absl::AnyInvocable on_commit, bool is_transparent_retry); - // Exposed for testing only. - static ChannelArgs MakeSubchannelArgs( - const ChannelArgs& channel_args, const ChannelArgs& address_args, - const RefCountedPtr& subchannel_pool, - const std::string& channel_default_authority); - private: class CallData; class FilterBasedCallData; diff --git a/src/core/client_channel/client_channel_internal.h b/src/core/client_channel/client_channel_internal.h index a2c759ec7d6..b4d204834ab 100644 --- a/src/core/client_channel/client_channel_internal.h +++ b/src/core/client_channel/client_channel_internal.h @@ -29,6 +29,7 @@ #include "src/core/lib/channel/context.h" #include "src/core/lib/gprpp/unique_type_name.h" #include "src/core/lib/resource_quota/arena.h" +#include "src/core/lib/transport/call_destination.h" #include "src/core/load_balancing/lb_policy.h" #include "src/core/service_config/service_config_call_data.h" #include "src/core/telemetry/call_tracer.h" @@ -75,6 +76,13 @@ class ClientChannelServiceConfigCallData final : public ServiceConfigCallData { absl::AnyInvocable on_commit_; }; +class SubchannelInterfaceWithCallDestination : public SubchannelInterface { + public: + using SubchannelInterface::SubchannelInterface; + // Obtain the call destination for this subchannel. + virtual RefCountedPtr call_destination() = 0; +}; + } // namespace grpc_core #endif // GRPC_SRC_CORE_CLIENT_CHANNEL_CLIENT_CHANNEL_INTERNAL_H diff --git a/src/core/client_channel/load_balanced_call_destination.cc b/src/core/client_channel/load_balanced_call_destination.cc new file mode 100644 index 00000000000..4d702a5858c --- /dev/null +++ b/src/core/client_channel/load_balanced_call_destination.cc @@ -0,0 +1,335 @@ +// Copyright 2024 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/client_channel/load_balanced_call_destination.h" + +#include "src/core/client_channel/client_channel.h" +#include "src/core/client_channel/client_channel_internal.h" +#include "src/core/client_channel/subchannel.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/promise/loop.h" +#include "src/core/telemetry/call_tracer.h" + +namespace grpc_core { + +// Defined in legacy client channel filter. +// TODO(roth): Move these here when we remove the legacy filter. +extern TraceFlag grpc_client_channel_trace; +extern TraceFlag grpc_client_channel_call_trace; +extern TraceFlag grpc_client_channel_lb_call_trace; + +namespace { + +class LbMetadata : public LoadBalancingPolicy::MetadataInterface { + public: + explicit LbMetadata(grpc_metadata_batch* batch) : batch_(batch) {} + + void Add(absl::string_view key, absl::string_view value) override { + if (batch_ == nullptr) return; + // Gross, egregious hack to support legacy grpclb behavior. + // TODO(ctiller): Use a promise context for this once that plumbing is done. + if (key == GrpcLbClientStatsMetadata::key()) { + batch_->Set( + GrpcLbClientStatsMetadata(), + const_cast( + reinterpret_cast(value.data()))); + return; + } + batch_->Append(key, Slice::FromStaticString(value), + [key](absl::string_view error, const Slice& value) { + gpr_log(GPR_ERROR, "%s", + absl::StrCat(error, " key:", key, + " value:", value.as_string_view()) + .c_str()); + }); + } + + std::vector> TestOnlyCopyToVector() + override { + if (batch_ == nullptr) return {}; + Encoder encoder; + batch_->Encode(&encoder); + return encoder.Take(); + } + + absl::optional Lookup(absl::string_view key, + std::string* buffer) const override { + if (batch_ == nullptr) return absl::nullopt; + return batch_->GetStringValue(key, buffer); + } + + private: + class Encoder { + public: + void Encode(const Slice& key, const Slice& value) { + out_.emplace_back(std::string(key.as_string_view()), + std::string(value.as_string_view())); + } + + template + void Encode(Which, const typename Which::ValueType& value) { + auto value_slice = Which::Encode(value); + out_.emplace_back(std::string(Which::key()), + std::string(value_slice.as_string_view())); + } + + void Encode(GrpcTimeoutMetadata, + const typename GrpcTimeoutMetadata::ValueType&) {} + void Encode(HttpPathMetadata, const Slice&) {} + void Encode(HttpMethodMetadata, + const typename HttpMethodMetadata::ValueType&) {} + + std::vector> Take() { + return std::move(out_); + } + + private: + std::vector> out_; + }; + + grpc_metadata_batch* batch_; +}; + +void MaybeCreateCallAttemptTracer(bool is_transparent_retry) { + auto* call_tracer = MaybeGetContext(); + if (call_tracer == nullptr) return; + auto* tracer = call_tracer->StartNewAttempt(is_transparent_retry); + SetContext(tracer); +} + +class LbCallState : public ClientChannelLbCallState { + public: + void* Alloc(size_t size) override { return GetContext()->Alloc(size); } + + // Internal API to allow first-party LB policies to access per-call + // attributes set by the ConfigSelector. + ServiceConfigCallData::CallAttributeInterface* GetCallAttribute( + UniqueTypeName type) const override { + auto* service_config_call_data = GetContext(); + return service_config_call_data->GetCallAttribute(type); + } + + ClientCallTracer::CallAttemptTracer* GetCallAttemptTracer() const override { + auto* legacy_context = GetContext(); + return static_cast( + legacy_context[GRPC_CONTEXT_CALL_TRACER].value); + } +}; + +// TODO(roth): Remove this in favor of the gprpp Match() function once +// we can do that without breaking lock annotations. +template +T HandlePickResult( + LoadBalancingPolicy::PickResult* result, + std::function complete_func, + std::function queue_func, + std::function fail_func, + std::function drop_func) { + auto* complete_pick = + absl::get_if(&result->result); + if (complete_pick != nullptr) { + return complete_func(complete_pick); + } + auto* queue_pick = + absl::get_if(&result->result); + if (queue_pick != nullptr) { + return queue_func(queue_pick); + } + auto* fail_pick = + absl::get_if(&result->result); + if (fail_pick != nullptr) { + return fail_func(fail_pick); + } + auto* drop_pick = + absl::get_if(&result->result); + CHECK(drop_pick != nullptr); + return drop_func(drop_pick); +} + +// Does an LB pick for a call. Returns one of the following things: +// - Continue{}, meaning to queue the pick +// - a non-OK status, meaning to fail the call +// - a call destination, meaning that the pick is complete +// When the pick is complete, pushes client_initial_metadata onto +// call_initiator. Also adds the subchannel call tracker (if any) to +// context. +LoopCtl>> PickSubchannel( + LoadBalancingPolicy::SubchannelPicker& picker, + UnstartedCallHandler& unstarted_handler) { + // Perform LB pick. + auto& client_initial_metadata = + unstarted_handler.UnprocessedClientInitialMetadata(); + LoadBalancingPolicy::PickArgs pick_args; + Slice* path = client_initial_metadata.get_pointer(HttpPathMetadata()); + CHECK(path != nullptr); + pick_args.path = path->as_string_view(); + LbCallState lb_call_state; + pick_args.call_state = &lb_call_state; + LbMetadata initial_metadata(&client_initial_metadata); + pick_args.initial_metadata = &initial_metadata; + auto result = picker.Pick(pick_args); + // Handle result. + return HandlePickResult< + LoopCtl>>>( + &result, + // CompletePick + [&](LoadBalancingPolicy::PickResult::Complete* complete_pick) + -> LoopCtl>> { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { + gpr_log(GPR_INFO, + "client_channel: %sLB pick succeeded: subchannel=%p", + GetContext()->DebugTag().c_str(), + complete_pick->subchannel.get()); + } + CHECK(complete_pick->subchannel != nullptr); + // Grab a ref to the call destination while we're still + // holding the data plane mutex. + auto call_destination = + DownCast( + complete_pick->subchannel.get()) + ->call_destination(); + // If the subchannel has no call destination (e.g., if the + // subchannel has moved out of state READY but the LB policy hasn't + // yet seen that change and given us a new picker), then just + // queue the pick. We'll try again as soon as we get a new picker. + if (call_destination == nullptr) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { + gpr_log(GPR_INFO, + "client_channel: %ssubchannel returned by LB picker " + "has no connected subchannel; queueing pick", + GetContext()->DebugTag().c_str()); + } + return Continue{}; + } + // If the LB policy returned a call tracker, inform it that the + // call is starting and add it to context, so that we can notify + // it when the call finishes. + if (complete_pick->subchannel_call_tracker != nullptr) { + complete_pick->subchannel_call_tracker->Start(); + SetContext(complete_pick->subchannel_call_tracker.release()); + } + // Return the connected subchannel. + return call_destination; + }, + // QueuePick + [&](LoadBalancingPolicy::PickResult::Queue* /*queue_pick*/) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { + gpr_log(GPR_INFO, "client_channel: %sLB pick queued", + GetContext()->DebugTag().c_str()); + } + return Continue{}; + }, + // FailPick + [&](LoadBalancingPolicy::PickResult::Fail* fail_pick) + -> LoopCtl>> { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { + gpr_log(GPR_INFO, "client_channel: %sLB pick failed: %s", + GetContext()->DebugTag().c_str(), + fail_pick->status.ToString().c_str()); + } + // If wait_for_ready is false, then the error indicates the RPC + // attempt's final status. + if (!unstarted_handler.UnprocessedClientInitialMetadata() + .GetOrCreatePointer(WaitForReady()) + ->value) { + return MaybeRewriteIllegalStatusCode(std::move(fail_pick->status), + "LB pick"); + } + // If wait_for_ready is true, then queue to retry when we get a new + // picker. + return Continue{}; + }, + // DropPick + [&](LoadBalancingPolicy::PickResult::Drop* drop_pick) + -> LoopCtl>> { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { + gpr_log(GPR_INFO, "client_channel: %sLB pick dropped: %s", + GetContext()->DebugTag().c_str(), + drop_pick->status.ToString().c_str()); + } + return grpc_error_set_int(MaybeRewriteIllegalStatusCode( + std::move(drop_pick->status), "LB drop"), + StatusIntProperty::kLbPolicyDrop, 1); + }); +} + +} // namespace + +void LoadBalancedCallDestination::StartCall( + UnstartedCallHandler unstarted_handler) { + // If there is a call tracer, create a call attempt tracer. + bool* is_transparent_retry_metadata = + unstarted_handler.UnprocessedClientInitialMetadata().get_pointer( + IsTransparentRetry()); + bool is_transparent_retry = is_transparent_retry_metadata != nullptr + ? *is_transparent_retry_metadata + : false; + MaybeCreateCallAttemptTracer(is_transparent_retry); + // Spawn a promise to do the LB pick. + // This will eventually start the call. + unstarted_handler.SpawnGuardedUntilCallCompletes( + "lb_pick", [unstarted_handler, picker = picker_]() mutable { + return Map( + // Wait for the LB picker. + CheckDelayed(Loop( + [last_picker = + RefCountedPtr(), + unstarted_handler, picker]() mutable { + return Map( + picker.Next(last_picker), + [unstarted_handler, &last_picker]( + RefCountedPtr + picker) mutable { + last_picker = std::move(picker); + // Returns 3 possible things: + // - Continue to queue the pick + // - non-OK status to fail the pick + // - a connected subchannel to complete the pick + return PickSubchannel(*last_picker, unstarted_handler); + }); + })), + // Create call stack on the connected subchannel. + [unstarted_handler]( + std::tuple< + absl::StatusOr>, + bool> + pick_result) { + auto& call_destination = std::get<0>(pick_result); + const bool was_queued = std::get<1>(pick_result); + if (!call_destination.ok()) { + return call_destination.status(); + } + // LB pick is done, so indicate that we've committed. + auto* on_commit = MaybeGetContext(); + if (on_commit != nullptr && *on_commit != nullptr) { + (*on_commit)(); + } + // If it was queued, add a trace annotation. + if (was_queued) { + auto* tracer = + MaybeGetContext(); + if (tracer != nullptr) { + tracer->RecordAnnotation("Delayed LB pick complete."); + } + } + // Delegate to connected subchannel. + // TODO(ctiller): need to insert LbCallTracingFilter at the top of + // the stack + (*call_destination)->StartCall(unstarted_handler); + return absl::OkStatus(); + }); + }); +} + +} // namespace grpc_core \ No newline at end of file diff --git a/src/core/client_channel/load_balanced_call_destination.h b/src/core/client_channel/load_balanced_call_destination.h new file mode 100644 index 00000000000..2adbdbe3dc3 --- /dev/null +++ b/src/core/client_channel/load_balanced_call_destination.h @@ -0,0 +1,49 @@ +// Copyright 2024 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_SRC_CORE_CLIENT_CHANNEL_LOAD_BALANCED_CALL_DESTINATION_H +#define GRPC_SRC_CORE_CLIENT_CHANNEL_LOAD_BALANCED_CALL_DESTINATION_H + +#include "absl/functional/any_invocable.h" + +#include "src/core/client_channel/client_channel.h" +#include "src/core/lib/promise/context.h" +#include "src/core/lib/transport/call_destination.h" +#include "src/core/load_balancing/lb_policy.h" + +namespace grpc_core { + +// Context type for LB on_commit callback. +// TODO(ctiller): make this a struct, so we don't accidentally alias context +// types +using LbOnCommit = absl::AnyInvocable; +template <> +struct ContextType {}; + +class LoadBalancedCallDestination final : public UnstartedCallDestination { + public: + explicit LoadBalancedCallDestination(ClientChannel::PickerObservable picker) + : picker_(std::move(picker)) {} + + void Orphaned() override {} + + void StartCall(UnstartedCallHandler unstarted_handler) override; + + private: + ClientChannel::PickerObservable picker_; +}; + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_CLIENT_CHANNEL_LOAD_BALANCED_CALL_DESTINATION_H diff --git a/src/core/client_channel/subchannel.cc b/src/core/client_channel/subchannel.cc index 9ebb91b276e..d12f24b592a 100644 --- a/src/core/client_channel/subchannel.cc +++ b/src/core/client_channel/subchannel.cc @@ -41,6 +41,7 @@ #include "src/core/channelz/channel_trace.h" #include "src/core/channelz/channelz.h" +#include "src/core/client_channel/client_channel_internal.h" #include "src/core/client_channel/subchannel_pool_interface.h" #include "src/core/handshaker/proxy_mapper_registry.h" #include "src/core/lib/address_utils/sockaddr_utils.h" @@ -50,7 +51,10 @@ #include "src/core/lib/channel/channel_stack_builder_impl.h" #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/debug/trace.h" +#include "src/core/lib/experiments/experiments.h" #include "src/core/lib/gprpp/debug_location.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" #include "src/core/lib/gprpp/status_helper.h" #include "src/core/lib/gprpp/sync.h" @@ -64,6 +68,7 @@ #include "src/core/lib/surface/init_internally.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/error_utils.h" +#include "src/core/lib/transport/interception_chain.h" #include "src/core/lib/transport/transport.h" #include "src/core/telemetry/stats.h" #include "src/core/telemetry/stats_data.h" @@ -97,75 +102,168 @@ DebugOnlyTraceFlag grpc_trace_subchannel_refcount(false, "subchannel_refcount"); // ConnectedSubchannel::ConnectedSubchannel( - grpc_channel_stack* channel_stack, const ChannelArgs& args, + const ChannelArgs& args, RefCountedPtr channelz_subchannel) : RefCounted( GRPC_TRACE_FLAG_ENABLED(grpc_trace_subchannel_refcount) ? "ConnectedSubchannel" : nullptr), - channel_stack_(channel_stack), args_(args), channelz_subchannel_(std::move(channelz_subchannel)) {} -ConnectedSubchannel::~ConnectedSubchannel() { - GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor"); -} - -void ConnectedSubchannel::StartWatch( - grpc_pollset_set* interested_parties, - OrphanablePtr watcher) { - grpc_transport_op* op = grpc_make_transport_op(nullptr); - op->start_connectivity_watch = std::move(watcher); - op->start_connectivity_watch_state = GRPC_CHANNEL_READY; - op->bind_pollset_set = interested_parties; - grpc_channel_element* elem = grpc_channel_stack_element(channel_stack_, 0); - elem->filter->start_transport_op(elem, op); -} - -void ConnectedSubchannel::Ping(grpc_closure* on_initiate, - grpc_closure* on_ack) { - grpc_transport_op* op = grpc_make_transport_op(nullptr); - grpc_channel_element* elem; - op->send_ping.on_initiate = on_initiate; - op->send_ping.on_ack = on_ack; - elem = grpc_channel_stack_element(channel_stack_, 0); - elem->filter->start_transport_op(elem, op); -} - -size_t ConnectedSubchannel::GetInitialCallSizeEstimate() const { - return GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)) + - channel_stack_->call_stack_size; -} - -ArenaPromise ConnectedSubchannel::MakeCallPromise( - CallArgs call_args) { - // If not using channelz, we just need to call the channel stack. - if (channelz_subchannel() == nullptr) { - return channel_stack_->MakeClientCallPromise(std::move(call_args)); - } - // Otherwise, we need to wrap the channel stack promise with code that - // handles the channelz updates. - return OnCancel( - Seq(channel_stack_->MakeClientCallPromise(std::move(call_args)), - [self = Ref()](ServerMetadataHandle metadata) { - channelz::SubchannelNode* channelz_subchannel = - self->channelz_subchannel(); - CHECK_NE(channelz_subchannel, nullptr); - if (metadata->get(GrpcStatusMetadata()) - .value_or(GRPC_STATUS_UNKNOWN) != GRPC_STATUS_OK) { - channelz_subchannel->RecordCallFailed(); - } else { - channelz_subchannel->RecordCallSucceeded(); - } - return metadata; - }), - [self = Ref()]() { - channelz::SubchannelNode* channelz_subchannel = - self->channelz_subchannel(); - CHECK_NE(channelz_subchannel, nullptr); - channelz_subchannel->RecordCallFailed(); - }); -} +// +// LegacyConnectedSubchannel +// + +class LegacyConnectedSubchannel : public ConnectedSubchannel { + public: + LegacyConnectedSubchannel( + RefCountedPtr channel_stack, const ChannelArgs& args, + RefCountedPtr channelz_subchannel) + : ConnectedSubchannel(args, std::move(channelz_subchannel)), + channel_stack_(std::move(channel_stack)) {} + + ~LegacyConnectedSubchannel() override { + channel_stack_.reset(DEBUG_LOCATION, "ConnectedSubchannel"); + } + + void StartWatch( + grpc_pollset_set* interested_parties, + OrphanablePtr watcher) override { + grpc_transport_op* op = grpc_make_transport_op(nullptr); + op->start_connectivity_watch = std::move(watcher); + op->start_connectivity_watch_state = GRPC_CHANNEL_READY; + op->bind_pollset_set = interested_parties; + grpc_channel_element* elem = + grpc_channel_stack_element(channel_stack_.get(), 0); + elem->filter->start_transport_op(elem, op); + } + + void Ping(absl::AnyInvocable) override { + Crash("call v3 ping method called in legacy impl"); + } + + RefCountedPtr unstarted_call_destination() + const override { + Crash("call v3 unstarted_call_destination method called in legacy impl"); + } + + grpc_channel_stack* channel_stack() const override { + return channel_stack_.get(); + } + + size_t GetInitialCallSizeEstimate() const override { + return GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)) + + channel_stack_->call_stack_size; + } + + ArenaPromise MakeCallPromise( + CallArgs call_args) override { + // If not using channelz, we just need to call the channel stack. + if (channelz_subchannel() == nullptr) { + return channel_stack_->MakeClientCallPromise(std::move(call_args)); + } + // Otherwise, we need to wrap the channel stack promise with code that + // handles the channelz updates. + return OnCancel( + Seq(channel_stack_->MakeClientCallPromise(std::move(call_args)), + [self = Ref()](ServerMetadataHandle metadata) { + channelz::SubchannelNode* channelz_subchannel = + self->channelz_subchannel(); + CHECK(channelz_subchannel != nullptr); + if (metadata->get(GrpcStatusMetadata()) + .value_or(GRPC_STATUS_UNKNOWN) != GRPC_STATUS_OK) { + channelz_subchannel->RecordCallFailed(); + } else { + channelz_subchannel->RecordCallSucceeded(); + } + return metadata; + }), + [self = Ref()]() { + channelz::SubchannelNode* channelz_subchannel = + self->channelz_subchannel(); + CHECK(channelz_subchannel != nullptr); + channelz_subchannel->RecordCallFailed(); + }); + } + + void Ping(grpc_closure* on_initiate, grpc_closure* on_ack) override { + grpc_transport_op* op = grpc_make_transport_op(nullptr); + op->send_ping.on_initiate = on_initiate; + op->send_ping.on_ack = on_ack; + grpc_channel_element* elem = + grpc_channel_stack_element(channel_stack_.get(), 0); + elem->filter->start_transport_op(elem, op); + } + + private: + RefCountedPtr channel_stack_; +}; + +// +// NewConnectedSubchannel +// + +class NewConnectedSubchannel : public ConnectedSubchannel { + public: + class TransportCallDestination final : public CallDestination { + public: + explicit TransportCallDestination(OrphanablePtr transport) + : transport_(std::move(transport)) {} + + ClientTransport* transport() { return transport_.get(); } + + void HandleCall(CallHandler handler) override { + transport_->StartCall(std::move(handler)); + } + + void Orphaned() override { transport_.reset(); } + + private: + OrphanablePtr transport_; + }; + + NewConnectedSubchannel( + RefCountedPtr call_destination, + RefCountedPtr transport, + const ChannelArgs& args, + RefCountedPtr channelz_subchannel) + : ConnectedSubchannel(args, std::move(channelz_subchannel)), + call_destination_(std::move(call_destination)), + transport_(std::move(transport)) {} + + void StartWatch( + grpc_pollset_set*, + OrphanablePtr watcher) override { + transport_->transport()->StartConnectivityWatch(std::move(watcher)); + } + + void Ping(absl::AnyInvocable) override { + // TODO(ctiller): add new transport API for this in v3 stack + Crash("not implemented"); + } + + RefCountedPtr unstarted_call_destination() + const override { + return call_destination_; + } + + grpc_channel_stack* channel_stack() const override { return nullptr; } + + size_t GetInitialCallSizeEstimate() const override { return 0; } + + ArenaPromise MakeCallPromise(CallArgs) override { + Crash("legacy MakeCallPromise() method called in call v3 impl"); + } + + void Ping(grpc_closure*, grpc_closure*) override { + Crash("legacy ping method called in call v3 impl"); + } + + private: + RefCountedPtr call_destination_; + RefCountedPtr transport_; +}; // // SubchannelCall @@ -255,8 +353,8 @@ void SubchannelCall::Destroy(void* arg, grpc_error_handle /*error*/) { // Destroy the subchannel call. self->~SubchannelCall(); // Destroy the call stack. This should be after destroying the subchannel - // call, because call->after_call_stack_destroy(), if not null, will free the - // call arena. + // call, because call->after_call_stack_destroy(), if not null, will free + // the call arena. grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(self), nullptr, after_call_stack_destroy); // Automatically reset connected_subchannel. This should be after destroying @@ -474,8 +572,8 @@ Subchannel::Subchannel(SubchannelKey key, // result the subchannel destruction happens asynchronously to channel // destruction. If the last channel destruction triggers a grpc_shutdown // before the last subchannel destruction, then there maybe race conditions - // triggering segmentation faults. To prevent this issue, we call a grpc_init - // here and a grpc_shutdown in the subchannel destructor. + // triggering segmentation faults. To prevent this issue, we call a + // grpc_init here and a grpc_shutdown in the subchannel destructor. InitInternally(); global_stats().IncrementClientSubchannelsCreated(); GRPC_CLOSURE_INIT(&on_connecting_finished_, OnConnectingFinished, this, @@ -587,7 +685,8 @@ void Subchannel::CancelConnectivityStateWatch( watcher_list_.RemoveWatcherLocked(watcher); } // Drain any connectivity state notifications after releasing the mutex. - // (Shouldn't actually be necessary in this case, but better safe than sorry.) + // (Shouldn't actually be necessary in this case, but better safe than + // sorry.) work_serializer_.DrainQueue(); } @@ -758,11 +857,11 @@ void Subchannel::OnConnectingFinishedLocked(grpc_error_handle error) { ExecCtx exec_ctx; self->OnRetryTimer(); // Subchannel deletion might require an active ExecCtx. So if - // self.reset() is not called here, the WeakRefCountedPtr destructor - // may run after the ExecCtx declared in the callback is destroyed. - // Since subchannel may get destroyed when the WeakRefCountedPtr - // destructor runs, it may not have an active ExecCtx - thus leading - // to crashes. + // self.reset() is not called here, the WeakRefCountedPtr + // destructor may run after the ExecCtx declared in the callback + // is destroyed. Since subchannel may get destroyed when the + // WeakRefCountedPtr destructor runs, it may not have an active + // ExecCtx - thus leading to crashes. self.reset(); } }); @@ -770,37 +869,60 @@ void Subchannel::OnConnectingFinishedLocked(grpc_error_handle error) { } bool Subchannel::PublishTransportLocked() { - // Construct channel stack. - // Builder takes ownership of transport. - ChannelStackBuilderImpl builder( - "subchannel", GRPC_CLIENT_SUBCHANNEL, - connecting_result_.channel_args.SetObject( - std::exchange(connecting_result_.transport, nullptr))); - if (!CoreConfiguration::Get().channel_init().CreateStack(&builder)) { - return false; - } - absl::StatusOr> stk = builder.Build(); - if (!stk.ok()) { - auto error = absl_status_to_grpc_error(stk.status()); - connecting_result_.Reset(); - gpr_log(GPR_ERROR, - "subchannel %p %s: error initializing subchannel stack: %s", this, - key_.ToString().c_str(), StatusToString(error).c_str()); - return false; + auto socket_node = std::move(connecting_result_.socket_node); + if (connecting_result_.transport->filter_stack_transport() != nullptr || + IsChaoticGoodEnabled()) { + // Construct channel stack. + // Builder takes ownership of transport. + ChannelStackBuilderImpl builder( + "subchannel", GRPC_CLIENT_SUBCHANNEL, + connecting_result_.channel_args.SetObject( + std::exchange(connecting_result_.transport, nullptr))); + if (!CoreConfiguration::Get().channel_init().CreateStack(&builder)) { + return false; + } + absl::StatusOr> stack = builder.Build(); + if (!stack.ok()) { + connecting_result_.Reset(); + gpr_log(GPR_ERROR, + "subchannel %p %s: error initializing subchannel stack: %s", this, + key_.ToString().c_str(), stack.status().ToString().c_str()); + return false; + } + connected_subchannel_ = MakeRefCounted( + std::move(*stack), args_, channelz_node_); + } else { + OrphanablePtr transport( + std::exchange(connecting_result_.transport, nullptr) + ->client_transport()); + InterceptionChainBuilder builder( + connecting_result_.channel_args.SetObject(transport.get())); + CoreConfiguration::Get().channel_init().AddToInterceptionChainBuilder( + GRPC_CLIENT_SUBCHANNEL, builder); + auto transport_destination = + MakeRefCounted( + std::move(transport)); + auto call_destination = builder.Build(transport_destination); + if (!call_destination.ok()) { + connecting_result_.Reset(); + gpr_log(GPR_ERROR, + "subchannel %p %s: error initializing subchannel stack: %s", this, + key_.ToString().c_str(), + call_destination.status().ToString().c_str()); + return false; + } + connected_subchannel_ = MakeRefCounted( + std::move(*call_destination), std::move(transport_destination), args_, + channelz_node_); } - RefCountedPtr socket = - std::move(connecting_result_.socket_node); connecting_result_.Reset(); - if (shutdown_) return false; // Publish. - connected_subchannel_.reset( - new ConnectedSubchannel(stk->release(), args_, channelz_node_)); if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_subchannel)) { gpr_log(GPR_INFO, "subchannel %p %s: new connected subchannel at %p", this, key_.ToString().c_str(), connected_subchannel_.get()); } if (channelz_node_ != nullptr) { - channelz_node_->SetChildSocket(std::move(socket)); + channelz_node_->SetChildSocket(std::move(socket_node)); } // Start watching connected subchannel. connected_subchannel_->StartWatch( @@ -811,4 +933,29 @@ bool Subchannel::PublishTransportLocked() { return true; } +ChannelArgs Subchannel::MakeSubchannelArgs( + const ChannelArgs& channel_args, const ChannelArgs& address_args, + const RefCountedPtr& subchannel_pool, + const std::string& channel_default_authority) { + // Note that we start with the channel-level args and then apply the + // per-address args, so that if a value is present in both, the one + // in the channel-level args is used. This is particularly important + // for the GRPC_ARG_DEFAULT_AUTHORITY arg, which we want to allow + // resolvers to set on a per-address basis only if the application + // did not explicitly set it at the channel level. + return channel_args.UnionWith(address_args) + .SetObject(subchannel_pool) + // If we haven't already set the default authority arg (i.e., it + // was not explicitly set by the application nor overridden by + // the resolver), add it from the channel's default. + .SetIfUnset(GRPC_ARG_DEFAULT_AUTHORITY, channel_default_authority) + // Remove channel args that should not affect subchannel + // uniqueness. + .Remove(GRPC_ARG_HEALTH_CHECK_SERVICE_NAME) + .Remove(GRPC_ARG_INHIBIT_HEALTH_CHECKING) + .Remove(GRPC_ARG_CHANNELZ_CHANNEL_NODE) + // Remove all keys with the no-subchannel prefix. + .RemoveAllKeysWithPrefix(GRPC_ARG_NO_SUBCHANNEL_PREFIX); +} + } // namespace grpc_core diff --git a/src/core/client_channel/subchannel.h b/src/core/client_channel/subchannel.h index f59a3810208..fc2c05ed873 100644 --- a/src/core/client_channel/subchannel.h +++ b/src/core/client_channel/subchannel.h @@ -64,30 +64,35 @@ namespace grpc_core { class SubchannelCall; -class ConnectedSubchannel final : public RefCounted { +class ConnectedSubchannel : public RefCounted { public: - ConnectedSubchannel( - grpc_channel_stack* channel_stack, const ChannelArgs& args, - RefCountedPtr channelz_subchannel); - ~ConnectedSubchannel() override; - - void StartWatch(grpc_pollset_set* interested_parties, - OrphanablePtr watcher); - - void Ping(grpc_closure* on_initiate, grpc_closure* on_ack); - - grpc_channel_stack* channel_stack() const { return channel_stack_; } const ChannelArgs& args() const { return args_; } channelz::SubchannelNode* channelz_subchannel() const { return channelz_subchannel_.get(); } - size_t GetInitialCallSizeEstimate() const; + virtual void StartWatch( + grpc_pollset_set* interested_parties, + OrphanablePtr watcher) = 0; + + // Methods for v3 stack. + virtual void Ping(absl::AnyInvocable on_ack) = 0; + virtual RefCountedPtr unstarted_call_destination() + const = 0; - ArenaPromise MakeCallPromise(CallArgs call_args); + // Methods for legacy stack. + virtual grpc_channel_stack* channel_stack() const = 0; + virtual size_t GetInitialCallSizeEstimate() const = 0; + virtual ArenaPromise MakeCallPromise( + CallArgs call_args) = 0; + virtual void Ping(grpc_closure* on_initiate, grpc_closure* on_ack) = 0; + + protected: + ConnectedSubchannel( + const ChannelArgs& args, + RefCountedPtr channelz_subchannel); private: - grpc_channel_stack* channel_stack_; ChannelArgs args_; // ref counted pointer to the channelz node in this connected subchannel's // owning subchannel. @@ -243,6 +248,12 @@ class Subchannel final : public DualRefCounted { return connected_subchannel_; } + RefCountedPtr call_destination() { + MutexLock lock(&mu_); + if (connected_subchannel_ == nullptr) return nullptr; + return connected_subchannel_->unstarted_call_destination(); + } + // Attempt to connect to the backend. Has no effect if already connected. void RequestConnection() ABSL_LOCKS_EXCLUDED(mu_); @@ -272,6 +283,12 @@ class Subchannel final : public DualRefCounted { return event_engine_; } + // Exposed for testing purposes only. + static ChannelArgs MakeSubchannelArgs( + const ChannelArgs& channel_args, const ChannelArgs& address_args, + const RefCountedPtr& subchannel_pool, + const std::string& channel_default_authority); + private: // Tears down any existing connection, and arranges for destruction void Orphaned() override ABSL_LOCKS_EXCLUDED(mu_); diff --git a/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc b/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc index fd48d034d38..63a886bc991 100644 --- a/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc +++ b/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc @@ -78,15 +78,11 @@ TraceFlag grpc_trace_client_idle_filter(false, "client_idle_filter"); } \ } while (0) -namespace { - Duration GetClientIdleTimeout(const ChannelArgs& args) { return args.GetDurationFromIntMillis(GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS) .value_or(kDefaultIdleTimeout); } -} // namespace - struct LegacyMaxAgeFilter::Config { Duration max_connection_age; Duration max_connection_idle; diff --git a/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h b/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h index 8e6215cebba..001282276f1 100644 --- a/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h +++ b/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h @@ -40,6 +40,8 @@ namespace grpc_core { +Duration GetClientIdleTimeout(const ChannelArgs& args); + class LegacyChannelIdleFilter : public ChannelFilter { public: LegacyChannelIdleFilter(grpc_channel_stack* channel_stack, diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h index 31e0430a7c6..55cb2785abc 100644 --- a/src/core/lib/channel/channel_args.h +++ b/src/core/lib/channel/channel_args.h @@ -83,6 +83,16 @@ inline int PointerCompare(void* a_ptr, const grpc_arg_pointer_vtable* a_vtable, // before the crt refcount base class. template using RefType = absl::remove_cvref_t().Ref())>; + +template +struct IsRawPointerTagged { + static constexpr bool kValue = false; +}; +template +struct IsRawPointerTagged> { + static constexpr bool kValue = true; +}; } // namespace channel_args_detail // Specialization for ref-counted pointers. @@ -91,13 +101,14 @@ using RefType = absl::remove_cvref_t().Ref())>; template struct ChannelArgTypeTraits< T, absl::enable_if_t< - std::is_base_of>, - channel_args_detail::RefType>::value || - std::is_base_of, - NonPolymorphicRefCount>, - channel_args_detail::RefType>::value || - std::is_base_of>, - channel_args_detail::RefType>::value, + !channel_args_detail::IsRawPointerTagged::kValue && + (std::is_base_of>, + channel_args_detail::RefType>::value || + std::is_base_of, + NonPolymorphicRefCount>, + channel_args_detail::RefType>::value || + std::is_base_of>, + channel_args_detail::RefType>::value), void>> { static const grpc_arg_pointer_vtable* VTable() { static const grpc_arg_pointer_vtable tbl = { diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h index 9fc6564c8de..c414b33eb23 100644 --- a/src/core/lib/channel/channel_stack.h +++ b/src/core/lib/channel/channel_stack.h @@ -230,6 +230,7 @@ struct grpc_channel_stack { // full C++-ification for now. void IncrementRefCount(); void Unref(); + void Unref(const grpc_core::DebugLocation& location, const char* reason); grpc_core::RefCountedPtr Ref() { IncrementRefCount(); return grpc_core::RefCountedPtr(this); @@ -345,6 +346,11 @@ inline void grpc_channel_stack::Unref() { GRPC_CHANNEL_STACK_UNREF(this, "smart_pointer"); } +inline void grpc_channel_stack::Unref(const grpc_core::DebugLocation&, + const char* reason) { + GRPC_CHANNEL_STACK_UNREF(this, reason); +} + inline void grpc_call_stack::IncrementRefCount() { GRPC_CALL_STACK_REF(this, "smart_pointer"); } diff --git a/src/core/lib/channel/context.h b/src/core/lib/channel/context.h index 95ce62240bf..1a78e3536ed 100644 --- a/src/core/lib/channel/context.h +++ b/src/core/lib/channel/context.h @@ -59,6 +59,9 @@ typedef enum { /// the server. GRPC_CONTEXT_BACKEND_METRIC_PROVIDER, + /// A LoadBalancingPolicy::SubchannelCallTrackerInterface + GRPC_SUBCHANNEL_CALL_TRACKER_INTERFACE, + /// Special Google context GRPC_CONTEXT_GOOGLE, @@ -73,6 +76,8 @@ struct grpc_call_context_element { namespace grpc_core { class Call; class CallTracerAnnotationInterface; +class CallTracerInterface; +class ServiceConfigCallData; // Bind the legacy context array into the new style structure // TODO(ctiller): remove as we migrate these contexts to the new system. @@ -96,6 +101,17 @@ struct OldStyleContext { GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE; }; +template <> +struct OldStyleContext { + static constexpr grpc_context_index kIndex = GRPC_CONTEXT_CALL_TRACER; +}; + +template <> +struct OldStyleContext { + static constexpr grpc_context_index kIndex = + GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA; +}; + template class Context::kIndex)>> { public: @@ -104,6 +120,15 @@ class Context::kIndex)>> { GetContext()[OldStyleContext::kIndex] .value); } + static void set(T* value) { + auto& elem = + GetContext()[OldStyleContext::kIndex]; + if (elem.destroy != nullptr) { + elem.destroy(elem.value); + elem.destroy = nullptr; + } + elem.value = value; + } }; } // namespace promise_detail diff --git a/src/core/lib/experiments/experiments.cc b/src/core/lib/experiments/experiments.cc index b4ba5bdba89..8fc435e0f24 100644 --- a/src/core/lib/experiments/experiments.cc +++ b/src/core/lib/experiments/experiments.cc @@ -29,8 +29,6 @@ const char* const description_call_status_override_on_cancellation = "with cancellation."; const char* const additional_constraints_call_status_override_on_cancellation = "{}"; -const char* const description_call_v3 = "Promise-based call version 3."; -const char* const additional_constraints_call_v3 = "{}"; const char* const description_canary_client_privacy = "If set, canary client privacy"; const char* const additional_constraints_canary_client_privacy = "{}"; @@ -133,6 +131,12 @@ const char* const description_work_serializer_dispatch = const char* const additional_constraints_work_serializer_dispatch = "{}"; const uint8_t required_experiments_work_serializer_dispatch[] = { static_cast(grpc_core::kExperimentIdEventEngineClient)}; +const char* const description_call_v3 = "Promise-based call version 3."; +const char* const additional_constraints_call_v3 = "{}"; +const uint8_t required_experiments_call_v3[] = { + static_cast(grpc_core::kExperimentIdEventEngineClient), + static_cast(grpc_core::kExperimentIdEventEngineListener), + static_cast(grpc_core::kExperimentIdWorkSerializerDispatch)}; } // namespace namespace grpc_core { @@ -142,8 +146,6 @@ const ExperimentMetadata g_experiment_metadata[] = { description_call_status_override_on_cancellation, additional_constraints_call_status_override_on_cancellation, nullptr, 0, true, true}, - {"call_v3", description_call_v3, additional_constraints_call_v3, nullptr, 0, - false, true}, {"canary_client_privacy", description_canary_client_privacy, additional_constraints_canary_client_privacy, nullptr, 0, false, false}, {"client_privacy", description_client_privacy, @@ -208,6 +210,8 @@ const ExperimentMetadata g_experiment_metadata[] = { {"work_serializer_dispatch", description_work_serializer_dispatch, additional_constraints_work_serializer_dispatch, required_experiments_work_serializer_dispatch, 1, false, true}, + {"call_v3", description_call_v3, additional_constraints_call_v3, + required_experiments_call_v3, 3, false, false}, }; } // namespace grpc_core @@ -219,8 +223,6 @@ const char* const description_call_status_override_on_cancellation = "with cancellation."; const char* const additional_constraints_call_status_override_on_cancellation = "{}"; -const char* const description_call_v3 = "Promise-based call version 3."; -const char* const additional_constraints_call_v3 = "{}"; const char* const description_canary_client_privacy = "If set, canary client privacy"; const char* const additional_constraints_canary_client_privacy = "{}"; @@ -323,6 +325,12 @@ const char* const description_work_serializer_dispatch = const char* const additional_constraints_work_serializer_dispatch = "{}"; const uint8_t required_experiments_work_serializer_dispatch[] = { static_cast(grpc_core::kExperimentIdEventEngineClient)}; +const char* const description_call_v3 = "Promise-based call version 3."; +const char* const additional_constraints_call_v3 = "{}"; +const uint8_t required_experiments_call_v3[] = { + static_cast(grpc_core::kExperimentIdEventEngineClient), + static_cast(grpc_core::kExperimentIdEventEngineListener), + static_cast(grpc_core::kExperimentIdWorkSerializerDispatch)}; } // namespace namespace grpc_core { @@ -332,8 +340,6 @@ const ExperimentMetadata g_experiment_metadata[] = { description_call_status_override_on_cancellation, additional_constraints_call_status_override_on_cancellation, nullptr, 0, true, true}, - {"call_v3", description_call_v3, additional_constraints_call_v3, nullptr, 0, - false, true}, {"canary_client_privacy", description_canary_client_privacy, additional_constraints_canary_client_privacy, nullptr, 0, false, false}, {"client_privacy", description_client_privacy, @@ -398,6 +404,8 @@ const ExperimentMetadata g_experiment_metadata[] = { {"work_serializer_dispatch", description_work_serializer_dispatch, additional_constraints_work_serializer_dispatch, required_experiments_work_serializer_dispatch, 1, false, true}, + {"call_v3", description_call_v3, additional_constraints_call_v3, + required_experiments_call_v3, 3, false, false}, }; } // namespace grpc_core @@ -409,8 +417,6 @@ const char* const description_call_status_override_on_cancellation = "with cancellation."; const char* const additional_constraints_call_status_override_on_cancellation = "{}"; -const char* const description_call_v3 = "Promise-based call version 3."; -const char* const additional_constraints_call_v3 = "{}"; const char* const description_canary_client_privacy = "If set, canary client privacy"; const char* const additional_constraints_canary_client_privacy = "{}"; @@ -513,6 +519,12 @@ const char* const description_work_serializer_dispatch = const char* const additional_constraints_work_serializer_dispatch = "{}"; const uint8_t required_experiments_work_serializer_dispatch[] = { static_cast(grpc_core::kExperimentIdEventEngineClient)}; +const char* const description_call_v3 = "Promise-based call version 3."; +const char* const additional_constraints_call_v3 = "{}"; +const uint8_t required_experiments_call_v3[] = { + static_cast(grpc_core::kExperimentIdEventEngineClient), + static_cast(grpc_core::kExperimentIdEventEngineListener), + static_cast(grpc_core::kExperimentIdWorkSerializerDispatch)}; } // namespace namespace grpc_core { @@ -522,8 +534,6 @@ const ExperimentMetadata g_experiment_metadata[] = { description_call_status_override_on_cancellation, additional_constraints_call_status_override_on_cancellation, nullptr, 0, true, true}, - {"call_v3", description_call_v3, additional_constraints_call_v3, nullptr, 0, - false, true}, {"canary_client_privacy", description_canary_client_privacy, additional_constraints_canary_client_privacy, nullptr, 0, false, false}, {"client_privacy", description_client_privacy, @@ -588,6 +598,8 @@ const ExperimentMetadata g_experiment_metadata[] = { {"work_serializer_dispatch", description_work_serializer_dispatch, additional_constraints_work_serializer_dispatch, required_experiments_work_serializer_dispatch, 1, true, true}, + {"call_v3", description_call_v3, additional_constraints_call_v3, + required_experiments_call_v3, 3, false, false}, }; } // namespace grpc_core diff --git a/src/core/lib/experiments/experiments.h b/src/core/lib/experiments/experiments.h index 50dc88d8269..eebbfe2afde 100644 --- a/src/core/lib/experiments/experiments.h +++ b/src/core/lib/experiments/experiments.h @@ -59,7 +59,6 @@ namespace grpc_core { #if defined(GRPC_CFSTREAM) #define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION inline bool IsCallStatusOverrideOnCancellationEnabled() { return true; } -inline bool IsCallV3Enabled() { return false; } inline bool IsCanaryClientPrivacyEnabled() { return false; } inline bool IsClientPrivacyEnabled() { return false; } inline bool IsEventEngineClientEnabled() { return false; } @@ -91,11 +90,11 @@ inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; } #define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; } inline bool IsWorkSerializerDispatchEnabled() { return false; } +inline bool IsCallV3Enabled() { return false; } #elif defined(GPR_WINDOWS) #define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION inline bool IsCallStatusOverrideOnCancellationEnabled() { return true; } -inline bool IsCallV3Enabled() { return false; } inline bool IsCanaryClientPrivacyEnabled() { return false; } inline bool IsClientPrivacyEnabled() { return false; } inline bool IsEventEngineClientEnabled() { return false; } @@ -129,11 +128,11 @@ inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; } #define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; } inline bool IsWorkSerializerDispatchEnabled() { return false; } +inline bool IsCallV3Enabled() { return false; } #else #define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION inline bool IsCallStatusOverrideOnCancellationEnabled() { return true; } -inline bool IsCallV3Enabled() { return false; } inline bool IsCanaryClientPrivacyEnabled() { return false; } inline bool IsClientPrivacyEnabled() { return false; } inline bool IsEventEngineClientEnabled() { return false; } @@ -168,12 +167,12 @@ inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; } inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; } #define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_DISPATCH inline bool IsWorkSerializerDispatchEnabled() { return true; } +inline bool IsCallV3Enabled() { return false; } #endif #else enum ExperimentIds { kExperimentIdCallStatusOverrideOnCancellation, - kExperimentIdCallV3, kExperimentIdCanaryClientPrivacy, kExperimentIdClientPrivacy, kExperimentIdEventEngineClient, @@ -200,16 +199,13 @@ enum ExperimentIds { kExperimentIdUnconstrainedMaxQuotaBufferSize, kExperimentIdWorkSerializerClearsTimeCache, kExperimentIdWorkSerializerDispatch, + kExperimentIdCallV3, kNumExperiments }; #define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION inline bool IsCallStatusOverrideOnCancellationEnabled() { return IsExperimentEnabled(kExperimentIdCallStatusOverrideOnCancellation); } -#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_V3 -inline bool IsCallV3Enabled() { - return IsExperimentEnabled(kExperimentIdCallV3); -} #define GRPC_EXPERIMENT_IS_INCLUDED_CANARY_CLIENT_PRIVACY inline bool IsCanaryClientPrivacyEnabled() { return IsExperimentEnabled(kExperimentIdCanaryClientPrivacy); @@ -314,6 +310,10 @@ inline bool IsWorkSerializerClearsTimeCacheEnabled() { inline bool IsWorkSerializerDispatchEnabled() { return IsExperimentEnabled(kExperimentIdWorkSerializerDispatch); } +#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_V3 +inline bool IsCallV3Enabled() { + return IsExperimentEnabled(kExperimentIdCallV3); +} extern const ExperimentMetadata g_experiment_metadata[kNumExperiments]; diff --git a/src/core/lib/experiments/experiments.yaml b/src/core/lib/experiments/experiments.yaml index f26fc02f27e..5d2678f99d2 100644 --- a/src/core/lib/experiments/experiments.yaml +++ b/src/core/lib/experiments/experiments.yaml @@ -52,6 +52,8 @@ expiry: 2024/06/01 owner: ctiller@google.com test_tags: [] + requires: ["work_serializer_dispatch", "event_engine_listener", "event_engine_client"] + allow_in_fuzzing_config: false - name: canary_client_privacy description: If set, canary client privacy diff --git a/src/core/lib/promise/activity.h b/src/core/lib/promise/activity.h index daf3e76a6c2..1cbbc01e268 100644 --- a/src/core/lib/promise/activity.h +++ b/src/core/lib/promise/activity.h @@ -26,6 +26,7 @@ #include "absl/base/thread_annotations.h" #include "absl/log/check.h" #include "absl/status/status.h" +#include "absl/strings/str_cat.h" #include "absl/types/optional.h" #include @@ -121,6 +122,11 @@ class Waker { return wakeable_and_arg_.ActivityDebugTag(); } + std::string DebugString() { + return absl::StrFormat("Waker{%p, %d}", wakeable_and_arg_.wakeable, + wakeable_and_arg_.wakeup_mask); + } + // This is for tests to assert that a waker is occupied or not. bool is_unwakeable() const { return wakeable_and_arg_.wakeable == promise_detail::unwakeable(); diff --git a/src/core/lib/promise/context.h b/src/core/lib/promise/context.h index 47b2bac39f2..e1f1f6511d9 100644 --- a/src/core/lib/promise/context.h +++ b/src/core/lib/promise/context.h @@ -125,6 +125,11 @@ T* MaybeGetContext() { return promise_detail::Context::get(); } +template +void SetContext(T* p) { + promise_detail::Context::set(p); +} + // Given a promise and a context, return a promise that has that context set. template promise_detail::WithContext WithContext(F f, T* context) { diff --git a/src/core/lib/promise/map.h b/src/core/lib/promise/map.h index 6ee27fef83d..b1772ad5b51 100644 --- a/src/core/lib/promise/map.h +++ b/src/core/lib/promise/map.h @@ -72,6 +72,23 @@ promise_detail::Map Map(Promise promise, Fn fn) { return promise_detail::Map(std::move(promise), std::move(fn)); } +// Maps a promise to a new promise that returns a tuple of the original result +// and a bool indicating whether there was ever a Pending{} value observed from +// polling. +template +auto CheckDelayed(Promise promise) { + using P = promise_detail::PromiseLike; + return [delayed = false, promise = P(std::move(promise))]() mutable + -> Poll> { + auto r = promise(); + if (r.pending()) { + delayed = true; + return Pending{}; + } + return std::make_tuple(r.value(), delayed); + }; +} + // Callable that takes a tuple and returns one element template struct JustElem { diff --git a/src/core/lib/promise/observable.h b/src/core/lib/promise/observable.h index edf7a37515a..9337feace3f 100644 --- a/src/core/lib/promise/observable.h +++ b/src/core/lib/promise/observable.h @@ -125,6 +125,7 @@ class Observable { Observer& operator=(const Observer&) = delete; Observer(Observer&& other) noexcept : state_(std::move(other.state_)) { CHECK(other.waker_.is_unwakeable()); + DCHECK(waker_.is_unwakeable()); CHECK(!other.saw_pending_); } Observer& operator=(Observer&& other) noexcept = delete; diff --git a/src/core/lib/promise/party.cc b/src/core/lib/promise/party.cc index c030f43c4e0..58931d978d4 100644 --- a/src/core/lib/promise/party.cc +++ b/src/core/lib/promise/party.cc @@ -308,8 +308,10 @@ void Party::AddParticipants(Participant** participants, size_t count) { for (size_t i = 0; i < count; i++) { if (grpc_trace_party_state.enabled()) { gpr_log(GPR_INFO, - "Party %p AddParticipant: %s @ %" PRIdPTR, - &sync_, std::string(participants[i]->name()).c_str(), slots[i]); + "Party %p AddParticipant: %s @ %" PRIdPTR + " [participant=%p]", + &sync_, std::string(participants[i]->name()).c_str(), slots[i], + participants[i]); } participants_[slots[i]].store(participants[i], std::memory_order_release); } diff --git a/src/core/lib/promise/party.h b/src/core/lib/promise/party.h index 214c36a588f..d2467168c26 100644 --- a/src/core/lib/promise/party.h +++ b/src/core/lib/promise/party.h @@ -379,6 +379,11 @@ class Party : public Activity, private Wakeable { // The on_complete callback will be called with the result of the promise if // it completes. // A maximum of sixteen promises can be spawned onto a party. + // promise_factory called to create the promise with the party lock taken; + // after the promise is created the factory is destroyed. + // This means that pointers or references to factory members will be + // invalidated after the promise is created - so the promise should not retain + // any of these. template void Spawn(absl::string_view name, Factory promise_factory, OnComplete on_complete); diff --git a/src/core/lib/promise/promise.h b/src/core/lib/promise/promise.h index bad6aad81d0..1595f2a8782 100644 --- a/src/core/lib/promise/promise.h +++ b/src/core/lib/promise/promise.h @@ -18,6 +18,7 @@ #include #include "absl/functional/any_invocable.h" +#include "absl/log/log.h" #include "absl/status/status.h" #include "absl/types/optional.h" diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h index c0ccaf842cc..d464de2ec89 100644 --- a/src/core/lib/surface/call.h +++ b/src/core/lib/surface/call.h @@ -130,6 +130,8 @@ class Call : public CppImplOf, // Implementation of EventEngine::Closure, called when deadline expires void Run() final; + gpr_cycle_counter start_time() const { return start_time_; } + protected: // The maximum number of concurrent batches possible. // Based upon the maximum number of individually queueable ops in the batch @@ -209,8 +211,6 @@ class Call : public CppImplOf, void HandleCompressionAlgorithmNotAccepted( grpc_compression_algorithm compression_algorithm) GPR_ATTRIBUTE_NOINLINE; - gpr_cycle_counter start_time() const { return start_time_; } - virtual grpc_compression_options compression_options() = 0; private: diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index b8134974794..b7f91e6003c 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -65,7 +65,22 @@ Channel::RegisteredCall::~RegisteredCall() {} Channel::Channel(std::string target, const ChannelArgs& channel_args) : target_(std::move(target)), channelz_node_(channel_args.GetObjectRef()), - compression_options_(CompressionOptionsFromChannelArgs(channel_args)) {} + compression_options_(CompressionOptionsFromChannelArgs(channel_args)), + call_size_estimator_(1024), + allocator_(channel_args.GetObject() + ->memory_quota() + ->CreateMemoryOwner()) {} + +Arena* Channel::CreateArena() { + const size_t initial_size = call_size_estimator_.CallSizeEstimate(); + global_stats().IncrementCallInitialSize(initial_size); + return Arena::Create(initial_size, &allocator_); +} + +void Channel::DestroyArena(Arena* arena) { + call_size_estimator_.UpdateCallSizeEstimate(arena->TotalUsedBytes()); + arena->Destroy(); +} Channel::RegisteredCall* Channel::RegisterCall(const char* method, const char* host) { diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h index 533a944c18c..d0547c5bdf5 100644 --- a/src/core/lib/surface/channel.h +++ b/src/core/lib/surface/channel.h @@ -40,8 +40,10 @@ #include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/iomgr_fwd.h" #include "src/core/lib/resource_quota/arena.h" +#include "src/core/lib/resource_quota/resource_quota.h" #include "src/core/lib/slice/slice.h" #include "src/core/lib/surface/channel_stack_type.h" +#include "src/core/lib/transport/call_arena_allocator.h" #include "src/core/lib/transport/connectivity_state.h" // Forward declaration to avoid dependency loop. @@ -52,7 +54,7 @@ namespace grpc_core { // Forward declaration to avoid dependency loop. class Transport; -class Channel : public RefCounted, +class Channel : public InternallyRefCounted, public CppImplOf { public: struct RegisteredCall { @@ -66,10 +68,17 @@ class Channel : public RefCounted, ~RegisteredCall(); }; - virtual void Orphan() = 0; - - virtual Arena* CreateArena() = 0; - virtual void DestroyArena(Arena* arena) = 0; + // Though internally ref counted channels expose their "Ref" method to + // create a RefCountedPtr to themselves. The OrphanablePtr owner is the + // singleton decision maker on whether the channel should be destroyed or + // not. + // TODO(ctiller): in a future change (I have it written) these will be removed + // and substituted with DualRefCounted as a base. + RefCountedPtr Ref() { return InternallyRefCounted::Ref(); } + template + RefCountedPtr RefAsSubclass() { + return InternallyRefCounted::RefAsSubclass(); + } virtual bool IsLame() const = 0; @@ -125,6 +134,8 @@ class Channel : public RefCounted, virtual void Ping(grpc_completion_queue* cq, void* tag) = 0; // TODO(roth): Remove these methods when LegacyChannel goes away. + Arena* CreateArena(); + void DestroyArena(Arena* arena); virtual grpc_channel_stack* channel_stack() const { return nullptr; } virtual bool is_client() const { return true; } virtual bool is_promising() const { return true; } @@ -137,6 +148,10 @@ class Channel : public RefCounted, const RefCountedPtr channelz_node_; const grpc_compression_options compression_options_; + // TODO(ctiller): move to use CallArenaAllocator + CallSizeEstimator call_size_estimator_; + MemoryAllocator allocator_; + Mutex mu_; // The map key needs to be owned strings rather than unowned char*'s to // guarantee that it outlives calls on the core channel (which may outlast diff --git a/src/core/lib/surface/channel_create.cc b/src/core/lib/surface/channel_create.cc index 5ae280171e7..6a22eeec630 100644 --- a/src/core/lib/surface/channel_create.cc +++ b/src/core/lib/surface/channel_create.cc @@ -22,8 +22,10 @@ #include #include "src/core/channelz/channelz.h" +#include "src/core/client_channel/client_channel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/config/core_configuration.h" +#include "src/core/lib/experiments/experiments.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/lame_client.h" #include "src/core/lib/surface/legacy_channel.h" @@ -77,9 +79,13 @@ absl::StatusOr> ChannelCreate( if (optional_transport != nullptr) { args = args.SetObject(optional_transport); } - // Delegate to legacy channel impl. - return LegacyChannel::Create(std::move(target), std::move(args), - channel_stack_type); + // Delegate to appropriate channel impl. + if (!IsCallV3Enabled()) { + return LegacyChannel::Create(std::move(target), std::move(args), + channel_stack_type); + } + CHECK_EQ(channel_stack_type, GRPC_CLIENT_CHANNEL); + return ClientChannel::Create(std::move(target), std::move(args)); } } // namespace grpc_core diff --git a/src/core/lib/surface/legacy_channel.cc b/src/core/lib/surface/legacy_channel.cc index 69a41cf503e..c35e0158c51 100644 --- a/src/core/lib/surface/legacy_channel.cc +++ b/src/core/lib/surface/legacy_channel.cc @@ -113,10 +113,7 @@ LegacyChannel::LegacyChannel(bool is_client, bool is_promising, : Channel(std::move(target), channel_args), is_client_(is_client), is_promising_(is_promising), - channel_stack_(std::move(channel_stack)), - allocator_(channel_args.GetObject() - ->memory_quota() - ->CreateMemoryOwner()) { + channel_stack_(std::move(channel_stack)) { // We need to make sure that grpc_shutdown() does not shut things down // until after the channel is destroyed. However, the channel may not // actually be destroyed by the time grpc_channel_destroy() returns, diff --git a/src/core/lib/surface/legacy_channel.h b/src/core/lib/surface/legacy_channel.h index 0ebf7b4aacb..b5199e80939 100644 --- a/src/core/lib/surface/legacy_channel.h +++ b/src/core/lib/surface/legacy_channel.h @@ -39,6 +39,7 @@ #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/call_arena_allocator.h" +#include "src/core/lib/transport/transport.h" #include "src/core/telemetry/stats.h" namespace grpc_core { @@ -56,16 +57,6 @@ class LegacyChannel final : public Channel { void Orphan() override; - Arena* CreateArena() override { - const size_t initial_size = call_size_estimator_.CallSizeEstimate(); - global_stats().IncrementCallInitialSize(initial_size); - return Arena::Create(initial_size, &allocator_); - } - void DestroyArena(Arena* arena) override { - call_size_estimator_.UpdateCallSizeEstimate(arena->TotalUsedBytes()); - arena->Destroy(); - } - bool IsLame() const override; grpc_call* CreateCall(grpc_call* parent_call, uint32_t propagation_mask, @@ -114,8 +105,6 @@ class LegacyChannel final : public Channel { const bool is_client_; const bool is_promising_; RefCountedPtr channel_stack_; - CallSizeEstimator call_size_estimator_{1024}; - grpc_event_engine::experimental::MemoryAllocator allocator_; }; } // namespace grpc_core diff --git a/src/core/lib/transport/call_destination.h b/src/core/lib/transport/call_destination.h index 938e0fd3725..04d402569c9 100644 --- a/src/core/lib/transport/call_destination.h +++ b/src/core/lib/transport/call_destination.h @@ -31,6 +31,8 @@ namespace grpc_core { class UnstartedCallDestination : public DualRefCounted { public: + using DualRefCounted::DualRefCounted; + ~UnstartedCallDestination() override = default; // Start a call. The UnstartedCallHandler will be consumed by the Destination // and started. diff --git a/src/core/lib/transport/call_filters.cc b/src/core/lib/transport/call_filters.cc index 2b89babdde4..c4b18721c86 100644 --- a/src/core/lib/transport/call_filters.cc +++ b/src/core/lib/transport/call_filters.cc @@ -170,8 +170,15 @@ Poll InfallibleOperationExecutor::ContinueStep(void* call_data) { template class OperationExecutor; template class OperationExecutor; template class InfallibleOperationExecutor; + } // namespace filters_detail +namespace { +// Call data for those calls that don't have any call data +// (we form pointers to this that aren't allowed to be nullptr) +char g_empty_call_data; +} // namespace + /////////////////////////////////////////////////////////////////////////////// // CallFilters @@ -181,7 +188,7 @@ CallFilters::CallFilters(ClientMetadataHandle client_initial_metadata) client_initial_metadata_(std::move(client_initial_metadata)) {} CallFilters::~CallFilters() { - if (call_data_ != nullptr) { + if (call_data_ != nullptr && call_data_ != &g_empty_call_data) { for (const auto& destructor : stack_->data_.filter_destructor) { destructor.call_destroy(Offset(call_data_, destructor.call_offset)); } @@ -192,8 +199,12 @@ CallFilters::~CallFilters() { void CallFilters::SetStack(RefCountedPtr stack) { CHECK_EQ(call_data_, nullptr); stack_ = std::move(stack); - call_data_ = gpr_malloc_aligned(stack_->data_.call_data_size, - stack_->data_.call_data_alignment); + if (stack_->data_.call_data_size != 0) { + call_data_ = gpr_malloc_aligned(stack_->data_.call_data_size, + stack_->data_.call_data_alignment); + } else { + call_data_ = &g_empty_call_data; + } for (const auto& constructor : stack_->data_.filter_constructor) { constructor.call_init(Offset(call_data_, constructor.call_offset), constructor.channel_data); @@ -232,7 +243,8 @@ void CallFilters::PushServerTrailingMetadata(ServerMetadataHandle md) { md->DebugString().c_str(), DebugString().c_str()); } CHECK(md != nullptr); - if (server_trailing_metadata_ != nullptr) return; + if (cancelled_.is_set()) return; + cancelled_.Set(md->get(GrpcCallWasCancelled()).value_or(false)); server_trailing_metadata_ = std::move(md); client_initial_metadata_state_.CloseWithError(); server_initial_metadata_state_.CloseSending(); diff --git a/src/core/lib/transport/call_filters.h b/src/core/lib/transport/call_filters.h index fd267fd1685..c69ef82c1dc 100644 --- a/src/core/lib/transport/call_filters.h +++ b/src/core/lib/transport/call_filters.h @@ -23,6 +23,7 @@ #include +#include "src/core/lib/gprpp/dump_args.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/promise/latch.h" @@ -1944,11 +1945,7 @@ inline auto CallFilters::PullServerToClientMessage() { } inline auto CallFilters::PullServerTrailingMetadata() { - return Map(PullServerTrailingMetadataPromise(this), - [this](ServerMetadataHandle h) { - cancelled_.Set(h->get(GrpcCallWasCancelled()).value_or(false)); - return h; - }); + return PullServerTrailingMetadataPromise(this); } inline auto CallFilters::WasCancelled() { return cancelled_.Wait(); } diff --git a/src/core/lib/transport/call_spine.h b/src/core/lib/transport/call_spine.h index 59c1fc2da16..8a27c95f593 100644 --- a/src/core/lib/transport/call_spine.h +++ b/src/core/lib/transport/call_spine.h @@ -21,13 +21,16 @@ #include #include "src/core/lib/channel/context.h" +#include "src/core/lib/gprpp/dual_ref_counted.h" #include "src/core/lib/promise/detail/status.h" #include "src/core/lib/promise/if.h" #include "src/core/lib/promise/latch.h" #include "src/core/lib/promise/party.h" #include "src/core/lib/promise/pipe.h" +#include "src/core/lib/promise/prioritized_race.h" #include "src/core/lib/promise/promise.h" #include "src/core/lib/promise/status_flag.h" +#include "src/core/lib/promise/try_seq.h" #include "src/core/lib/transport/call_arena_allocator.h" #include "src/core/lib/transport/call_filters.h" #include "src/core/lib/transport/message.h" @@ -135,6 +138,23 @@ class CallSpineInterface { }); } + // Wrap a promise so that if the call completes that promise is cancelled. + template + auto UntilCallCompletes(Promise promise) { + using Result = PromiseResult; + return PrioritizedRace(std::move(promise), Map(WasCancelled(), [](bool) { + return FailureStatusCast(Failure{}); + })); + } + + template + void SpawnGuardedUntilCallCompletes(absl::string_view name, + PromiseFactory promise_factory) { + SpawnGuarded(name, [this, promise_factory]() mutable { + return UntilCallCompletes(promise_factory()); + }); + } + private: absl::AnyInvocable on_done_{nullptr}; }; @@ -272,7 +292,7 @@ class CallSpine final : public CallSpineInterface, public Party { if (legacy_context_is_owned_) { for (size_t i = 0; i < GRPC_CONTEXT_COUNT; i++) { grpc_call_context_element& elem = legacy_context_[i]; - if (elem.destroy != nullptr) elem.destroy(&elem); + if (elem.destroy != nullptr) elem.destroy(elem.value); } } } @@ -472,6 +492,12 @@ class CallInitiator { spine_->SpawnGuarded(name, std::move(promise_factory)); } + template + void SpawnGuardedUntilCallCompletes(absl::string_view name, + PromiseFactory promise_factory) { + spine_->SpawnGuardedUntilCallCompletes(name, std::move(promise_factory)); + } + template void SpawnInfallible(absl::string_view name, PromiseFactory promise_factory) { spine_->SpawnInfallible(name, std::move(promise_factory)); @@ -526,6 +552,12 @@ class CallHandler { spine_->SpawnGuarded(name, std::move(promise_factory), whence); } + template + void SpawnGuardedUntilCallCompletes(absl::string_view name, + PromiseFactory promise_factory) { + spine_->SpawnGuardedUntilCallCompletes(name, std::move(promise_factory)); + } + template void SpawnInfallible(absl::string_view name, PromiseFactory promise_factory) { spine_->SpawnInfallible(name, std::move(promise_factory)); @@ -577,6 +609,12 @@ class UnstartedCallHandler { spine_->SpawnGuarded(name, std::move(promise_factory), whence); } + template + void SpawnGuardedUntilCallCompletes(absl::string_view name, + PromiseFactory promise_factory) { + spine_->SpawnGuardedUntilCallCompletes(name, std::move(promise_factory)); + } + template void SpawnInfallible(absl::string_view name, PromiseFactory promise_factory) { spine_->SpawnInfallible(name, std::move(promise_factory)); diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h index c8611a225fa..a5a934803ee 100644 --- a/src/core/lib/transport/metadata_batch.h +++ b/src/core/lib/transport/metadata_batch.h @@ -528,6 +528,14 @@ struct WaitForReady { static std::string DisplayValue(ValueType x); }; +// Annotation added by retry code to indicate a transparent retry. +struct IsTransparentRetry { + static absl::string_view DebugKey() { return "IsTransparentRetry"; } + static constexpr bool kRepeatable = false; + using ValueType = bool; + static std::string DisplayValue(ValueType x) { return x ? "true" : "false"; } +}; + // Annotation added by a transport to note that server trailing metadata // is a Trailers-Only response. struct GrpcTrailersOnly { @@ -1536,7 +1544,8 @@ using grpc_metadata_batch_base = grpc_core::MetadataMap< grpc_core::GrpcStreamNetworkState, grpc_core::PeerString, grpc_core::GrpcStatusContext, grpc_core::GrpcStatusFromWire, grpc_core::GrpcCallWasCancelled, grpc_core::WaitForReady, - grpc_core::GrpcTrailersOnly, grpc_core::GrpcTarPit, + grpc_core::IsTransparentRetry, grpc_core::GrpcTrailersOnly, + grpc_core::GrpcTarPit, grpc_core::GrpcRegisteredMethod GRPC_CUSTOM_CLIENT_METADATA GRPC_CUSTOM_SERVER_METADATA>; diff --git a/src/core/load_balancing/lb_policy.h b/src/core/load_balancing/lb_policy.h index 838d89ae2d5..91441547414 100644 --- a/src/core/load_balancing/lb_policy.h +++ b/src/core/load_balancing/lb_policy.h @@ -484,6 +484,16 @@ class LoadBalancingPolicy : public InternallyRefCounted { ChannelArgs channel_args_; }; +namespace promise_detail { + +template <> +struct OldStyleContext { + static constexpr grpc_context_index kIndex = + GRPC_SUBCHANNEL_CALL_TRACKER_INTERFACE; +}; + +} // namespace promise_detail + } // namespace grpc_core #endif // GRPC_SRC_CORE_LOAD_BALANCING_LB_POLICY_H diff --git a/src/core/telemetry/call_tracer.h b/src/core/telemetry/call_tracer.h index 3f98c7098e0..967658fa36b 100644 --- a/src/core/telemetry/call_tracer.h +++ b/src/core/telemetry/call_tracer.h @@ -33,6 +33,7 @@ #include "src/core/lib/channel/context.h" #include "src/core/lib/gprpp/ref_counted_string.h" #include "src/core/lib/iomgr/error.h" +#include "src/core/lib/promise/context.h" #include "src/core/lib/resource_quota/arena.h" #include "src/core/lib/slice/slice_buffer.h" #include "src/core/lib/transport/call_final_info.h" @@ -221,6 +222,21 @@ void AddClientCallTracerToContext(grpc_call_context_element* call_context, void AddServerCallTracerToContext(grpc_call_context_element* call_context, ServerCallTracer* tracer); +template <> +struct ContextSubclass { + using Base = CallTracerInterface; +}; + +template <> +struct ContextSubclass { + using Base = CallTracerInterface; +}; + +template <> +struct ContextSubclass { + using Base = CallTracerAnnotationInterface; +}; + } // namespace grpc_core #endif // GRPC_SRC_CORE_TELEMETRY_CALL_TRACER_H diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 39fb7a6487f..3ed50fe703b 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -19,6 +19,7 @@ CORE_SOURCE_FILES = [ 'src/core/channelz/channelz.cc', 'src/core/channelz/channelz_registry.cc', 'src/core/client_channel/backup_poller.cc', + 'src/core/client_channel/client_channel.cc', 'src/core/client_channel/client_channel_factory.cc', 'src/core/client_channel/client_channel_filter.cc', 'src/core/client_channel/client_channel_plugin.cc', @@ -26,6 +27,7 @@ CORE_SOURCE_FILES = [ 'src/core/client_channel/config_selector.cc', 'src/core/client_channel/dynamic_filters.cc', 'src/core/client_channel/global_subchannel_pool.cc', + 'src/core/client_channel/load_balanced_call_destination.cc', 'src/core/client_channel/local_subchannel_pool.cc', 'src/core/client_channel/retry_filter.cc', 'src/core/client_channel/retry_filter_legacy_call_data.cc', @@ -486,6 +488,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/experiments/config.cc', 'src/core/lib/experiments/experiments.cc', 'src/core/lib/gprpp/crash.cc', + 'src/core/lib/gprpp/dump_args.cc', 'src/core/lib/gprpp/examine_stack.cc', 'src/core/lib/gprpp/fork.cc', 'src/core/lib/gprpp/host_port.cc', diff --git a/test/core/call/yodel/grpc_yodel_test.bzl b/test/core/call/yodel/grpc_yodel_test.bzl index ab43116e481..de21e4d20f6 100644 --- a/test/core/call/yodel/grpc_yodel_test.bzl +++ b/test/core/call/yodel/grpc_yodel_test.bzl @@ -16,7 +16,7 @@ Generate one transport test & associated fuzzer """ -load("//bazel:grpc_build_system.bzl", "grpc_cc_test") +load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test") load("//test/core/test_util:grpc_fuzzer.bzl", "grpc_proto_fuzzer") def grpc_yodel_test(name, deps): @@ -57,3 +57,12 @@ def grpc_yodel_test(name, deps): corpus = "corpus/%s" % name, proto = None, ) + +def grpc_yodel_simple_test(name, **kwargs): + grpc_cc_library( + name = "%s_test_lib" % name, + testonly = True, + alwayslink = 1, + **kwargs + ) + grpc_yodel_test(name, deps = ["%s_test_lib" % name]) diff --git a/test/core/call/yodel/yodel_test.cc b/test/core/call/yodel/yodel_test.cc index 88a3c4033ff..bf9d5da8e82 100644 --- a/test/core/call/yodel/yodel_test.cc +++ b/test/core/call/yodel/yodel_test.cc @@ -14,8 +14,12 @@ #include "test/core/call/yodel/yodel_test.h" +#include + #include "absl/random/random.h" +#include "src/core/lib/config/core_configuration.h" +#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/timer_manager.h" #include "src/core/lib/resource_quota/resource_quota.h" @@ -117,13 +121,13 @@ void SimpleTestRegistry::ContributeTests(std::vector& tests) { class YodelTest::WatchDog { public: explicit WatchDog(YodelTest* test) : test_(test) {} - ~WatchDog() { test_->event_engine_->Cancel(timer_); } + ~WatchDog() { test_->state_->event_engine->Cancel(timer_); } private: YodelTest* const test_; grpc_event_engine::experimental::EventEngine::TaskHandle const timer_{ - test_->event_engine_->RunAfter(Duration::Minutes(5), - [this]() { test_->Timeout(); })}; + test_->state_->event_engine->RunAfter(Duration::Minutes(5), + [this]() { test_->Timeout(); })}; }; /////////////////////////////////////////////////////////////////////////////// @@ -131,36 +135,46 @@ class YodelTest::WatchDog { YodelTest::YodelTest(const fuzzing_event_engine::Actions& actions, absl::BitGenRef rng) - : rng_(rng), - event_engine_{ - std::make_shared( - []() { - grpc_timer_manager_set_threading(false); - grpc_event_engine::experimental::FuzzingEventEngine::Options - options; - return options; - }(), - actions)}, - call_arena_allocator_{MakeRefCounted( - MakeResourceQuota("test-quota") - ->memory_quota() - ->CreateMemoryAllocator("test-allocator"), - 1024)} {} + : rng_(rng), actions_(actions) {} void YodelTest::RunTest() { - TestImpl(); + CoreConfiguration::Reset(); + InitCoreConfiguration(); + state_ = std::make_unique(); + state_->event_engine = + std::make_shared( + []() { + grpc_timer_manager_set_threading(false); + grpc_event_engine::experimental::FuzzingEventEngine::Options + options; + return options; + }(), + actions_); + state_->call_arena_allocator = MakeRefCounted( + ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator( + "test-allocator"), + 1024); + { + ExecCtx exec_ctx; + InitTest(); + } + { + ExecCtx exec_ctx; + TestImpl(); + } EXPECT_EQ(pending_actions_.size(), 0) << "There are still pending actions: did you forget to call " "WaitForAllPendingWork()?"; Shutdown(); - event_engine_->TickUntilIdle(); - event_engine_->UnsetGlobalHooks(); + state_->event_engine->TickUntilIdle(); + state_->event_engine->UnsetGlobalHooks(); } void YodelTest::TickUntilTrue(absl::FunctionRef poll) { WatchDog watchdog(this); while (!poll()) { - event_engine_->Tick(); + ExecCtx exec_ctx; + state_->event_engine->Tick(); } } @@ -171,7 +185,7 @@ void YodelTest::WaitForAllPendingWork() { pending_actions_.pop(); continue; } - event_engine_->Tick(); + state_->event_engine->Tick(); } } diff --git a/test/core/call/yodel/yodel_test.h b/test/core/call/yodel/yodel_test.h index bca587eff41..d80675750d2 100644 --- a/test/core/call/yodel/yodel_test.h +++ b/test/core/call/yodel/yodel_test.h @@ -350,7 +350,7 @@ class YodelTest : public ::testing::Test { yodel_detail::SequenceSpawner( name_and_location, yodel_detail::SpawnerForContext(std::move(context), - event_engine_.get()), + state_->event_engine.get()), [this](yodel_detail::NameAndLocation name_and_location, int step) { auto action = std::make_shared( name_and_location, step); @@ -361,9 +361,10 @@ class YodelTest : public ::testing::Test { } auto MakeCall(ClientMetadataHandle client_initial_metadata) { - auto* arena = call_arena_allocator_->MakeArena(); - return MakeCallPair(std::move(client_initial_metadata), event_engine_.get(), - arena, call_arena_allocator_, nullptr); + auto* arena = state_->call_arena_allocator->MakeArena(); + return MakeCallPair(std::move(client_initial_metadata), + state_->event_engine.get(), arena, + state_->call_arena_allocator, nullptr); } void WaitForAllPendingWork(); @@ -384,25 +385,35 @@ class YodelTest : public ::testing::Test { const std::shared_ptr& event_engine() { - return event_engine_; + return state_->event_engine; } private: class WatchDog; + struct State { + grpc::testing::TestGrpcScope grpc_scope; + std::shared_ptr + event_engine; + RefCountedPtr call_arena_allocator; + }; virtual void TestImpl() = 0; void Timeout(); void TickUntilTrue(absl::FunctionRef poll); + // Called before the test runs, after core configuration has been reset + // and before the event engine is started. + // This is a good time to register any custom core configuration builders. + virtual void InitCoreConfiguration() {} + // Called after the event engine has been started, but before the test runs. + virtual void InitTest() {} // Called after the test has run, but before the event engine is shut down. virtual void Shutdown() {} - grpc::testing::TestGrpcScope grpc_scope_; absl::BitGenRef rng_; - const std::shared_ptr - event_engine_; - const RefCountedPtr call_arena_allocator_; + fuzzing_event_engine::Actions actions_; + std::unique_ptr state_; std::queue> pending_actions_; }; diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD index 3e014705200..eaeccd3b414 100644 --- a/test/core/client_channel/BUILD +++ b/test/core/client_channel/BUILD @@ -13,14 +13,15 @@ # limitations under the License. load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package") +load("//test/core/call/yodel:grpc_yodel_test.bzl", "grpc_yodel_simple_test") grpc_package(name = "test/core/client_channel") licenses(["notice"]) grpc_cc_test( - name = "client_channel_test", - srcs = ["client_channel_test.cc"], + name = "subchannel_args_test", + srcs = ["subchannel_args_test.cc"], external_deps = ["gtest"], language = "C++", uses_event_engine = False, @@ -33,6 +34,36 @@ grpc_cc_test( ], ) +grpc_yodel_simple_test( + name = "client_channel", + srcs = ["client_channel_test.cc"], + external_deps = ["gtest"], + deps = [ + "//:grpc_client_channel", + "//test/core/call/yodel:yodel_test", + ], +) + +grpc_yodel_simple_test( + name = "connected_subchannel", + srcs = ["connected_subchannel_test.cc"], + external_deps = ["gtest"], + deps = [ + "//:grpc_client_channel", + "//test/core/call/yodel:yodel_test", + ], +) + +grpc_yodel_simple_test( + name = "load_balanced_call_destination", + srcs = ["load_balanced_call_destination_test.cc"], + external_deps = ["gtest"], + deps = [ + "//:grpc_client_channel", + "//test/core/call/yodel:yodel_test", + ], +) + grpc_cc_test( name = "retry_throttle_test", srcs = ["retry_throttle_test.cc"], diff --git a/test/core/client_channel/client_channel_test.cc b/test/core/client_channel/client_channel_test.cc index 7fe497d91e8..78b44db971c 100644 --- a/test/core/client_channel/client_channel_test.cc +++ b/test/core/client_channel/client_channel_test.cc @@ -1,5 +1,4 @@ -// -// Copyright 2022 gRPC authors. +// Copyright 2024 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,79 +11,272 @@ // 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/client_channel/client_channel.h" + +#include #include -#include "absl/types/optional.h" +#include "absl/strings/string_view.h" #include "gtest/gtest.h" -#include -#include +#include -#include "src/core/client_channel/client_channel_filter.h" -#include "src/core/client_channel/subchannel_pool_interface.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/resolver/endpoint_addresses.h" -#include "test/core/test_util/test_config.h" +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/config/core_configuration.h" +#include "test/core/call/yodel/yodel_test.h" namespace grpc_core { -namespace testing { -namespace { -TEST(MakeSubchannelArgs, UsesChannelDefaultAuthorityByDefault) { - ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs( - ChannelArgs(), ChannelArgs(), nullptr, "foo.example.com"); - EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "foo.example.com"); -} +using EventEngine = grpc_event_engine::experimental::EventEngine; -TEST(MakeSubchannelArgs, DefaultAuthorityFromChannelArgs) { - ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs( - ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"), - ChannelArgs(), nullptr, "foo.example.com"); - EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com"); +namespace { +const absl::string_view kTestScheme = "test"; +const absl::string_view kTestTarget = "/target"; +const absl::string_view kTestPath = "/test_method"; +std::string TestTarget() { + return absl::StrCat(kTestScheme, "://", kTestTarget); } +} // namespace -TEST(MakeSubchannelArgs, DefaultAuthorityFromResolver) { - ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs( - ChannelArgs(), - ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"), nullptr, - "foo.example.com"); - EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com"); -} +class ClientChannelTest : public YodelTest { + protected: + using YodelTest::YodelTest; -TEST(MakeSubchannelArgs, - DefaultAuthorityFromChannelArgsOverridesValueFromResolver) { - ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs( - ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"), - ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "baz.example.com"), nullptr, - "foo.example.com"); - EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com"); -} + ClientChannel& InitChannel(const ChannelArgs& args) { + auto channel = ClientChannel::Create(TestTarget(), CompleteArgs(args)); + CHECK_OK(channel); + channel_ = OrphanablePtr( + DownCast(channel->release())); + return *channel_; + } + + ClientChannel& channel() { return *channel_; } + + ClientMetadataHandle MakeClientInitialMetadata() { + auto client_initial_metadata = Arena::MakePooled(); + client_initial_metadata->Set(HttpPathMetadata(), + Slice::FromCopiedString(kTestPath)); + return client_initial_metadata; + } + + CallHandler TickUntilCallStarted() { + return TickUntil([this]() -> Poll { + auto handler = call_destination_->PopHandler(); + if (handler.has_value()) return std::move(*handler); + return Pending(); + }); + } + + void QueueNameResolutionResult(Resolver::Result result) { + if (resolver_ != nullptr) { + resolver_->QueueNameResolutionResult(std::move(result)); + } else { + early_resolver_results_.push(std::move(result)); + } + } + + Resolver::Result MakeSuccessfulResolutionResult( + absl::string_view endpoint_address) { + Resolver::Result result; + grpc_resolved_address address; + CHECK(grpc_parse_uri(URI::Parse(endpoint_address).value(), &address)); + result.addresses = EndpointAddressesList({EndpointAddresses{address, {}}}); + return result; + } + + private: + class TestConnector final : public SubchannelConnector { + public: + void Connect(const Args&, Result*, grpc_closure* notify) override { + CHECK_EQ(notify_, nullptr); + notify_ = notify; + } + + void Shutdown(grpc_error_handle error) override { + if (notify_ != nullptr) ExecCtx::Run(DEBUG_LOCATION, notify_, error); + } + + private: + grpc_closure* notify_ = nullptr; + }; + + class TestClientChannelFactory final : public ClientChannelFactory { + public: + RefCountedPtr CreateSubchannel( + const grpc_resolved_address& address, + const ChannelArgs& args) override { + gpr_log(GPR_INFO, "CreateSubchannel: args=%s", args.ToString().c_str()); + return Subchannel::Create(MakeOrphanable(), address, args); + } + }; + + class TestCallDestination final : public UnstartedCallDestination { + public: + void StartCall(UnstartedCallHandler unstarted_call_handler) override { + handlers_.push( + unstarted_call_handler.V2HackToStartCallWithoutACallFilterStack()); + } + + absl::optional PopHandler() { + if (handlers_.empty()) return absl::nullopt; + auto handler = std::move(handlers_.front()); + handlers_.pop(); + return handler; + } + + void Orphaned() override {} + + private: + std::queue handlers_; + }; -TEST(MakeSubchannelArgs, ArgsFromChannelTrumpPerAddressArgs) { - ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs( - ChannelArgs().Set("foo", 1), ChannelArgs().Set("foo", 2), nullptr, - "foo.example.com"); - EXPECT_EQ(args.GetInt("foo"), 1); + class TestCallDestinationFactory final + : public ClientChannel::CallDestinationFactory { + public: + explicit TestCallDestinationFactory(ClientChannelTest* test) + : test_(test) {} + + RefCountedPtr CreateCallDestination( + ClientChannel::PickerObservable picker) override { + CHECK(!test_->picker_.has_value()); + test_->picker_ = std::move(picker); + return test_->call_destination_; + } + + private: + ClientChannelTest* const test_; + }; + + class TestResolver final : public Resolver { + public: + explicit TestResolver( + ClientChannelTest* test, ChannelArgs args, + std::unique_ptr result_handler, + std::shared_ptr work_serializer) + : test_(test), + args_(std::move(args)), + result_handler_(std::move(result_handler)), + work_serializer_(std::move(work_serializer)) { + CHECK(test_->resolver_ == nullptr); + test_->resolver_ = this; + } + + ~TestResolver() override { + CHECK_EQ(test_->resolver_, this); + test_->resolver_ = nullptr; + } + + void StartLocked() override { + while (!test_->early_resolver_results_.empty()) { + QueueNameResolutionResult( + std::move(test_->early_resolver_results_.front())); + test_->early_resolver_results_.pop(); + } + } + void ShutdownLocked() override {} + + void QueueNameResolutionResult(Resolver::Result result) { + result.args = result.args.UnionWith(args_); + work_serializer_->Run( + [self = RefAsSubclass(), + result = std::move(result)]() mutable { + self->result_handler_->ReportResult(std::move(result)); + }, + DEBUG_LOCATION); + } + + private: + ClientChannelTest* const test_; + const ChannelArgs args_; + const std::unique_ptr result_handler_; + const std::shared_ptr work_serializer_; + }; + + class TestResolverFactory final : public ResolverFactory { + public: + explicit TestResolverFactory(ClientChannelTest* test) : test_(test) {} + + OrphanablePtr CreateResolver(ResolverArgs args) const override { + CHECK_EQ(args.uri.scheme(), kTestScheme); + CHECK_EQ(args.uri.path(), kTestTarget); + return MakeOrphanable(test_, std::move(args.args), + std::move(args.result_handler), + std::move(args.work_serializer)); + } + + absl::string_view scheme() const override { return "test"; } + bool IsValidUri(const URI&) const override { return true; } + + private: + ClientChannelTest* const test_; + }; + + ChannelArgs CompleteArgs(const ChannelArgs& args) { + return args.SetObject(&call_destination_factory_) + .SetObject(&client_channel_factory_) + .SetObject(ResourceQuota::Default()) + .SetObject(std::static_pointer_cast(event_engine())) + // TODO(ctiller): remove once v3 supports retries? + .SetIfUnset(GRPC_ARG_ENABLE_RETRIES, 0); + } + + void InitCoreConfiguration() override { + CoreConfiguration::RegisterBuilder( + [this](CoreConfiguration::Builder* builder) { + builder->resolver_registry()->RegisterResolverFactory( + std::make_unique(this)); + }); + } + + void Shutdown() override { + ExecCtx exec_ctx; + channel_.reset(); + picker_.reset(); + } + + OrphanablePtr channel_; + absl::optional picker_; + TestCallDestinationFactory call_destination_factory_{this}; + TestClientChannelFactory client_channel_factory_; + RefCountedPtr call_destination_ = + MakeRefCounted(); + // Resolver results that have been reported before the resolver has been + // instantiated. + std::queue early_resolver_results_; + TestResolver* resolver_ = nullptr; +}; + +#define CLIENT_CHANNEL_TEST(name) YODEL_TEST(ClientChannelTest, name) + +CLIENT_CHANNEL_TEST(NoOp) { InitChannel(ChannelArgs()); } + +CLIENT_CHANNEL_TEST(CreateCall) { + auto& channel = InitChannel(ChannelArgs()); + auto call_initiator = channel.CreateCall(MakeClientInitialMetadata()); + SpawnTestSeq(call_initiator, "cancel", [call_initiator]() mutable { + call_initiator.Cancel(); + return Empty{}; + }); + WaitForAllPendingWork(); } -TEST(MakeSubchannelArgs, StripsOutNoSubchannelArgs) { - ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs( - ChannelArgs().Set(GRPC_ARG_NO_SUBCHANNEL_PREFIX "foo", 1), - ChannelArgs().Set(GRPC_ARG_NO_SUBCHANNEL_PREFIX "bar", 1), nullptr, - "foo.example.com"); - EXPECT_EQ(args.GetString(GRPC_ARG_NO_SUBCHANNEL_PREFIX "foo"), absl::nullopt); - EXPECT_EQ(args.GetString(GRPC_ARG_NO_SUBCHANNEL_PREFIX "bar"), absl::nullopt); +CLIENT_CHANNEL_TEST(StartCall) { + auto& channel = InitChannel(ChannelArgs()); + auto call_initiator = channel.CreateCall(MakeClientInitialMetadata()); + QueueNameResolutionResult( + MakeSuccessfulResolutionResult("ipv4:127.0.0.1:1234")); + auto call_handler = TickUntilCallStarted(); + SpawnTestSeq(call_initiator, "cancel", [call_initiator]() mutable { + call_initiator.Cancel(); + return Empty{}; + }); + WaitForAllPendingWork(); } -} // namespace -} // namespace testing -} // namespace grpc_core +// TODO(ctiller, roth): MANY more test cases +// - Resolver returns an error for the initial result, then returns a valid +// result. +// - Resolver returns a service config (various permutations). -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - grpc::testing::TestEnvironment env(&argc, argv); - auto result = RUN_ALL_TESTS(); - return result; -} +} // namespace grpc_core diff --git a/test/core/client_channel/connected_subchannel_test.cc b/test/core/client_channel/connected_subchannel_test.cc new file mode 100644 index 00000000000..613509d7456 --- /dev/null +++ b/test/core/client_channel/connected_subchannel_test.cc @@ -0,0 +1,178 @@ +// Copyright 2024 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "absl/status/status.h" +#include "absl/strings/string_view.h" +#include "gtest/gtest.h" + +#include + +#include "src/core/client_channel/client_channel.h" +#include "src/core/client_channel/local_subchannel_pool.h" +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/config/core_configuration.h" +#include "test/core/call/yodel/yodel_test.h" + +namespace grpc_core { + +using EventEngine = grpc_event_engine::experimental::EventEngine; + +namespace { +const absl::string_view kTestPath = "/test_method"; +const absl::string_view kTestAddress = "ipv4:127.0.0.1:1234"; +const absl::string_view kDefaultAuthority = "test-authority"; +} // namespace + +class ConnectedSubchannelTest : public YodelTest { + protected: + using YodelTest::YodelTest; + + RefCountedPtr InitChannel(const ChannelArgs& args) { + grpc_resolved_address addr; + CHECK(grpc_parse_uri(URI::Parse(kTestAddress).value(), &addr)); + auto subchannel = Subchannel::Create(MakeOrphanable(this), + addr, CompleteArgs(args)); + { + ExecCtx exec_ctx; + subchannel->RequestConnection(); + } + return TickUntil>( + [subchannel]() -> Poll> { + auto connected_subchannel = subchannel->connected_subchannel(); + if (connected_subchannel != nullptr) return connected_subchannel; + return Pending(); + }); + } + + ClientMetadataHandle MakeClientInitialMetadata() { + auto client_initial_metadata = Arena::MakePooled(); + client_initial_metadata->Set(HttpPathMetadata(), + Slice::FromCopiedString(kTestPath)); + return client_initial_metadata; + } + + CallInitiatorAndHandler MakeCall( + ClientMetadataHandle client_initial_metadata) { + return MakeCallPair( + std::move(client_initial_metadata), event_engine().get(), + call_arena_allocator_->MakeArena(), call_arena_allocator_, nullptr); + } + + CallHandler TickUntilCallStarted() { + return TickUntil([this]() -> Poll { + auto handler = PopHandler(); + if (handler.has_value()) return std::move(*handler); + return Pending(); + }); + } + + private: + class TestTransport final : public ClientTransport { + public: + explicit TestTransport(ConnectedSubchannelTest* test) : test_(test) {} + + void Orphan() override { + state_tracker_.SetState(GRPC_CHANNEL_SHUTDOWN, absl::OkStatus(), + "transport-orphaned"); + Unref(); + } + + FilterStackTransport* filter_stack_transport() override { return nullptr; } + ClientTransport* client_transport() override { return this; } + ServerTransport* server_transport() override { return nullptr; } + absl::string_view GetTransportName() const override { return "test"; } + void SetPollset(grpc_stream*, grpc_pollset*) override {} + void SetPollsetSet(grpc_stream*, grpc_pollset_set*) override {} + void PerformOp(grpc_transport_op* op) override { + LOG(INFO) << "PerformOp: " << grpc_transport_op_string(op); + if (op->start_connectivity_watch != nullptr) { + state_tracker_.AddWatcher(op->start_connectivity_watch_state, + std::move(op->start_connectivity_watch)); + } + ExecCtx::Run(DEBUG_LOCATION, op->on_consumed, absl::OkStatus()); + } + + void StartCall(CallHandler call_handler) override { + test_->handlers_.push(std::move(call_handler)); + } + + private: + ConnectedSubchannelTest* const test_; + ConnectivityStateTracker state_tracker_{"test-transport"}; + }; + + class TestConnector final : public SubchannelConnector { + public: + explicit TestConnector(ConnectedSubchannelTest* test) : test_(test) {} + + void Connect(const Args& args, Result* result, + grpc_closure* notify) override { + result->channel_args = args.channel_args; + result->transport = MakeOrphanable(test_).release(); + ExecCtx::Run(DEBUG_LOCATION, notify, absl::OkStatus()); + } + + void Shutdown(grpc_error_handle) override {} + + private: + ConnectedSubchannelTest* const test_; + }; + + ChannelArgs CompleteArgs(const ChannelArgs& args) { + return args.SetObject(ResourceQuota::Default()) + .SetObject(std::static_pointer_cast(event_engine())) + .SetObject(MakeRefCounted()) + .Set(GRPC_ARG_DEFAULT_AUTHORITY, kDefaultAuthority); + } + + void InitCoreConfiguration() override {} + + void Shutdown() override {} + + absl::optional PopHandler() { + if (handlers_.empty()) return absl::nullopt; + auto handler = std::move(handlers_.front()); + handlers_.pop(); + return handler; + } + + std::queue handlers_; + RefCountedPtr call_arena_allocator_ = + MakeRefCounted( + ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator( + "test"), + 1024); +}; + +#define CONNECTED_SUBCHANNEL_CHANNEL_TEST(name) \ + YODEL_TEST(ConnectedSubchannelTest, name) + +CONNECTED_SUBCHANNEL_CHANNEL_TEST(NoOp) { InitChannel(ChannelArgs()); } + +CONNECTED_SUBCHANNEL_CHANNEL_TEST(StartCall) { + auto channel = InitChannel(ChannelArgs()); + auto call = MakeCall(MakeClientInitialMetadata()); + SpawnTestSeq( + call.handler, "start-call", [channel, handler = call.handler]() mutable { + channel->unstarted_call_destination()->StartCall(std::move(handler)); + return Empty{}; + }); + auto handler = TickUntilCallStarted(); + WaitForAllPendingWork(); +} + +} // namespace grpc_core diff --git a/test/core/client_channel/corpus/client_channel/empty b/test/core/client_channel/corpus/client_channel/empty new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/test/core/client_channel/corpus/client_channel/empty @@ -0,0 +1 @@ + diff --git a/test/core/client_channel/corpus/connected_subchannel/empty b/test/core/client_channel/corpus/connected_subchannel/empty new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/test/core/client_channel/corpus/connected_subchannel/empty @@ -0,0 +1 @@ + diff --git a/test/core/client_channel/corpus/load_balanced_call_destination/empty b/test/core/client_channel/corpus/load_balanced_call_destination/empty new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/test/core/client_channel/corpus/load_balanced_call_destination/empty @@ -0,0 +1 @@ + diff --git a/test/core/client_channel/load_balanced_call_destination_test.cc b/test/core/client_channel/load_balanced_call_destination_test.cc new file mode 100644 index 00000000000..c8651fc305f --- /dev/null +++ b/test/core/client_channel/load_balanced_call_destination_test.cc @@ -0,0 +1,202 @@ +// Copyright 2024 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/client_channel/load_balanced_call_destination.h" + +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include + +#include "test/core/call/yodel/yodel_test.h" + +using testing::StrictMock; + +namespace grpc_core { + +using EventEngine = grpc_event_engine::experimental::EventEngine; + +namespace { +const absl::string_view kTestPath = "/test_method"; +} // namespace + +class LoadBalancedCallDestinationTest : public YodelTest { + protected: + using YodelTest::YodelTest; + + ClientMetadataHandle MakeClientInitialMetadata() { + auto client_initial_metadata = Arena::MakePooled(); + client_initial_metadata->Set(HttpPathMetadata(), + Slice::FromCopiedString(kTestPath)); + return client_initial_metadata; + } + + CallInitiatorAndHandler MakeCall( + ClientMetadataHandle client_initial_metadata) { + return MakeCallPair( + std::move(client_initial_metadata), event_engine().get(), + call_arena_allocator_->MakeArena(), call_arena_allocator_, nullptr); + } + + CallHandler TickUntilCallStarted() { + auto poll = [this]() -> Poll { + auto handler = call_destination_->PopHandler(); + if (handler.has_value()) return std::move(*handler); + return Pending(); + }; + return TickUntil(absl::FunctionRef()>(poll)); + } + + LoadBalancedCallDestination& destination_under_test() { + return *destination_under_test_; + } + + ClientChannel::PickerObservable& picker() { return picker_; } + + RefCountedPtr subchannel() { return subchannel_; } + + private: + class TestCallDestination final : public UnstartedCallDestination { + public: + void StartCall(UnstartedCallHandler unstarted_call_handler) override { + handlers_.push( + unstarted_call_handler.V2HackToStartCallWithoutACallFilterStack()); + } + + absl::optional PopHandler() { + if (handlers_.empty()) return absl::nullopt; + auto handler = std::move(handlers_.front()); + handlers_.pop(); + return handler; + } + + void Orphaned() override {} + + private: + std::queue handlers_; + }; + + class TestSubchannel : public SubchannelInterfaceWithCallDestination { + public: + explicit TestSubchannel( + RefCountedPtr call_destination) + : call_destination_(std::move(call_destination)) {} + + void WatchConnectivityState( + std::unique_ptr) override { + Crash("not implemented"); + } + void CancelConnectivityStateWatch( + ConnectivityStateWatcherInterface*) override { + Crash("not implemented"); + } + void RequestConnection() override { Crash("not implemented"); } + void ResetBackoff() override { Crash("not implemented"); } + void AddDataWatcher(std::unique_ptr) override { + Crash("not implemented"); + } + void CancelDataWatcher(DataWatcherInterface*) override { + Crash("not implemented"); + } + RefCountedPtr call_destination() override { + return call_destination_; + } + + private: + const RefCountedPtr call_destination_; + }; + + void InitCoreConfiguration() override {} + + void Shutdown() override { + channel_.reset(); + picker_ = ClientChannel::PickerObservable(nullptr); + call_destination_.reset(); + destination_under_test_.reset(); + call_arena_allocator_.reset(); + subchannel_.reset(); + } + + OrphanablePtr channel_; + ClientChannel::PickerObservable picker_{nullptr}; + RefCountedPtr call_destination_ = + MakeRefCounted(); + RefCountedPtr destination_under_test_ = + MakeRefCounted(picker_); + RefCountedPtr call_arena_allocator_ = + MakeRefCounted( + ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator( + "test"), + 1024); + RefCountedPtr subchannel_ = + MakeRefCounted(call_destination_); +}; + +#define LOAD_BALANCED_CALL_DESTINATION_TEST(name) \ + YODEL_TEST(LoadBalancedCallDestinationTest, name) + +class MockPicker : public LoadBalancingPolicy::SubchannelPicker { + public: + MOCK_METHOD(LoadBalancingPolicy::PickResult, Pick, + (LoadBalancingPolicy::PickArgs)); +}; + +LOAD_BALANCED_CALL_DESTINATION_TEST(NoOp) {} + +LOAD_BALANCED_CALL_DESTINATION_TEST(CreateCall) { + auto call = MakeCall(MakeClientInitialMetadata()); + SpawnTestSeq( + call.initiator, "initiator", + [this, handler = std::move(call.handler)]() { + destination_under_test().StartCall(handler); + return Empty{}; + }, + [call_initiator = call.initiator]() mutable { + call_initiator.Cancel(); + return Empty{}; + }); + WaitForAllPendingWork(); +} + +LOAD_BALANCED_CALL_DESTINATION_TEST(StartCall) { + auto call = MakeCall(MakeClientInitialMetadata()); + SpawnTestSeq(call.initiator, "initiator", + [this, handler = std::move(call.handler)]() { + destination_under_test().StartCall(handler); + return Empty{}; + }); + auto mock_picker = MakeRefCounted>(); + EXPECT_CALL(*mock_picker, Pick) + .WillOnce([this](LoadBalancingPolicy::PickArgs) { + return LoadBalancingPolicy::PickResult::Complete{subchannel()}; + }); + picker().Set(mock_picker); + auto handler = TickUntilCallStarted(); + SpawnTestSeq(call.initiator, "cancel", + [call_initiator = call.initiator]() mutable { + call_initiator.Cancel(); + return Empty{}; + }); + WaitForAllPendingWork(); +} + +// TODO(roth, ctiller): more tests +// - tests for the picker returning queue, fail, and drop results. + +} // namespace grpc_core diff --git a/test/core/client_channel/subchannel_args_test.cc b/test/core/client_channel/subchannel_args_test.cc new file mode 100644 index 00000000000..3750a8dc42b --- /dev/null +++ b/test/core/client_channel/subchannel_args_test.cc @@ -0,0 +1,90 @@ +// +// Copyright 2022 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include + +#include "absl/types/optional.h" +#include "gtest/gtest.h" + +#include +#include + +#include "src/core/client_channel/subchannel.h" +#include "src/core/client_channel/subchannel_pool_interface.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/resolver/endpoint_addresses.h" +#include "test/core/test_util/test_config.h" + +namespace grpc_core { +namespace testing { +namespace { + +TEST(MakeSubchannelArgs, UsesChannelDefaultAuthorityByDefault) { + ChannelArgs args = Subchannel::MakeSubchannelArgs( + ChannelArgs(), ChannelArgs(), nullptr, "foo.example.com"); + EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "foo.example.com"); +} + +TEST(MakeSubchannelArgs, DefaultAuthorityFromChannelArgs) { + ChannelArgs args = Subchannel::MakeSubchannelArgs( + ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"), + ChannelArgs(), nullptr, "foo.example.com"); + EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com"); +} + +TEST(MakeSubchannelArgs, DefaultAuthorityFromResolver) { + ChannelArgs args = Subchannel::MakeSubchannelArgs( + ChannelArgs(), + ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"), nullptr, + "foo.example.com"); + EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com"); +} + +TEST(MakeSubchannelArgs, + DefaultAuthorityFromChannelArgsOverridesValueFromResolver) { + ChannelArgs args = Subchannel::MakeSubchannelArgs( + ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"), + ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "baz.example.com"), nullptr, + "foo.example.com"); + EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com"); +} + +TEST(MakeSubchannelArgs, ArgsFromChannelTrumpPerAddressArgs) { + ChannelArgs args = Subchannel::MakeSubchannelArgs(ChannelArgs().Set("foo", 1), + ChannelArgs().Set("foo", 2), + nullptr, "foo.example.com"); + EXPECT_EQ(args.GetInt("foo"), 1); +} + +TEST(MakeSubchannelArgs, StripsOutNoSubchannelArgs) { + ChannelArgs args = Subchannel::MakeSubchannelArgs( + ChannelArgs().Set(GRPC_ARG_NO_SUBCHANNEL_PREFIX "foo", 1), + ChannelArgs().Set(GRPC_ARG_NO_SUBCHANNEL_PREFIX "bar", 1), nullptr, + "foo.example.com"); + EXPECT_EQ(args.GetString(GRPC_ARG_NO_SUBCHANNEL_PREFIX "foo"), absl::nullopt); + EXPECT_EQ(args.GetString(GRPC_ARG_NO_SUBCHANNEL_PREFIX "bar"), absl::nullopt); +} + +} // namespace +} // namespace testing +} // namespace grpc_core + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + grpc::testing::TestEnvironment env(&argc, argv); + auto result = RUN_ALL_TESTS(); + return result; +} diff --git a/test/core/promise/BUILD b/test/core/promise/BUILD index 2b2b2cb9943..973dfaa88d3 100644 --- a/test/core/promise/BUILD +++ b/test/core/promise/BUILD @@ -145,6 +145,7 @@ grpc_cc_test( uses_event_engine = False, uses_polling = False, deps = [ + "poll_matcher", "//:promise", "//src/core:map", ], diff --git a/test/core/promise/map_test.cc b/test/core/promise/map_test.cc index c153327971c..85697084084 100644 --- a/test/core/promise/map_test.cc +++ b/test/core/promise/map_test.cc @@ -20,12 +20,13 @@ #include "gtest/gtest.h" #include "src/core/lib/promise/promise.h" +#include "test/core/promise/poll_matcher.h" namespace grpc_core { TEST(MapTest, Works) { Promise x = Map([]() { return 42; }, [](int i) { return i / 2; }); - EXPECT_EQ(x(), Poll(21)); + EXPECT_THAT(x(), IsReady(21)); } TEST(MapTest, JustElem) { @@ -34,6 +35,21 @@ TEST(MapTest, JustElem) { EXPECT_EQ(JustElem<0>()(t), 1); } +TEST(CheckDelayedTest, SeesImmediate) { + auto x = CheckDelayed([]() { return 42; }); + EXPECT_THAT(x(), IsReady(std::make_tuple(42, false))); +} + +TEST(CheckDelayedTest, SeesDelayed) { + auto x = CheckDelayed([n = 1]() mutable -> Poll { + if (n == 0) return 42; + --n; + return Pending{}; + }); + EXPECT_THAT(x(), IsPending()); + EXPECT_THAT(x(), IsReady(std::make_tuple(42, true))); +} + } // namespace grpc_core int main(int argc, char** argv) { diff --git a/test/core/promise/observable_test.cc b/test/core/promise/observable_test.cc index e3c74332f04..b6a2268ad99 100644 --- a/test/core/promise/observable_test.cc +++ b/test/core/promise/observable_test.cc @@ -140,6 +140,16 @@ TEST(ObservableTest, MultipleActivitiesWakeUp) { EXPECT_THAT(next2(), IsReady(2)); } +TEST(ObservableTest, NoDeadlockOnDestruction) { + StrictMock activity; + Observable observable(1); + activity.Activate(); + { + auto next = observable.Next(1); + EXPECT_THAT(next(), IsPending()); + } +} + class ThreadWakeupScheduler { public: template diff --git a/test/core/surface/secure_channel_create_test.cc b/test/core/surface/secure_channel_create_test.cc index 89f21615e98..e22aa5cd61b 100644 --- a/test/core/surface/secure_channel_create_test.cc +++ b/test/core/surface/secure_channel_create_test.cc @@ -39,7 +39,7 @@ void test_unknown_scheme_target(void) { grpc_core::Channel::FromC(chan)->channel_stack(), 0); ASSERT_STREQ(elem->filter->name, "lame-client"); grpc_core::ExecCtx exec_ctx; - grpc_core::Channel::FromC(chan)->Unref(); + grpc_core::Channel::FromC(chan)->Orphan(); creds->Unref(); } @@ -53,7 +53,7 @@ void test_security_connector_already_in_arg(void) { grpc_core::Channel::FromC(chan)->channel_stack(), 0); ASSERT_STREQ(elem->filter->name, "lame-client"); grpc_core::ExecCtx exec_ctx; - grpc_core::Channel::FromC(chan)->Unref(); + grpc_core::Channel::FromC(chan)->Orphan(); } void test_null_creds(void) { @@ -62,7 +62,7 @@ void test_null_creds(void) { grpc_core::Channel::FromC(chan)->channel_stack(), 0); ASSERT_STREQ(elem->filter->name, "lame-client"); grpc_core::ExecCtx exec_ctx; - grpc_core::Channel::FromC(chan)->Unref(); + grpc_core::Channel::FromC(chan)->Orphan(); } TEST(SecureChannelCreateTest, MainTest) { diff --git a/test/core/transport/test_suite/transport_test.cc b/test/core/transport/test_suite/transport_test.cc index 1dd3d9db500..12e2932faa7 100644 --- a/test/core/transport/test_suite/transport_test.cc +++ b/test/core/transport/test_suite/transport_test.cc @@ -58,12 +58,10 @@ void TransportTest::ServerCallDestination::StartCall( } absl::optional TransportTest::ServerCallDestination::PopHandler() { - if (!handlers_.empty()) { - auto handler = std::move(handlers_.front()); - handlers_.pop(); - return handler; - } - return absl::nullopt; + if (handlers_.empty()) return absl::nullopt; + auto handler = std::move(handlers_.front()); + handlers_.pop(); + return handler; } } // namespace grpc_core diff --git a/test/core/transport/test_suite/transport_test.h b/test/core/transport/test_suite/transport_test.h index 6122b42cf91..97e099f348a 100644 --- a/test/core/transport/test_suite/transport_test.h +++ b/test/core/transport/test_suite/transport_test.h @@ -42,7 +42,7 @@ class TransportTest : public YodelTest { TransportTest(const TransportFixture& fixture, const fuzzing_event_engine::Actions& actions, absl::BitGenRef rng) - : YodelTest(actions, rng), transport_pair_(fixture(event_engine())) {} + : YodelTest(actions, rng), fixture_(std::move(fixture)) {} void SetServerCallDestination(); CallInitiator CreateCall(ClientMetadataHandle client_initial_metadata); @@ -60,6 +60,8 @@ class TransportTest : public YodelTest { std::queue handlers_; }; + void InitTest() override { transport_pair_ = fixture_(event_engine()); } + void Shutdown() override { transport_pair_.client.reset(); transport_pair_.server.reset(); @@ -67,6 +69,7 @@ class TransportTest : public YodelTest { RefCountedPtr server_call_destination_ = MakeRefCounted(); + const TransportFixture& fixture_; ClientAndServerTransportPair transport_pair_; }; diff --git a/tools/distrib/fix_build_deps.py b/tools/distrib/fix_build_deps.py index d34a0c03f03..8e4acb81ca7 100755 --- a/tools/distrib/fix_build_deps.py +++ b/tools/distrib/fix_build_deps.py @@ -400,6 +400,7 @@ for dirname in [ "src/cpp/ext/otel", "test/core/backoff", "test/core/call/yodel", + "test/core/client_channel", "test/core/experiments", "test/core/uri", "test/core/test_util", @@ -430,7 +431,10 @@ for dirname in [ "grpc_cc_library": grpc_cc_library, "grpc_cc_test": grpc_cc_library, "grpc_core_end2end_test": lambda **kwargs: None, + "grpc_filegroup": lambda **kwargs: None, "grpc_transport_test": lambda **kwargs: None, + "grpc_yodel_test": lambda **kwargs: None, + "grpc_yodel_simple_test": lambda **kwargs: None, "grpc_fuzzer": grpc_cc_library, "grpc_fuzz_test": grpc_cc_library, "grpc_proto_fuzzer": grpc_cc_library, diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index a65cdb9fc4f..c3428fdd3a1 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1093,6 +1093,8 @@ src/core/channelz/channelz_registry.cc \ src/core/channelz/channelz_registry.h \ src/core/client_channel/backup_poller.cc \ src/core/client_channel/backup_poller.h \ +src/core/client_channel/client_channel.cc \ +src/core/client_channel/client_channel.h \ src/core/client_channel/client_channel_factory.cc \ src/core/client_channel/client_channel_factory.h \ src/core/client_channel/client_channel_filter.cc \ @@ -1108,6 +1110,8 @@ src/core/client_channel/dynamic_filters.cc \ src/core/client_channel/dynamic_filters.h \ src/core/client_channel/global_subchannel_pool.cc \ src/core/client_channel/global_subchannel_pool.h \ +src/core/client_channel/load_balanced_call_destination.cc \ +src/core/client_channel/load_balanced_call_destination.h \ src/core/client_channel/local_subchannel_pool.cc \ src/core/client_channel/local_subchannel_pool.h \ src/core/client_channel/retry_filter.cc \ @@ -2260,6 +2264,8 @@ src/core/lib/gprpp/debug_location.h \ src/core/lib/gprpp/directory_reader.h \ src/core/lib/gprpp/down_cast.h \ src/core/lib/gprpp/dual_ref_counted.h \ +src/core/lib/gprpp/dump_args.cc \ +src/core/lib/gprpp/dump_args.h \ src/core/lib/gprpp/env.h \ src/core/lib/gprpp/examine_stack.cc \ src/core/lib/gprpp/examine_stack.h \ @@ -2485,6 +2491,7 @@ src/core/lib/promise/interceptor_list.h \ src/core/lib/promise/latch.h \ src/core/lib/promise/loop.h \ src/core/lib/promise/map.h \ +src/core/lib/promise/observable.h \ src/core/lib/promise/party.cc \ src/core/lib/promise/party.h \ src/core/lib/promise/pipe.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 4a5484a7c0f..1439a0c8d46 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -896,6 +896,8 @@ src/core/channelz/channelz_registry.h \ src/core/client_channel/README.md \ src/core/client_channel/backup_poller.cc \ src/core/client_channel/backup_poller.h \ +src/core/client_channel/client_channel.cc \ +src/core/client_channel/client_channel.h \ src/core/client_channel/client_channel_factory.cc \ src/core/client_channel/client_channel_factory.h \ src/core/client_channel/client_channel_filter.cc \ @@ -911,6 +913,8 @@ src/core/client_channel/dynamic_filters.cc \ src/core/client_channel/dynamic_filters.h \ src/core/client_channel/global_subchannel_pool.cc \ src/core/client_channel/global_subchannel_pool.h \ +src/core/client_channel/load_balanced_call_destination.cc \ +src/core/client_channel/load_balanced_call_destination.h \ src/core/client_channel/local_subchannel_pool.cc \ src/core/client_channel/local_subchannel_pool.h \ src/core/client_channel/retry_filter.cc \ @@ -2033,6 +2037,8 @@ src/core/lib/gprpp/debug_location.h \ src/core/lib/gprpp/directory_reader.h \ src/core/lib/gprpp/down_cast.h \ src/core/lib/gprpp/dual_ref_counted.h \ +src/core/lib/gprpp/dump_args.cc \ +src/core/lib/gprpp/dump_args.h \ src/core/lib/gprpp/env.h \ src/core/lib/gprpp/examine_stack.cc \ src/core/lib/gprpp/examine_stack.h \ @@ -2259,6 +2265,7 @@ src/core/lib/promise/interceptor_list.h \ src/core/lib/promise/latch.h \ src/core/lib/promise/loop.h \ src/core/lib/promise/map.h \ +src/core/lib/promise/observable.h \ src/core/lib/promise/party.cc \ src/core/lib/promise/party.h \ src/core/lib/promise/pipe.h \ diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 8dc1a7348a1..17e26c19e11 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -2118,9 +2118,7 @@ "benchmark": false, "ci_platforms": [ "linux", - "mac", - "posix", - "windows" + "posix" ], "cpu_cost": 1.0, "exclude_configs": [], @@ -2131,9 +2129,7 @@ "name": "client_channel_test", "platforms": [ "linux", - "mac", - "posix", - "windows" + "posix" ], "uses_polling": false }, @@ -2445,6 +2441,26 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "connected_subchannel_test", + "platforms": [ + "linux", + "posix" + ], + "uses_polling": false + }, { "args": [], "benchmark": false, @@ -5533,6 +5549,26 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "load_balanced_call_destination_test", + "platforms": [ + "linux", + "posix" + ], + "uses_polling": false + }, { "args": [], "benchmark": false, @@ -10065,6 +10101,30 @@ ], "uses_polling": false }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "subchannel_args_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": false + }, { "args": [], "benchmark": false,