diff --git a/BUILD b/BUILD
index b1797baa2e8..832e608be67 100644
--- a/BUILD
+++ b/BUILD
@@ -1099,6 +1099,7 @@ grpc_cc_library(
name = "promise",
external_deps = [
"absl/types:optional",
+ "absl/status",
],
language = "c++",
public_hdrs = [
@@ -1313,6 +1314,7 @@ grpc_cc_library(
"context",
"gpr_base",
"gpr_codegen",
+ "orphanable",
"poll",
"promise_factory",
"promise_status",
@@ -1866,6 +1868,7 @@ grpc_cc_library(
"src/core/lib/channel/channelz_registry.cc",
"src/core/lib/channel/connected_channel.cc",
"src/core/lib/channel/handshaker.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",
@@ -3698,6 +3701,7 @@ grpc_cc_library(
"gpr_base",
"grpc_base",
"grpc_security_base",
+ "promise",
"ref_counted_ptr",
"tsi_fake_credentials",
],
@@ -3716,6 +3720,7 @@ grpc_cc_library(
deps = [
"gpr",
"grpc_security_base",
+ "promise",
"ref_counted_ptr",
"tsi_local_credentials",
],
@@ -3758,6 +3763,7 @@ grpc_cc_library(
"grpc_client_channel",
"grpc_security_base",
"grpc_sockaddr",
+ "promise",
"ref_counted_ptr",
"sockaddr_utils",
"tsi_local_credentials",
@@ -3787,6 +3793,7 @@ grpc_cc_library(
"gpr_base",
"grpc_base",
"grpc_security_base",
+ "promise",
"ref_counted_ptr",
"tsi_alts_credentials",
"tsi_base",
@@ -3814,6 +3821,7 @@ grpc_cc_library(
"grpc_credentials_util",
"grpc_security_base",
"grpc_transport_chttp2_alpn",
+ "promise",
"ref_counted_ptr",
"tsi_base",
"tsi_ssl_credentials",
@@ -3882,6 +3890,7 @@ grpc_cc_library(
"grpc_base",
"grpc_credentials_util",
"grpc_security_base",
+ "promise",
"tsi_base",
"tsi_ssl_credentials",
],
@@ -3904,6 +3913,7 @@ grpc_cc_library(
"gpr_base",
"grpc_base",
"grpc_security_base",
+ "promise",
"ref_counted_ptr",
],
)
@@ -3935,6 +3945,7 @@ grpc_cc_library(
"httpcli",
"httpcli_ssl_credentials",
"json",
+ "promise",
"ref_counted",
"ref_counted_ptr",
"tsi_ssl_types",
@@ -3954,9 +3965,11 @@ grpc_cc_library(
"absl/container:inlined_vector",
"absl/strings",
"absl/strings:str_format",
+ "absl/status",
],
language = "c++",
deps = [
+ "capture",
"gpr_base",
"grpc_base",
"grpc_codegen",
@@ -3965,6 +3978,7 @@ grpc_cc_library(
"httpcli",
"httpcli_ssl_credentials",
"json",
+ "promise",
"ref_counted_ptr",
"uri_parser",
],
@@ -4023,6 +4037,7 @@ grpc_cc_library(
"gpr_base",
"grpc_base",
"grpc_security_base",
+ "promise",
"ref_counted_ptr",
"tsi_ssl_credentials",
],
@@ -4058,6 +4073,7 @@ grpc_cc_library(
"httpcli",
"httpcli_ssl_credentials",
"json",
+ "promise",
"ref_counted",
"ref_counted_ptr",
"slice",
@@ -4084,6 +4100,7 @@ grpc_cc_library(
name = "grpc_security_base",
srcs = [
"src/core/lib/security/context/security_context.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",
@@ -4096,6 +4113,7 @@ grpc_cc_library(
],
hdrs = [
"src/core/lib/security/context/security_context.h",
+ "src/core/lib/security/credentials/call_creds_util.h",
"src/core/lib/security/credentials/composite/composite_credentials.h",
"src/core/lib/security/credentials/credentials.h",
"src/core/lib/security/credentials/plugin/plugin_credentials.h",
@@ -4115,13 +4133,16 @@ grpc_cc_library(
visibility = ["@grpc:public"],
deps = [
"arena",
+ "arena_promise",
"config",
"gpr_base",
"grpc_base",
"grpc_trace",
"json",
+ "promise",
"ref_counted",
"ref_counted_ptr",
+ "try_seq",
"tsi_base",
],
)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e58b5d73aab..0398c9df385 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1988,6 +1988,7 @@ add_library(grpc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
src/core/lib/channel/handshaker_registry.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
@@ -2124,6 +2125,7 @@ add_library(grpc
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
@@ -2630,6 +2632,7 @@ add_library(grpc_unsecure
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
src/core/lib/channel/handshaker_registry.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
@@ -2753,6 +2756,7 @@ add_library(grpc_unsecure
src/core/lib/security/authorization/evaluate_args.cc
src/core/lib/security/authorization/grpc_server_authz_filter.cc
src/core/lib/security/context/security_context.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
@@ -7373,52 +7377,7 @@ endif()
if(gRPC_BUILD_TESTS)
add_executable(activity_test
- src/core/ext/upb-generated/google/protobuf/any.upb.c
- src/core/ext/upb-generated/google/rpc/status.upb.c
- src/core/lib/gpr/alloc.cc
- src/core/lib/gpr/atm.cc
- src/core/lib/gpr/cpu_iphone.cc
- src/core/lib/gpr/cpu_linux.cc
- src/core/lib/gpr/cpu_posix.cc
- src/core/lib/gpr/cpu_windows.cc
- src/core/lib/gpr/env_linux.cc
- src/core/lib/gpr/env_posix.cc
- src/core/lib/gpr/env_windows.cc
- src/core/lib/gpr/log.cc
- src/core/lib/gpr/log_android.cc
- src/core/lib/gpr/log_linux.cc
- src/core/lib/gpr/log_posix.cc
- src/core/lib/gpr/log_windows.cc
- src/core/lib/gpr/murmur_hash.cc
- src/core/lib/gpr/string.cc
- src/core/lib/gpr/string_posix.cc
- src/core/lib/gpr/string_util_windows.cc
- src/core/lib/gpr/string_windows.cc
- src/core/lib/gpr/sync.cc
- src/core/lib/gpr/sync_abseil.cc
- src/core/lib/gpr/sync_posix.cc
- src/core/lib/gpr/sync_windows.cc
- src/core/lib/gpr/time.cc
- src/core/lib/gpr/time_posix.cc
- src/core/lib/gpr/time_precise.cc
- src/core/lib/gpr/time_windows.cc
- src/core/lib/gpr/tmpfile_msys.cc
- src/core/lib/gpr/tmpfile_posix.cc
- src/core/lib/gpr/tmpfile_windows.cc
- src/core/lib/gpr/wrap_memcpy.cc
- src/core/lib/gprpp/examine_stack.cc
- src/core/lib/gprpp/fork.cc
- src/core/lib/gprpp/global_config_env.cc
- src/core/lib/gprpp/host_port.cc
- src/core/lib/gprpp/mpscq.cc
- src/core/lib/gprpp/stat_posix.cc
- src/core/lib/gprpp/stat_windows.cc
- src/core/lib/gprpp/status_helper.cc
- src/core/lib/gprpp/thd_posix.cc
- src/core/lib/gprpp/thd_windows.cc
- src/core/lib/gprpp/time_util.cc
- src/core/lib/profiling/basic_timers.cc
- src/core/lib/profiling/stap_timers.cc
+ src/core/lib/debug/trace.cc
src/core/lib/promise/activity.cc
test/core/promise/activity_test.cc
third_party/googletest/googletest/src/gtest-all.cc
@@ -7447,21 +7406,10 @@ target_include_directories(activity_test
target_link_libraries(activity_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
- absl::base
- absl::core_headers
absl::flat_hash_set
- absl::memory
- absl::random_random
- absl::status
absl::statusor
- absl::cord
- absl::str_format
- absl::strings
- absl::synchronization
- absl::time
- absl::optional
absl::variant
- upb
+ gpr
)
@@ -12503,52 +12451,7 @@ endif()
if(gRPC_BUILD_TESTS)
add_executable(latch_test
- src/core/ext/upb-generated/google/protobuf/any.upb.c
- src/core/ext/upb-generated/google/rpc/status.upb.c
- src/core/lib/gpr/alloc.cc
- src/core/lib/gpr/atm.cc
- src/core/lib/gpr/cpu_iphone.cc
- src/core/lib/gpr/cpu_linux.cc
- src/core/lib/gpr/cpu_posix.cc
- src/core/lib/gpr/cpu_windows.cc
- src/core/lib/gpr/env_linux.cc
- src/core/lib/gpr/env_posix.cc
- src/core/lib/gpr/env_windows.cc
- src/core/lib/gpr/log.cc
- src/core/lib/gpr/log_android.cc
- src/core/lib/gpr/log_linux.cc
- src/core/lib/gpr/log_posix.cc
- src/core/lib/gpr/log_windows.cc
- src/core/lib/gpr/murmur_hash.cc
- src/core/lib/gpr/string.cc
- src/core/lib/gpr/string_posix.cc
- src/core/lib/gpr/string_util_windows.cc
- src/core/lib/gpr/string_windows.cc
- src/core/lib/gpr/sync.cc
- src/core/lib/gpr/sync_abseil.cc
- src/core/lib/gpr/sync_posix.cc
- src/core/lib/gpr/sync_windows.cc
- src/core/lib/gpr/time.cc
- src/core/lib/gpr/time_posix.cc
- src/core/lib/gpr/time_precise.cc
- src/core/lib/gpr/time_windows.cc
- src/core/lib/gpr/tmpfile_msys.cc
- src/core/lib/gpr/tmpfile_posix.cc
- src/core/lib/gpr/tmpfile_windows.cc
- src/core/lib/gpr/wrap_memcpy.cc
- src/core/lib/gprpp/examine_stack.cc
- src/core/lib/gprpp/fork.cc
- src/core/lib/gprpp/global_config_env.cc
- src/core/lib/gprpp/host_port.cc
- src/core/lib/gprpp/mpscq.cc
- src/core/lib/gprpp/stat_posix.cc
- src/core/lib/gprpp/stat_windows.cc
- src/core/lib/gprpp/status_helper.cc
- src/core/lib/gprpp/thd_posix.cc
- src/core/lib/gprpp/thd_windows.cc
- src/core/lib/gprpp/time_util.cc
- src/core/lib/profiling/basic_timers.cc
- src/core/lib/profiling/stap_timers.cc
+ src/core/lib/debug/trace.cc
src/core/lib/promise/activity.cc
test/core/promise/latch_test.cc
third_party/googletest/googletest/src/gtest-all.cc
@@ -12577,20 +12480,9 @@ target_include_directories(latch_test
target_link_libraries(latch_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
- absl::base
- absl::core_headers
- absl::memory
- absl::random_random
- absl::status
absl::statusor
- absl::cord
- absl::str_format
- absl::strings
- absl::synchronization
- absl::time
- absl::optional
absl::variant
- upb
+ gpr
)
@@ -13166,52 +13058,7 @@ endif()
if(gRPC_BUILD_TESTS)
add_executable(observable_test
- src/core/ext/upb-generated/google/protobuf/any.upb.c
- src/core/ext/upb-generated/google/rpc/status.upb.c
- src/core/lib/gpr/alloc.cc
- src/core/lib/gpr/atm.cc
- src/core/lib/gpr/cpu_iphone.cc
- src/core/lib/gpr/cpu_linux.cc
- src/core/lib/gpr/cpu_posix.cc
- src/core/lib/gpr/cpu_windows.cc
- src/core/lib/gpr/env_linux.cc
- src/core/lib/gpr/env_posix.cc
- src/core/lib/gpr/env_windows.cc
- src/core/lib/gpr/log.cc
- src/core/lib/gpr/log_android.cc
- src/core/lib/gpr/log_linux.cc
- src/core/lib/gpr/log_posix.cc
- src/core/lib/gpr/log_windows.cc
- src/core/lib/gpr/murmur_hash.cc
- src/core/lib/gpr/string.cc
- src/core/lib/gpr/string_posix.cc
- src/core/lib/gpr/string_util_windows.cc
- src/core/lib/gpr/string_windows.cc
- src/core/lib/gpr/sync.cc
- src/core/lib/gpr/sync_abseil.cc
- src/core/lib/gpr/sync_posix.cc
- src/core/lib/gpr/sync_windows.cc
- src/core/lib/gpr/time.cc
- src/core/lib/gpr/time_posix.cc
- src/core/lib/gpr/time_precise.cc
- src/core/lib/gpr/time_windows.cc
- src/core/lib/gpr/tmpfile_msys.cc
- src/core/lib/gpr/tmpfile_posix.cc
- src/core/lib/gpr/tmpfile_windows.cc
- src/core/lib/gpr/wrap_memcpy.cc
- src/core/lib/gprpp/examine_stack.cc
- src/core/lib/gprpp/fork.cc
- src/core/lib/gprpp/global_config_env.cc
- src/core/lib/gprpp/host_port.cc
- src/core/lib/gprpp/mpscq.cc
- src/core/lib/gprpp/stat_posix.cc
- src/core/lib/gprpp/stat_windows.cc
- src/core/lib/gprpp/status_helper.cc
- src/core/lib/gprpp/thd_posix.cc
- src/core/lib/gprpp/thd_windows.cc
- src/core/lib/gprpp/time_util.cc
- src/core/lib/profiling/basic_timers.cc
- src/core/lib/profiling/stap_timers.cc
+ src/core/lib/debug/trace.cc
src/core/lib/promise/activity.cc
test/core/promise/observable_test.cc
third_party/googletest/googletest/src/gtest-all.cc
@@ -13240,21 +13087,10 @@ target_include_directories(observable_test
target_link_libraries(observable_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
- absl::base
- absl::core_headers
absl::flat_hash_set
- absl::memory
- absl::random_random
- absl::status
absl::statusor
- absl::cord
- absl::str_format
- absl::strings
- absl::synchronization
- absl::time
- absl::optional
absl::variant
- upb
+ gpr
)
@@ -13603,6 +13439,7 @@ target_link_libraries(promise_factory_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::bind_front
+ absl::status
absl::optional
absl::variant
absl::utility
@@ -13640,6 +13477,7 @@ target_include_directories(promise_map_test
target_link_libraries(promise_map_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
+ absl::status
absl::optional
absl::variant
)
@@ -13676,6 +13514,7 @@ target_include_directories(promise_test
target_link_libraries(promise_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
+ absl::status
absl::optional
absl::variant
)
diff --git a/Makefile b/Makefile
index 4e29ddfdcfd..84d404dc139 100644
--- a/Makefile
+++ b/Makefile
@@ -1429,6 +1429,7 @@ LIBGRPC_SRC = \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
src/core/lib/channel/handshaker_registry.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 \
@@ -1565,6 +1566,7 @@ LIBGRPC_SRC = \
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 \
@@ -1920,6 +1922,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
src/core/lib/channel/handshaker_registry.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 \
@@ -2043,6 +2046,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/security/authorization/evaluate_args.cc \
src/core/lib/security/authorization/grpc_server_authz_filter.cc \
src/core/lib/security/context/security_context.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 \
diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml
index e95d8105bb1..739c88bf393 100644
--- a/build_autogenerated.yaml
+++ b/build_autogenerated.yaml
@@ -970,6 +970,7 @@ libs:
- src/core/lib/security/credentials/alts/alts_credentials.h
- src/core/lib/security/credentials/alts/check_gcp_environment.h
- src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h
+ - src/core/lib/security/credentials/call_creds_util.h
- src/core/lib/security/credentials/channel_creds_registry.h
- src/core/lib/security/credentials/composite/composite_credentials.h
- src/core/lib/security/credentials/credentials.h
@@ -1487,6 +1488,7 @@ libs:
- src/core/lib/channel/connected_channel.cc
- src/core/lib/channel/handshaker.cc
- src/core/lib/channel/handshaker_registry.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
@@ -1623,6 +1625,7 @@ libs:
- 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
@@ -2129,6 +2132,7 @@ libs:
- src/core/lib/security/authorization/evaluate_args.h
- src/core/lib/security/authorization/grpc_server_authz_filter.h
- src/core/lib/security/context/security_context.h
+ - src/core/lib/security/credentials/call_creds_util.h
- src/core/lib/security/credentials/channel_creds_registry.h
- src/core/lib/security/credentials/composite/composite_credentials.h
- src/core/lib/security/credentials/credentials.h
@@ -2308,6 +2312,7 @@ libs:
- src/core/lib/channel/connected_channel.cc
- src/core/lib/channel/handshaker.cc
- src/core/lib/channel/handshaker_registry.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
@@ -2431,6 +2436,7 @@ libs:
- src/core/lib/security/authorization/evaluate_args.cc
- src/core/lib/security/authorization/grpc_server_authz_filter.cc
- src/core/lib/security/context/security_context.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
@@ -4411,38 +4417,12 @@ targets:
build: test
language: c++
headers:
- - src/core/ext/upb-generated/google/protobuf/any.upb.h
- - src/core/ext/upb-generated/google/rpc/status.upb.h
- - src/core/lib/gpr/alloc.h
- - src/core/lib/gpr/env.h
- - src/core/lib/gpr/murmur_hash.h
- - src/core/lib/gpr/spinlock.h
- - src/core/lib/gpr/string.h
- - src/core/lib/gpr/string_windows.h
- - src/core/lib/gpr/time_precise.h
- - src/core/lib/gpr/tls.h
- - src/core/lib/gpr/tmpfile.h
- - src/core/lib/gpr/useful.h
+ - src/core/lib/debug/trace.h
- src/core/lib/gprpp/atomic_utils.h
- src/core/lib/gprpp/bitset.h
- - src/core/lib/gprpp/construct_destruct.h
- - src/core/lib/gprpp/debug_location.h
- - src/core/lib/gprpp/examine_stack.h
- - src/core/lib/gprpp/fork.h
- - src/core/lib/gprpp/global_config.h
- - src/core/lib/gprpp/global_config_custom.h
- - src/core/lib/gprpp/global_config_env.h
- - src/core/lib/gprpp/global_config_generic.h
- - src/core/lib/gprpp/host_port.h
- - src/core/lib/gprpp/manual_constructor.h
- - src/core/lib/gprpp/memory.h
- - src/core/lib/gprpp/mpscq.h
- - src/core/lib/gprpp/stat.h
- - src/core/lib/gprpp/status_helper.h
- - src/core/lib/gprpp/sync.h
- - src/core/lib/gprpp/thd.h
- - src/core/lib/gprpp/time_util.h
- - src/core/lib/profiling/timers.h
+ - src/core/lib/gprpp/orphanable.h
+ - src/core/lib/gprpp/ref_counted.h
+ - src/core/lib/gprpp/ref_counted_ptr.h
- src/core/lib/promise/activity.h
- src/core/lib/promise/context.h
- src/core/lib/promise/detail/basic_join.h
@@ -4458,70 +4438,14 @@ targets:
- src/core/lib/promise/wait_set.h
- test/core/promise/test_wakeup_schedulers.h
src:
- - src/core/ext/upb-generated/google/protobuf/any.upb.c
- - src/core/ext/upb-generated/google/rpc/status.upb.c
- - src/core/lib/gpr/alloc.cc
- - src/core/lib/gpr/atm.cc
- - src/core/lib/gpr/cpu_iphone.cc
- - src/core/lib/gpr/cpu_linux.cc
- - src/core/lib/gpr/cpu_posix.cc
- - src/core/lib/gpr/cpu_windows.cc
- - src/core/lib/gpr/env_linux.cc
- - src/core/lib/gpr/env_posix.cc
- - src/core/lib/gpr/env_windows.cc
- - src/core/lib/gpr/log.cc
- - src/core/lib/gpr/log_android.cc
- - src/core/lib/gpr/log_linux.cc
- - src/core/lib/gpr/log_posix.cc
- - src/core/lib/gpr/log_windows.cc
- - src/core/lib/gpr/murmur_hash.cc
- - src/core/lib/gpr/string.cc
- - src/core/lib/gpr/string_posix.cc
- - src/core/lib/gpr/string_util_windows.cc
- - src/core/lib/gpr/string_windows.cc
- - src/core/lib/gpr/sync.cc
- - src/core/lib/gpr/sync_abseil.cc
- - src/core/lib/gpr/sync_posix.cc
- - src/core/lib/gpr/sync_windows.cc
- - src/core/lib/gpr/time.cc
- - src/core/lib/gpr/time_posix.cc
- - src/core/lib/gpr/time_precise.cc
- - src/core/lib/gpr/time_windows.cc
- - src/core/lib/gpr/tmpfile_msys.cc
- - src/core/lib/gpr/tmpfile_posix.cc
- - src/core/lib/gpr/tmpfile_windows.cc
- - src/core/lib/gpr/wrap_memcpy.cc
- - src/core/lib/gprpp/examine_stack.cc
- - src/core/lib/gprpp/fork.cc
- - src/core/lib/gprpp/global_config_env.cc
- - src/core/lib/gprpp/host_port.cc
- - src/core/lib/gprpp/mpscq.cc
- - src/core/lib/gprpp/stat_posix.cc
- - src/core/lib/gprpp/stat_windows.cc
- - src/core/lib/gprpp/status_helper.cc
- - src/core/lib/gprpp/thd_posix.cc
- - src/core/lib/gprpp/thd_windows.cc
- - src/core/lib/gprpp/time_util.cc
- - src/core/lib/profiling/basic_timers.cc
- - src/core/lib/profiling/stap_timers.cc
+ - src/core/lib/debug/trace.cc
- src/core/lib/promise/activity.cc
- test/core/promise/activity_test.cc
deps:
- - absl/base:base
- - absl/base:core_headers
- absl/container:flat_hash_set
- - absl/memory:memory
- - absl/random:random
- - absl/status:status
- absl/status:statusor
- - absl/strings:cord
- - absl/strings:str_format
- - absl/strings:strings
- - absl/synchronization:synchronization
- - absl/time:time
- - absl/types:optional
- absl/types:variant
- - upb
+ - gpr
uses_polling: false
- name: address_sorting_test
gtest: true
@@ -5690,6 +5614,7 @@ targets:
headers:
- src/core/lib/debug/trace.h
- src/core/lib/gprpp/atomic_utils.h
+ - src/core/lib/gprpp/orphanable.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
- src/core/lib/gprpp/time.h
@@ -6516,38 +6441,12 @@ targets:
build: test
language: c++
headers:
- - src/core/ext/upb-generated/google/protobuf/any.upb.h
- - src/core/ext/upb-generated/google/rpc/status.upb.h
- - src/core/lib/gpr/alloc.h
- - src/core/lib/gpr/env.h
- - src/core/lib/gpr/murmur_hash.h
- - src/core/lib/gpr/spinlock.h
- - src/core/lib/gpr/string.h
- - src/core/lib/gpr/string_windows.h
- - src/core/lib/gpr/time_precise.h
- - src/core/lib/gpr/tls.h
- - src/core/lib/gpr/tmpfile.h
- - src/core/lib/gpr/useful.h
+ - src/core/lib/debug/trace.h
- src/core/lib/gprpp/atomic_utils.h
- src/core/lib/gprpp/bitset.h
- - src/core/lib/gprpp/construct_destruct.h
- - src/core/lib/gprpp/debug_location.h
- - src/core/lib/gprpp/examine_stack.h
- - src/core/lib/gprpp/fork.h
- - src/core/lib/gprpp/global_config.h
- - src/core/lib/gprpp/global_config_custom.h
- - src/core/lib/gprpp/global_config_env.h
- - src/core/lib/gprpp/global_config_generic.h
- - src/core/lib/gprpp/host_port.h
- - src/core/lib/gprpp/manual_constructor.h
- - src/core/lib/gprpp/memory.h
- - src/core/lib/gprpp/mpscq.h
- - src/core/lib/gprpp/stat.h
- - src/core/lib/gprpp/status_helper.h
- - src/core/lib/gprpp/sync.h
- - src/core/lib/gprpp/thd.h
- - src/core/lib/gprpp/time_util.h
- - src/core/lib/profiling/timers.h
+ - src/core/lib/gprpp/orphanable.h
+ - src/core/lib/gprpp/ref_counted.h
+ - src/core/lib/gprpp/ref_counted_ptr.h
- src/core/lib/promise/activity.h
- src/core/lib/promise/context.h
- src/core/lib/promise/detail/basic_join.h
@@ -6563,69 +6462,13 @@ targets:
- src/core/lib/promise/seq.h
- test/core/promise/test_wakeup_schedulers.h
src:
- - src/core/ext/upb-generated/google/protobuf/any.upb.c
- - src/core/ext/upb-generated/google/rpc/status.upb.c
- - src/core/lib/gpr/alloc.cc
- - src/core/lib/gpr/atm.cc
- - src/core/lib/gpr/cpu_iphone.cc
- - src/core/lib/gpr/cpu_linux.cc
- - src/core/lib/gpr/cpu_posix.cc
- - src/core/lib/gpr/cpu_windows.cc
- - src/core/lib/gpr/env_linux.cc
- - src/core/lib/gpr/env_posix.cc
- - src/core/lib/gpr/env_windows.cc
- - src/core/lib/gpr/log.cc
- - src/core/lib/gpr/log_android.cc
- - src/core/lib/gpr/log_linux.cc
- - src/core/lib/gpr/log_posix.cc
- - src/core/lib/gpr/log_windows.cc
- - src/core/lib/gpr/murmur_hash.cc
- - src/core/lib/gpr/string.cc
- - src/core/lib/gpr/string_posix.cc
- - src/core/lib/gpr/string_util_windows.cc
- - src/core/lib/gpr/string_windows.cc
- - src/core/lib/gpr/sync.cc
- - src/core/lib/gpr/sync_abseil.cc
- - src/core/lib/gpr/sync_posix.cc
- - src/core/lib/gpr/sync_windows.cc
- - src/core/lib/gpr/time.cc
- - src/core/lib/gpr/time_posix.cc
- - src/core/lib/gpr/time_precise.cc
- - src/core/lib/gpr/time_windows.cc
- - src/core/lib/gpr/tmpfile_msys.cc
- - src/core/lib/gpr/tmpfile_posix.cc
- - src/core/lib/gpr/tmpfile_windows.cc
- - src/core/lib/gpr/wrap_memcpy.cc
- - src/core/lib/gprpp/examine_stack.cc
- - src/core/lib/gprpp/fork.cc
- - src/core/lib/gprpp/global_config_env.cc
- - src/core/lib/gprpp/host_port.cc
- - src/core/lib/gprpp/mpscq.cc
- - src/core/lib/gprpp/stat_posix.cc
- - src/core/lib/gprpp/stat_windows.cc
- - src/core/lib/gprpp/status_helper.cc
- - src/core/lib/gprpp/thd_posix.cc
- - src/core/lib/gprpp/thd_windows.cc
- - src/core/lib/gprpp/time_util.cc
- - src/core/lib/profiling/basic_timers.cc
- - src/core/lib/profiling/stap_timers.cc
+ - src/core/lib/debug/trace.cc
- src/core/lib/promise/activity.cc
- test/core/promise/latch_test.cc
deps:
- - absl/base:base
- - absl/base:core_headers
- - absl/memory:memory
- - absl/random:random
- - absl/status:status
- absl/status:statusor
- - absl/strings:cord
- - absl/strings:str_format
- - absl/strings:strings
- - absl/synchronization:synchronization
- - absl/time:time
- - absl/types:optional
- absl/types:variant
- - upb
+ - gpr
uses_polling: false
- name: lb_get_cpu_stats_test
gtest: true
@@ -6851,37 +6694,11 @@ targets:
build: test
language: c++
headers:
- - src/core/ext/upb-generated/google/protobuf/any.upb.h
- - src/core/ext/upb-generated/google/rpc/status.upb.h
- - src/core/lib/gpr/alloc.h
- - src/core/lib/gpr/env.h
- - src/core/lib/gpr/murmur_hash.h
- - src/core/lib/gpr/spinlock.h
- - src/core/lib/gpr/string.h
- - src/core/lib/gpr/string_windows.h
- - src/core/lib/gpr/time_precise.h
- - src/core/lib/gpr/tls.h
- - src/core/lib/gpr/tmpfile.h
- - src/core/lib/gpr/useful.h
+ - src/core/lib/debug/trace.h
- src/core/lib/gprpp/atomic_utils.h
- - src/core/lib/gprpp/construct_destruct.h
- - src/core/lib/gprpp/debug_location.h
- - src/core/lib/gprpp/examine_stack.h
- - src/core/lib/gprpp/fork.h
- - src/core/lib/gprpp/global_config.h
- - src/core/lib/gprpp/global_config_custom.h
- - src/core/lib/gprpp/global_config_env.h
- - src/core/lib/gprpp/global_config_generic.h
- - src/core/lib/gprpp/host_port.h
- - src/core/lib/gprpp/manual_constructor.h
- - src/core/lib/gprpp/memory.h
- - src/core/lib/gprpp/mpscq.h
- - src/core/lib/gprpp/stat.h
- - src/core/lib/gprpp/status_helper.h
- - src/core/lib/gprpp/sync.h
- - src/core/lib/gprpp/thd.h
- - src/core/lib/gprpp/time_util.h
- - src/core/lib/profiling/timers.h
+ - src/core/lib/gprpp/orphanable.h
+ - src/core/lib/gprpp/ref_counted.h
+ - src/core/lib/gprpp/ref_counted_ptr.h
- src/core/lib/promise/activity.h
- src/core/lib/promise/context.h
- src/core/lib/promise/detail/basic_seq.h
@@ -6896,70 +6713,14 @@ targets:
- src/core/lib/promise/wait_set.h
- test/core/promise/test_wakeup_schedulers.h
src:
- - src/core/ext/upb-generated/google/protobuf/any.upb.c
- - src/core/ext/upb-generated/google/rpc/status.upb.c
- - src/core/lib/gpr/alloc.cc
- - src/core/lib/gpr/atm.cc
- - src/core/lib/gpr/cpu_iphone.cc
- - src/core/lib/gpr/cpu_linux.cc
- - src/core/lib/gpr/cpu_posix.cc
- - src/core/lib/gpr/cpu_windows.cc
- - src/core/lib/gpr/env_linux.cc
- - src/core/lib/gpr/env_posix.cc
- - src/core/lib/gpr/env_windows.cc
- - src/core/lib/gpr/log.cc
- - src/core/lib/gpr/log_android.cc
- - src/core/lib/gpr/log_linux.cc
- - src/core/lib/gpr/log_posix.cc
- - src/core/lib/gpr/log_windows.cc
- - src/core/lib/gpr/murmur_hash.cc
- - src/core/lib/gpr/string.cc
- - src/core/lib/gpr/string_posix.cc
- - src/core/lib/gpr/string_util_windows.cc
- - src/core/lib/gpr/string_windows.cc
- - src/core/lib/gpr/sync.cc
- - src/core/lib/gpr/sync_abseil.cc
- - src/core/lib/gpr/sync_posix.cc
- - src/core/lib/gpr/sync_windows.cc
- - src/core/lib/gpr/time.cc
- - src/core/lib/gpr/time_posix.cc
- - src/core/lib/gpr/time_precise.cc
- - src/core/lib/gpr/time_windows.cc
- - src/core/lib/gpr/tmpfile_msys.cc
- - src/core/lib/gpr/tmpfile_posix.cc
- - src/core/lib/gpr/tmpfile_windows.cc
- - src/core/lib/gpr/wrap_memcpy.cc
- - src/core/lib/gprpp/examine_stack.cc
- - src/core/lib/gprpp/fork.cc
- - src/core/lib/gprpp/global_config_env.cc
- - src/core/lib/gprpp/host_port.cc
- - src/core/lib/gprpp/mpscq.cc
- - src/core/lib/gprpp/stat_posix.cc
- - src/core/lib/gprpp/stat_windows.cc
- - src/core/lib/gprpp/status_helper.cc
- - src/core/lib/gprpp/thd_posix.cc
- - src/core/lib/gprpp/thd_windows.cc
- - src/core/lib/gprpp/time_util.cc
- - src/core/lib/profiling/basic_timers.cc
- - src/core/lib/profiling/stap_timers.cc
+ - src/core/lib/debug/trace.cc
- src/core/lib/promise/activity.cc
- test/core/promise/observable_test.cc
deps:
- - absl/base:base
- - absl/base:core_headers
- absl/container:flat_hash_set
- - absl/memory:memory
- - absl/random:random
- - absl/status:status
- absl/status:statusor
- - absl/strings:cord
- - absl/strings:str_format
- - absl/strings:strings
- - absl/synchronization:synchronization
- - absl/time:time
- - absl/types:optional
- absl/types:variant
- - upb
+ - gpr
uses_polling: false
- name: orphanable_test
gtest: true
@@ -7124,6 +6885,7 @@ targets:
- test/core/promise/promise_factory_test.cc
deps:
- absl/functional:bind_front
+ - absl/status:status
- absl/types:optional
- absl/types:variant
- absl/utility:utility
@@ -7140,6 +6902,7 @@ targets:
src:
- test/core/promise/map_test.cc
deps:
+ - absl/status:status
- absl/types:optional
- absl/types:variant
uses_polling: false
@@ -7154,6 +6917,7 @@ targets:
src:
- test/core/promise/promise_test.cc
deps:
+ - absl/status:status
- absl/types:optional
- absl/types:variant
uses_polling: false
diff --git a/config.m4 b/config.m4
index b744d3e35d7..4553bec115e 100644
--- a/config.m4
+++ b/config.m4
@@ -447,6 +447,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
src/core/lib/channel/handshaker_registry.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 \
@@ -627,6 +628,7 @@ if test "$PHP_GRPC" != "no"; then
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 \
diff --git a/config.w32 b/config.w32
index 7c1cf958c8f..a6e3d6bce98 100644
--- a/config.w32
+++ b/config.w32
@@ -413,6 +413,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\channel\\connected_channel.cc " +
"src\\core\\lib\\channel\\handshaker.cc " +
"src\\core\\lib\\channel\\handshaker_registry.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 " +
@@ -593,6 +594,7 @@ if (PHP_GRPC != "no") {
"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 " +
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index daa38fd9b43..35fd3f8286e 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -816,6 +816,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/alts/alts_credentials.h',
'src/core/lib/security/credentials/alts/check_gcp_environment.h',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
+ 'src/core/lib/security/credentials/call_creds_util.h',
'src/core/lib/security/credentials/channel_creds_registry.h',
'src/core/lib/security/credentials/composite/composite_credentials.h',
'src/core/lib/security/credentials/credentials.h',
@@ -1614,6 +1615,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/alts/alts_credentials.h',
'src/core/lib/security/credentials/alts/check_gcp_environment.h',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
+ 'src/core/lib/security/credentials/call_creds_util.h',
'src/core/lib/security/credentials/channel_creds_registry.h',
'src/core/lib/security/credentials/composite/composite_credentials.h',
'src/core/lib/security/credentials/credentials.h',
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 7ca112584b7..93b39a97698 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -993,6 +993,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/handshaker_factory.h',
'src/core/lib/channel/handshaker_registry.cc',
'src/core/lib/channel/handshaker_registry.h',
+ 'src/core/lib/channel/promise_based_filter.cc',
'src/core/lib/channel/promise_based_filter.h',
'src/core/lib/channel/status_util.cc',
'src/core/lib/channel/status_util.h',
@@ -1342,6 +1343,8 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
'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/call_creds_util.h',
'src/core/lib/security/credentials/channel_creds_registry.h',
'src/core/lib/security/credentials/channel_creds_registry_init.cc',
'src/core/lib/security/credentials/composite/composite_credentials.cc',
@@ -2209,6 +2212,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/alts/alts_credentials.h',
'src/core/lib/security/credentials/alts/check_gcp_environment.h',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
+ 'src/core/lib/security/credentials/call_creds_util.h',
'src/core/lib/security/credentials/channel_creds_registry.h',
'src/core/lib/security/credentials/composite/composite_credentials.h',
'src/core/lib/security/credentials/credentials.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index 1f9de679e9a..1a84d9eb853 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -912,6 +912,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/handshaker_factory.h )
s.files += %w( src/core/lib/channel/handshaker_registry.cc )
s.files += %w( src/core/lib/channel/handshaker_registry.h )
+ s.files += %w( src/core/lib/channel/promise_based_filter.cc )
s.files += %w( src/core/lib/channel/promise_based_filter.h )
s.files += %w( src/core/lib/channel/status_util.cc )
s.files += %w( src/core/lib/channel/status_util.h )
@@ -1261,6 +1262,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc )
s.files += %w( src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h )
s.files += %w( src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc )
+ s.files += %w( src/core/lib/security/credentials/call_creds_util.cc )
+ s.files += %w( src/core/lib/security/credentials/call_creds_util.h )
s.files += %w( src/core/lib/security/credentials/channel_creds_registry.h )
s.files += %w( src/core/lib/security/credentials/channel_creds_registry_init.cc )
s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.cc )
diff --git a/grpc.gyp b/grpc.gyp
index be77bb59c99..2c89374f8aa 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -891,6 +891,7 @@
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
'src/core/lib/channel/handshaker_registry.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',
@@ -1027,6 +1028,7 @@
'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',
@@ -1353,6 +1355,7 @@
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
'src/core/lib/channel/handshaker_registry.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',
@@ -1476,6 +1479,7 @@
'src/core/lib/security/authorization/evaluate_args.cc',
'src/core/lib/security/authorization/grpc_server_authz_filter.cc',
'src/core/lib/security/context/security_context.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',
diff --git a/package.xml b/package.xml
index 10e3e312618..013b15ebffa 100644
--- a/package.xml
+++ b/package.xml
@@ -892,6 +892,7 @@
+
@@ -1241,6 +1242,8 @@
+
+
diff --git a/src/core/lib/channel/context.h b/src/core/lib/channel/context.h
index 0c0556abcdc..ad1021b822b 100644
--- a/src/core/lib/channel/context.h
+++ b/src/core/lib/channel/context.h
@@ -19,6 +19,10 @@
#ifndef GRPC_CORE_LIB_CHANNEL_CONTEXT_H
#define GRPC_CORE_LIB_CHANNEL_CONTEXT_H
+#include
+
+#include "src/core/lib/promise/context.h"
+
/// Call object context pointers.
/// Call context is represented as an array of \a grpc_call_context_elements.
@@ -49,4 +53,11 @@ struct grpc_call_context_element {
void (*destroy)(void*) = nullptr;
};
+namespace grpc_core {
+// Bind the legacy context array into the new style structure
+// TODO(ctiller): remove as we migrate these contexts to the new system.
+template <>
+struct ContextType {};
+} // namespace grpc_core
+
#endif /* GRPC_CORE_LIB_CHANNEL_CONTEXT_H */
diff --git a/src/core/lib/channel/promise_based_filter.cc b/src/core/lib/channel/promise_based_filter.cc
new file mode 100644
index 00000000000..6ba9ef1de3d
--- /dev/null
+++ b/src/core/lib/channel/promise_based_filter.cc
@@ -0,0 +1,50 @@
+// 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 "src/core/lib/channel/promise_based_filter.h"
+
+#include "src/core/lib/channel/channel_stack.h"
+
+namespace grpc_core {
+namespace promise_filter_detail {
+
+// We don't form ActivityPtr's to this type, and consequently don't need
+// Orphan().
+void BaseCallData::Orphan() { abort(); }
+
+// For now we don't care about owning/non-owning wakers, instead just share
+// implementation.
+Waker BaseCallData::MakeNonOwningWaker() { return MakeOwningWaker(); }
+
+Waker BaseCallData::MakeOwningWaker() {
+ GRPC_CALL_STACK_REF(call_stack_, "waker");
+ return Waker(this);
+}
+
+void BaseCallData::Wakeup() {
+ auto wakeup = [](void* p, grpc_error_handle) {
+ auto* self = static_cast(p);
+ self->OnWakeup();
+ self->Drop();
+ };
+ auto* closure = GRPC_CLOSURE_CREATE(wakeup, this, nullptr);
+ GRPC_CALL_COMBINER_START(call_combiner_, closure, GRPC_ERROR_NONE, "wakeup");
+}
+
+void BaseCallData::Drop() { GRPC_CALL_STACK_UNREF(call_stack_, "waker"); }
+
+} // namespace promise_filter_detail
+} // namespace grpc_core
diff --git a/src/core/lib/channel/promise_based_filter.h b/src/core/lib/channel/promise_based_filter.h
index 001eac288eb..c89f76d81f6 100644
--- a/src/core/lib/channel/promise_based_filter.h
+++ b/src/core/lib/channel/promise_based_filter.h
@@ -27,6 +27,7 @@
#include
#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/channel/context.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/promise/arena_promise.h"
@@ -77,19 +78,34 @@ enum class FilterEndpoint {
namespace promise_filter_detail {
// Call data shared between all implementations of promise-based filters.
-class BaseCallData {
+class BaseCallData : public Activity, private Wakeable {
public:
BaseCallData(grpc_call_element* elem, const grpc_call_element_args* args)
- : elem_(elem),
+ : call_stack_(args->call_stack),
+ elem_(elem),
arena_(args->arena),
call_combiner_(args->call_combiner),
- deadline_(args->deadline) {}
+ deadline_(args->deadline),
+ context_(args->context) {}
+
+ void set_pollent(grpc_polling_entity* pollent) { pollent_ = pollent; }
+
+ // Activity implementation (partial).
+ void Orphan() final;
+ Waker MakeNonOwningWaker() final;
+ Waker MakeOwningWaker() final;
protected:
- class ScopedContext : public promise_detail::Context {
+ class ScopedContext
+ : public promise_detail::Context,
+ public promise_detail::Context,
+ public promise_detail::Context {
public:
explicit ScopedContext(BaseCallData* call_data)
- : promise_detail::Context(call_data->arena_) {}
+ : promise_detail::Context(call_data->arena_),
+ promise_detail::Context(
+ call_data->context_),
+ promise_detail::Context(call_data->pollent_) {}
};
static MetadataHandle WrapMetadata(
@@ -105,12 +121,22 @@ class BaseCallData {
grpc_call_element* elem() const { return elem_; }
CallCombiner* call_combiner() const { return call_combiner_; }
Timestamp deadline() const { return deadline_; }
+ grpc_call_stack* call_stack() const { return call_stack_; }
private:
+ // Wakeable implementation.
+ void Wakeup() final;
+ void Drop() final;
+
+ virtual void OnWakeup() = 0;
+
+ grpc_call_stack* const call_stack_;
grpc_call_element* const elem_;
Arena* const arena_;
CallCombiner* const call_combiner_;
const Timestamp deadline_;
+ grpc_call_context_element* const context_;
+ grpc_polling_entity* pollent_ = nullptr;
};
// Specific call data per channel filter.
@@ -130,11 +156,17 @@ class CallData : public BaseCallData {
grpc_schedule_on_exec_ctx);
}
- ~CallData() {
+ ~CallData() override {
GPR_ASSERT(!is_polling_);
GRPC_ERROR_UNREF(cancelled_error_);
}
+ // Activity implementation.
+ void ForceImmediateRepoll() final {
+ GPR_ASSERT(is_polling_);
+ repoll_ = true;
+ }
+
// Handle one grpc_transport_stream_op_batch
void StartBatch(grpc_transport_stream_op_batch* batch) {
// Fake out the activity based context.
@@ -235,9 +267,23 @@ class CallData : public BaseCallData {
if (recv_trailing_state_ == RecvTrailingState::kQueued) {
recv_trailing_state_ = RecvTrailingState::kCancelled;
}
- grpc_transport_stream_op_batch_finish_with_failure(
- absl::exchange(send_initial_metadata_batch_, nullptr),
- GRPC_ERROR_REF(cancelled_error_), call_combiner());
+ struct FailBatch : public grpc_closure {
+ grpc_transport_stream_op_batch* batch;
+ CallCombiner* call_combiner;
+ };
+ auto fail = [](void* p, grpc_error_handle error) {
+ auto* f = static_cast(p);
+ grpc_transport_stream_op_batch_finish_with_failure(
+ f->batch, GRPC_ERROR_REF(error), f->call_combiner);
+ delete f;
+ };
+ auto* b = new FailBatch();
+ GRPC_CLOSURE_INIT(b, fail, b, nullptr);
+ b->batch = absl::exchange(send_initial_metadata_batch_, nullptr);
+ b->call_combiner = call_combiner();
+ GRPC_CALL_COMBINER_START(call_combiner(), b,
+ GRPC_ERROR_REF(cancelled_error_),
+ "cancel pending batch");
} else {
send_initial_state_ = SendInitialState::kCancelled;
}
@@ -250,12 +296,15 @@ class CallData : public BaseCallData {
ChannelFilter* filter = static_cast(elem()->channel_data);
// Construct the promise.
- promise_ = filter->MakeCallPromise(
- WrapMetadata(send_initial_metadata_batch_->payload
- ->send_initial_metadata.send_initial_metadata),
- [this](ClientInitialMetadata initial_metadata) {
- return MakeNextPromise(std::move(initial_metadata));
- });
+ {
+ ScopedActivity activity(this);
+ promise_ = filter->MakeCallPromise(
+ WrapMetadata(send_initial_metadata_batch_->payload
+ ->send_initial_metadata.send_initial_metadata),
+ [this](ClientInitialMetadata initial_metadata) {
+ return MakeNextPromise(std::move(initial_metadata));
+ });
+ }
// Poll once.
WakeInsideCombiner();
}
@@ -366,24 +415,75 @@ class CallData : public BaseCallData {
GPR_ASSERT(!is_polling_);
grpc_closure* call_closure = nullptr;
is_polling_ = true;
+ grpc_error_handle cancel_send_initial_metadata_error = GRPC_ERROR_NONE;
+ grpc_transport_stream_op_batch* forward_batch = nullptr;
switch (send_initial_state_) {
case SendInitialState::kQueued:
case SendInitialState::kForwarded: {
// Poll the promise once since we're waiting for it.
- Poll poll = promise_();
+ Poll poll;
+ {
+ ScopedActivity activity(this);
+ poll = promise_();
+ }
if (auto* r = absl::get_if(&poll)) {
- GPR_ASSERT(recv_trailing_state_ == RecvTrailingState::kComplete);
- GPR_ASSERT(recv_trailing_metadata_ == UnwrapMetadata(std::move(*r)));
- recv_trailing_state_ = RecvTrailingState::kResponded;
- call_closure =
- absl::exchange(original_recv_trailing_metadata_ready_, nullptr);
+ promise_ = ArenaPromise();
+ auto* md = UnwrapMetadata(std::move(*r));
+ bool destroy_md = true;
+ switch (recv_trailing_state_) {
+ case RecvTrailingState::kComplete:
+ if (recv_trailing_metadata_ != md) {
+ *recv_trailing_metadata_ = std::move(*md);
+ } else {
+ destroy_md = false;
+ }
+ recv_trailing_state_ = RecvTrailingState::kResponded;
+ call_closure = absl::exchange(
+ original_recv_trailing_metadata_ready_, nullptr);
+ break;
+ case RecvTrailingState::kQueued:
+ case RecvTrailingState::kForwarded: {
+ GPR_ASSERT(*md->get_pointer(GrpcStatusMetadata()) !=
+ GRPC_STATUS_OK);
+ grpc_error_handle error = grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "early return from promise based filter"),
+ GRPC_ERROR_INT_GRPC_STATUS,
+ *md->get_pointer(GrpcStatusMetadata()));
+ if (auto* message = md->get_pointer(GrpcMessageMetadata())) {
+ error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
+ message->as_string_view());
+ }
+ if (recv_trailing_state_ == RecvTrailingState::kQueued) {
+ GPR_ASSERT(send_initial_state_ == SendInitialState::kQueued);
+ send_initial_state_ = SendInitialState::kCancelled;
+ cancel_send_initial_metadata_error = error;
+ } else {
+ call_combiner()->Cancel(GRPC_ERROR_REF(error));
+ forward_batch =
+ grpc_make_transport_stream_op(GRPC_CLOSURE_CREATE(
+ [](void*, grpc_error_handle) {}, nullptr, nullptr));
+ forward_batch->cancel_stream = true;
+ forward_batch->payload->cancel_stream.cancel_error = error;
+ }
+ recv_trailing_state_ = RecvTrailingState::kCancelled;
+ } break;
+ case RecvTrailingState::kInitial:
+ abort(); // unimplemented
+ case RecvTrailingState::kResponded:
+ case RecvTrailingState::kCancelled:
+ abort(); // unreachable
+ }
+ if (destroy_md) {
+ md->~grpc_metadata_batch();
+ }
}
} break;
case SendInitialState::kInitial:
case SendInitialState::kCancelled:
- // If we get a response without sending anything, we just propagate that
- // up. (note: that situation isn't possible once we finish the promise
- // transition).
+ // If we get a response without sending anything, we just propagate
+ // that up. (note: that situation isn't possible once we finish the
+ // promise transition).
if (recv_trailing_state_ == RecvTrailingState::kComplete) {
recv_trailing_state_ = RecvTrailingState::kResponded;
call_closure =
@@ -391,14 +491,64 @@ class CallData : public BaseCallData {
}
break;
}
+ GRPC_CALL_STACK_REF(call_stack(), "finish_poll");
is_polling_ = false;
+ bool in_combiner = true;
+ bool repoll = absl::exchange(repoll_, false);
+ if (forward_batch != nullptr) {
+ GPR_ASSERT(in_combiner);
+ in_combiner = false;
+ forward_send_initial_metadata_ = false;
+ grpc_call_next_op(elem(), forward_batch);
+ }
+ if (cancel_send_initial_metadata_error != GRPC_ERROR_NONE) {
+ GPR_ASSERT(in_combiner);
+ forward_send_initial_metadata_ = false;
+ in_combiner = false;
+ grpc_transport_stream_op_batch_finish_with_failure(
+ absl::exchange(send_initial_metadata_batch_, nullptr),
+ cancel_send_initial_metadata_error, call_combiner());
+ }
if (absl::exchange(forward_send_initial_metadata_, false)) {
+ GPR_ASSERT(in_combiner);
+ in_combiner = false;
grpc_call_next_op(elem(),
absl::exchange(send_initial_metadata_batch_, nullptr));
}
if (call_closure != nullptr) {
+ GPR_ASSERT(in_combiner);
+ in_combiner = false;
Closure::Run(DEBUG_LOCATION, call_closure, GRPC_ERROR_NONE);
}
+ if (repoll) {
+ if (in_combiner) {
+ WakeInsideCombiner();
+ } else {
+ struct NextPoll : public grpc_closure {
+ grpc_call_stack* call_stack;
+ CallData* call_data;
+ };
+ auto run = [](void* p, grpc_error_handle) {
+ auto* next_poll = static_cast(p);
+ next_poll->call_data->WakeInsideCombiner();
+ GRPC_CALL_STACK_UNREF(next_poll->call_stack, "re-poll");
+ delete next_poll;
+ };
+ auto* p = new NextPoll;
+ GRPC_CALL_STACK_REF(call_stack(), "re-poll");
+ GRPC_CLOSURE_INIT(p, run, p, nullptr);
+ GRPC_CALL_COMBINER_START(call_combiner(), p, GRPC_ERROR_NONE,
+ "re-poll");
+ }
+ } else if (in_combiner) {
+ GRPC_CALL_COMBINER_STOP(call_combiner(), "poll paused");
+ }
+ GRPC_CALL_STACK_UNREF(call_stack(), "finish_poll");
+ }
+
+ void OnWakeup() override {
+ ScopedContext context(this);
+ WakeInsideCombiner();
}
// Contained promise
@@ -419,6 +569,8 @@ class CallData : public BaseCallData {
RecvTrailingState recv_trailing_state_ = RecvTrailingState::kInitial;
// Whether we're currently polling the promise.
bool is_polling_ = false;
+ // Should we repoll after completing polling?
+ bool repoll_ = false;
// Whether we should forward send initial metadata after polling?
bool forward_send_initial_metadata_ = false;
};
@@ -434,18 +586,21 @@ class CallData : public BaseCallData {
grpc_schedule_on_exec_ctx);
}
- ~CallData() {
+ ~CallData() override {
GPR_ASSERT(!is_polling_);
GRPC_ERROR_UNREF(cancelled_error_);
}
+ // Activity implementation.
+ void ForceImmediateRepoll() final { abort(); } // Not implemented.
+
// Handle one grpc_transport_stream_op_batch
void StartBatch(grpc_transport_stream_op_batch* batch) {
// Fake out the activity based context.
ScopedContext context(this);
- // If this is a cancel stream, cancel anything we have pending and propagate
- // the cancellation.
+ // If this is a cancel stream, cancel anything we have pending and
+ // propagate the cancellation.
if (batch->cancel_stream) {
GPR_ASSERT(!batch->send_initial_metadata &&
!batch->send_trailing_metadata && !batch->send_message &&
@@ -535,9 +690,23 @@ class CallData : public BaseCallData {
promise_ = ArenaPromise();
if (send_trailing_state_ == SendTrailingState::kQueued) {
send_trailing_state_ = SendTrailingState::kCancelled;
- grpc_transport_stream_op_batch_finish_with_failure(
- absl::exchange(send_trailing_metadata_batch_, nullptr),
- GRPC_ERROR_REF(cancelled_error_), call_combiner());
+ struct FailBatch : public grpc_closure {
+ grpc_transport_stream_op_batch* batch;
+ CallCombiner* call_combiner;
+ };
+ auto fail = [](void* p, grpc_error_handle error) {
+ auto* f = static_cast(p);
+ grpc_transport_stream_op_batch_finish_with_failure(
+ f->batch, GRPC_ERROR_REF(error), f->call_combiner);
+ delete f;
+ };
+ auto* b = new FailBatch();
+ GRPC_CLOSURE_INIT(b, fail, b, nullptr);
+ b->batch = absl::exchange(send_trailing_metadata_batch_, nullptr);
+ b->call_combiner = call_combiner();
+ GRPC_CALL_COMBINER_START(call_combiner(), b,
+ GRPC_ERROR_REF(cancelled_error_),
+ "cancel pending batch");
} else {
send_trailing_state_ = SendTrailingState::kCancelled;
}
@@ -623,7 +792,11 @@ class CallData : public BaseCallData {
bool forward_send_trailing_metadata = false;
is_polling_ = true;
if (recv_initial_state_ == RecvInitialState::kComplete) {
- Poll poll = promise_();
+ Poll poll;
+ {
+ ScopedActivity activity(this);
+ poll = promise_();
+ }
if (auto* r = absl::get_if(&poll)) {
auto* md = UnwrapMetadata(std::move(*r));
bool destroy_md = true;
@@ -672,6 +845,8 @@ class CallData : public BaseCallData {
}
}
+ void OnWakeup() override { abort(); } // not implemented
+
// Contained promise
ArenaPromise promise_;
// Pointer to where initial metadata will be stored.
@@ -736,7 +911,9 @@ MakePromiseBasedFilter(const char* name) {
return GRPC_ERROR_NONE;
},
// set_pollset_or_pollset_set
- grpc_call_stack_ignore_set_pollset_or_pollset_set,
+ [](grpc_call_element* elem, grpc_polling_entity* pollent) {
+ static_cast(elem->call_data)->set_pollent(pollent);
+ },
// destroy_call_elem
[](grpc_call_element* elem, const grpc_call_final_info*, grpc_closure*) {
static_cast(elem->call_data)->~CallData();
diff --git a/src/core/lib/http/httpcli_security_connector.cc b/src/core/lib/http/httpcli_security_connector.cc
index 5defca225b6..6a3158906fb 100644
--- a/src/core/lib/http/httpcli_security_connector.cc
+++ b/src/core/lib/http/httpcli_security_connector.cc
@@ -32,6 +32,7 @@
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/pollset.h"
+#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/security_connector/ssl_utils.h"
#include "src/core/lib/security/transport/security_handshaker.h"
@@ -116,17 +117,9 @@ class grpc_httpcli_ssl_channel_security_connector final
return strcmp(secure_peer_name_, other->secure_peer_name_);
}
- bool check_call_host(absl::string_view /*host*/,
- grpc_auth_context* /*auth_context*/,
- grpc_closure* /*on_call_host_checked*/,
- grpc_error_handle* error) override {
- *error = GRPC_ERROR_NONE;
- return true;
- }
-
- void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/,
- grpc_error_handle error) override {
- GRPC_ERROR_UNREF(error);
+ ArenaPromise CheckCallHost(absl::string_view,
+ grpc_auth_context*) override {
+ return ImmediateOkStatus();
}
const char* secure_peer_name() const { return secure_peer_name_; }
diff --git a/src/core/lib/iomgr/polling_entity.h b/src/core/lib/iomgr/polling_entity.h
index 6f4c5bdd665..e177176d614 100644
--- a/src/core/lib/iomgr/polling_entity.h
+++ b/src/core/lib/iomgr/polling_entity.h
@@ -23,6 +23,7 @@
#include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/iomgr/pollset_set.h"
+#include "src/core/lib/promise/context.h"
typedef enum grpc_pollset_tag {
GRPC_POLLS_NONE,
@@ -65,4 +66,9 @@ void grpc_polling_entity_add_to_pollset_set(grpc_polling_entity* pollent,
void grpc_polling_entity_del_from_pollset_set(grpc_polling_entity* pollent,
grpc_pollset_set* pss_dst);
+namespace grpc_core {
+template <>
+struct ContextType {};
+} // namespace grpc_core
+
#endif /* GRPC_CORE_LIB_IOMGR_POLLING_ENTITY_H */
diff --git a/src/core/lib/promise/activity.cc b/src/core/lib/promise/activity.cc
index 00b11b05271..adb35272264 100644
--- a/src/core/lib/promise/activity.cc
+++ b/src/core/lib/promise/activity.cc
@@ -28,14 +28,16 @@ namespace grpc_core {
GPR_THREAD_LOCAL(Activity*) Activity::g_current_activity_{nullptr};
Waker::Unwakeable Waker::unwakeable_;
+namespace promise_detail {
+
///////////////////////////////////////////////////////////////////////////////
// HELPER TYPES
// Weak handle to an Activity.
// Handle can persist while Activity goes away.
-class Activity::Handle final : public Wakeable {
+class FreestandingActivity::Handle final : public Wakeable {
public:
- explicit Handle(Activity* activity) : activity_(activity) {}
+ explicit Handle(FreestandingActivity* activity) : activity_(activity) {}
// Ref the Handle (not the activity).
void Ref() { refs_.fetch_add(1, std::memory_order_relaxed); }
@@ -57,7 +59,7 @@ class Activity::Handle final : public Wakeable {
// against DropActivity, so we need to only increase activities refcount if
// it is non-zero.
if (activity_ && activity_->RefIfNonzero()) {
- Activity* activity = activity_;
+ FreestandingActivity* activity = activity_;
mu_.Unlock();
// Activity still exists and we have a reference: wake it up, which will
// drop the ref.
@@ -85,15 +87,15 @@ class Activity::Handle final : public Wakeable {
// activity.
std::atomic refs_{2};
Mutex mu_ ABSL_ACQUIRED_AFTER(activity_->mu_);
- Activity* activity_ ABSL_GUARDED_BY(mu_);
+ FreestandingActivity* activity_ ABSL_GUARDED_BY(mu_);
};
///////////////////////////////////////////////////////////////////////////////
// ACTIVITY IMPLEMENTATION
-bool Activity::RefIfNonzero() { return IncrementIfNonzero(&refs_); }
+bool FreestandingActivity::RefIfNonzero() { return IncrementIfNonzero(&refs_); }
-Activity::Handle* Activity::RefHandle() {
+FreestandingActivity::Handle* FreestandingActivity::RefHandle() {
if (handle_ == nullptr) {
// No handle created yet - construct it and return it.
handle_ = new Handle(this);
@@ -105,11 +107,15 @@ Activity::Handle* Activity::RefHandle() {
}
}
-void Activity::DropHandle() {
+void FreestandingActivity::DropHandle() {
handle_->DropActivity();
handle_ = nullptr;
}
-Waker Activity::MakeNonOwningWaker() { return Waker(RefHandle()); }
+Waker FreestandingActivity::MakeNonOwningWaker() {
+ mu_.AssertHeld();
+ return Waker(RefHandle());
+}
+} // namespace promise_detail
} // namespace grpc_core
diff --git a/src/core/lib/promise/activity.h b/src/core/lib/promise/activity.h
index 0743ec2d02e..01aed8b3e20 100644
--- a/src/core/lib/promise/activity.h
+++ b/src/core/lib/promise/activity.h
@@ -37,6 +37,7 @@
#include "src/core/lib/gpr/tls.h"
#include "src/core/lib/gprpp/construct_destruct.h"
+#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/detail/promise_factory.h"
@@ -110,22 +111,8 @@ class Waker {
// Activity execution may be cancelled by simply deleting the activity. In such
// a case, if execution had not already finished, the done callback would be
// called with absl::CancelledError().
-class Activity : private Wakeable {
+class Activity : public Orphanable {
public:
- // Cancel execution of the underlying promise.
- virtual void Cancel() ABSL_LOCKS_EXCLUDED(mu_) = 0;
-
- // Destroy the Activity - used for the type alias ActivityPtr.
- struct Deleter {
- void operator()(Activity* activity) {
- activity->Cancel();
- activity->Unref();
- }
- };
-
- // Fetch the size of the implementation of this activity.
- virtual size_t Size() = 0;
-
// Force wakeup from the outside.
// This should be rarely needed, and usages should be accompanied with a note
// on why it's not possible to wakeup with a Waker object.
@@ -133,11 +120,8 @@ class Activity : private Wakeable {
// an Activity to repoll.
void ForceWakeup() { MakeOwningWaker().Wakeup(); }
- // Wakeup the current threads activity - will force a subsequent poll after
- // the one that's running.
- static void WakeupCurrent() {
- current()->SetActionDuringRun(ActionDuringRun::kWakeup);
- }
+ // Force the current activity to immediately repoll if it doesn't complete.
+ virtual void ForceImmediateRepoll() = 0;
// Return the current activity.
// Additionally:
@@ -146,58 +130,23 @@ class Activity : private Wakeable {
// locked
// - back up that assertation with a runtime check in debug builds (it's
// prohibitively expensive in non-debug builds)
- static Activity* current() ABSL_ASSERT_EXCLUSIVE_LOCK(current()->mu_) {
-#ifndef NDEBUG
- GPR_ASSERT(g_current_activity_);
- if (g_current_activity_ != nullptr) {
- g_current_activity_->mu_.AssertHeld();
- }
-#endif
- return g_current_activity_;
- }
+ static Activity* current() { return g_current_activity_; }
// Produce an activity-owning Waker. The produced waker will keep the activity
// alive until it's awoken or dropped.
- Waker MakeOwningWaker() {
- Ref();
- return Waker(this);
- }
+ virtual Waker MakeOwningWaker() = 0;
// Produce a non-owning Waker. The waker will own a small heap allocated weak
// pointer to this activity. This is more suitable for wakeups that may not be
// delivered until long after the activity should be destroyed.
- Waker MakeNonOwningWaker() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
+ virtual Waker MakeNonOwningWaker() = 0;
protected:
- // Action received during a run, in priority order.
- // If more than one action is received during a run, we use max() to resolve
- // which one to report (so Cancel overrides Wakeup).
- enum class ActionDuringRun : uint8_t {
- kNone, // No action occured during run.
- kWakeup, // A wakeup occured during run.
- kCancel, // Cancel was called during run.
- };
-
- inline virtual ~Activity() {
- if (handle_) {
- DropHandle();
- }
- }
-
- // All promise execution occurs under this mutex.
- Mutex mu_;
-
// Check if this activity is the current activity executing on the current
// thread.
bool is_current() const { return this == g_current_activity_; }
// Check if there is an activity executing on the current thread.
static bool have_current() { return g_current_activity_ != nullptr; }
- // Check if we got an internal wakeup since the last time this function was
- // called.
- ActionDuringRun GotActionDuringRun() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
- return absl::exchange(action_during_run_, ActionDuringRun::kNone);
- }
-
// Set the current activity at construction, clean it up at destruction.
class ScopedActivity {
public:
@@ -210,58 +159,14 @@ class Activity : private Wakeable {
ScopedActivity& operator=(const ScopedActivity&) = delete;
};
- // Implementors of Wakeable::Wakeup should call this after the wakeup has
- // completed.
- void WakeupComplete() { Unref(); }
-
- // Mark the current activity as being cancelled (so we can actually cancel it
- // after polling).
- void CancelCurrent() {
- current()->SetActionDuringRun(ActionDuringRun::kCancel);
- }
-
private:
- class Handle;
-
- void Ref() { refs_.fetch_add(1, std::memory_order_relaxed); }
- void Unref() {
- if (1 == refs_.fetch_sub(1, std::memory_order_acq_rel)) {
- delete this;
- }
- }
-
- // Return a Handle instance with a ref so that it can be stored waiting for
- // some wakeup.
- Handle* RefHandle() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
- // If our refcount is non-zero, ref and return true.
- // Otherwise, return false.
- bool RefIfNonzero();
- // Drop the (proved existing) wait handle.
- void DropHandle() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
- // Set the action that occured during this run.
- // We use max to combine actions so that cancellation overrides wakeups.
- void SetActionDuringRun(ActionDuringRun action)
- ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
- action_during_run_ = std::max(action_during_run_, action);
- }
-
- // Current refcount.
- std::atomic refs_{1};
- // If wakeup is called during Promise polling, we set this to Wakeup and
- // repoll. If cancel is called during Promise polling, we set this to Cancel
- // and cancel at the end of polling.
- ActionDuringRun action_during_run_ ABSL_GUARDED_BY(mu_) =
- ActionDuringRun::kNone;
- // Handle for long waits. Allows a very small weak pointer type object to
- // queue for wakeups while Activity may be deleted earlier.
- Handle* handle_ ABSL_GUARDED_BY(mu_) = nullptr;
// Set during RunLoop to the Activity that's executing.
// Being set implies that mu_ is held.
static GPR_THREAD_LOCAL(Activity*) g_current_activity_;
};
// Owned pointer to one Activity.
-using ActivityPtr = std::unique_ptr;
+using ActivityPtr = OrphanablePtr;
namespace promise_detail {
@@ -320,6 +225,107 @@ class ActivityContexts : public ContextHolder... {
};
};
+// A free standing activity: an activity that owns its own synchronization and
+// memory.
+// The alternative is an activity that's somehow tied into another system, for
+// instance the type seen in promise_based_filter.h as we're transitioning from
+// the old filter stack to the new system.
+// FreestandingActivity is-a Wakeable, but needs to increment a refcount before
+// returning that Wakeable interface. Additionally, we want to keep
+// FreestandingActivity as small as is possible, since it will be used
+// everywhere. So we use inheritance to provide the Wakeable interface: this
+// makes it zero sized, and we make the inheritance private to prevent
+// accidental casting.
+class FreestandingActivity : public Activity, private Wakeable {
+ public:
+ Waker MakeOwningWaker() final {
+ Ref();
+ return Waker(this);
+ }
+ Waker MakeNonOwningWaker() final;
+
+ void Orphan() final {
+ Cancel();
+ Unref();
+ }
+
+ void ForceImmediateRepoll() final {
+ mu_.AssertHeld();
+ SetActionDuringRun(ActionDuringRun::kWakeup);
+ }
+
+ protected:
+ // Action received during a run, in priority order.
+ // If more than one action is received during a run, we use max() to resolve
+ // which one to report (so Cancel overrides Wakeup).
+ enum class ActionDuringRun : uint8_t {
+ kNone, // No action occured during run.
+ kWakeup, // A wakeup occured during run.
+ kCancel, // Cancel was called during run.
+ };
+
+ inline ~FreestandingActivity() override {
+ if (handle_) {
+ DropHandle();
+ }
+ }
+
+ // Check if we got an internal wakeup since the last time this function was
+ // called.
+ ActionDuringRun GotActionDuringRun() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ return absl::exchange(action_during_run_, ActionDuringRun::kNone);
+ }
+
+ // Implementors of Wakeable::Wakeup should call this after the wakeup has
+ // completed.
+ void WakeupComplete() { Unref(); }
+
+ // Set the action that occured during this run.
+ // We use max to combine actions so that cancellation overrides wakeups.
+ void SetActionDuringRun(ActionDuringRun action)
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ action_during_run_ = std::max(action_during_run_, action);
+ }
+
+ Mutex* mu() ABSL_LOCK_RETURNED(mu_) { return &mu_; }
+
+ private:
+ class Handle;
+
+ // Cancel execution of the underlying promise.
+ virtual void Cancel() = 0;
+
+ void Ref() { refs_.fetch_add(1, std::memory_order_relaxed); }
+ void Unref() {
+ if (1 == refs_.fetch_sub(1, std::memory_order_acq_rel)) {
+ delete this;
+ }
+ }
+
+ // Return a Handle instance with a ref so that it can be stored waiting for
+ // some wakeup.
+ Handle* RefHandle() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
+ // If our refcount is non-zero, ref and return true.
+ // Otherwise, return false.
+ bool RefIfNonzero();
+ // Drop the (proved existing) wait handle.
+ void DropHandle() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
+
+ // All promise execution occurs under this mutex.
+ Mutex mu_;
+
+ // Current refcount.
+ std::atomic refs_{1};
+ // If wakeup is called during Promise polling, we set this to Wakeup and
+ // repoll. If cancel is called during Promise polling, we set this to Cancel
+ // and cancel at the end of polling.
+ ActionDuringRun action_during_run_ ABSL_GUARDED_BY(mu_) =
+ ActionDuringRun::kNone;
+ // Handle for long waits. Allows a very small weak pointer type object to
+ // queue for wakeups while Activity may be deleted earlier.
+ Handle* handle_ ABSL_GUARDED_BY(mu_) = nullptr;
+};
+
// Implementation details for an Activity of an arbitrary type of promise.
// There should exist a static function:
// struct WakeupScheduler {
@@ -331,8 +337,12 @@ class ActivityContexts : public ContextHolder... {
// It can assume that activity will remain live until RunScheduledWakeup() is
// invoked, and that a given activity will not be concurrently scheduled again
// until its RunScheduledWakeup() has been invoked.
+// We use private inheritance here as a way of getting private members for
+// each of the contexts.
+// TODO(ctiller): We can probably reconsider the private inheritance here
+// when we move away from C++11 and have more powerful template features.
template
-class PromiseActivity final : public Activity,
+class PromiseActivity final : public FreestandingActivity,
private ActivityContexts {
public:
using Factory = PromiseFactory;
@@ -340,7 +350,7 @@ class PromiseActivity final : public Activity,
PromiseActivity(F promise_factory, WakeupScheduler wakeup_scheduler,
OnDone on_done, Contexts&&... contexts)
- : Activity(),
+ : FreestandingActivity(),
ActivityContexts(std::forward(contexts)...),
wakeup_scheduler_(std::move(wakeup_scheduler)),
on_done_(std::move(on_done)) {
@@ -348,9 +358,9 @@ class PromiseActivity final : public Activity,
// This may hit a waiter, which could expose our this pointer to other
// threads, meaning we do need to hold this mutex even though we're still
// constructing.
- mu_.Lock();
+ mu()->Lock();
auto status = Start(Factory(std::move(promise_factory)));
- mu_.Unlock();
+ mu()->Unlock();
// We may complete immediately.
if (status.has_value()) {
on_done_(std::move(*status));
@@ -364,16 +374,24 @@ class PromiseActivity final : public Activity,
GPR_ASSERT(done_);
}
- size_t Size() override { return sizeof(*this); }
+ void RunScheduledWakeup() {
+ GPR_ASSERT(wakeup_scheduled_.exchange(false, std::memory_order_acq_rel));
+ Step();
+ WakeupComplete();
+ }
+
+ private:
+ using typename ActivityContexts::ScopedContext;
void Cancel() final {
if (Activity::is_current()) {
- CancelCurrent();
+ mu()->AssertHeld();
+ SetActionDuringRun(ActionDuringRun::kCancel);
return;
}
bool was_done;
{
- MutexLock lock(&mu_);
+ MutexLock lock(mu());
// Check if we were done, and flag done.
was_done = done_;
if (!done_) MarkDone();
@@ -384,15 +402,6 @@ class PromiseActivity final : public Activity,
}
}
- void RunScheduledWakeup() {
- GPR_ASSERT(wakeup_scheduled_.exchange(false, std::memory_order_acq_rel));
- Step();
- WakeupComplete();
- }
-
- private:
- using typename ActivityContexts::ScopedContext;
-
// Wakeup this activity. Arrange to poll the activity again at a convenient
// time: this could be inline if it's deemed safe, or it could be by passing
// the activity to an external threadpool to run. If the activity is already
@@ -402,7 +411,8 @@ class PromiseActivity final : public Activity,
// If there is an active activity, but hey it's us, flag that and we'll loop
// in RunLoop (that's calling from above here!).
if (Activity::is_current()) {
- WakeupCurrent();
+ mu()->AssertHeld();
+ SetActionDuringRun(ActionDuringRun::kWakeup);
WakeupComplete();
return;
}
@@ -420,7 +430,7 @@ class PromiseActivity final : public Activity,
// Notification that we're no longer executing - it's ok to destruct the
// promise.
- void MarkDone() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ void MarkDone() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu()) {
GPR_ASSERT(!done_);
done_ = true;
Destruct(&promise_holder_.promise);
@@ -428,16 +438,16 @@ class PromiseActivity final : public Activity,
// In response to Wakeup, run the Promise state machine again until it
// settles. Then check for completion, and if we have completed, call on_done.
- void Step() ABSL_LOCKS_EXCLUDED(mu_) {
+ void Step() ABSL_LOCKS_EXCLUDED(mu()) {
// Poll the promise until things settle out under a lock.
- mu_.Lock();
+ mu()->Lock();
if (done_) {
// We might get some spurious wakeups after finishing.
- mu_.Unlock();
+ mu()->Unlock();
return;
}
auto status = RunStep();
- mu_.Unlock();
+ mu()->Unlock();
if (status.has_value()) {
on_done_(std::move(*status));
}
@@ -446,7 +456,7 @@ class PromiseActivity final : public Activity,
// The main body of a step: set the current activity, and any contexts, and
// then run the main polling loop. Contained in a function by itself in
// order to keep the scoping rules a little easier in Step().
- absl::optional RunStep() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ absl::optional RunStep() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu()) {
ScopedActivity scoped_activity(this);
ScopedContext contexts(this);
return StepLoop();
@@ -456,7 +466,7 @@ class PromiseActivity final : public Activity,
// promise factory before entering the main loop. Called once from the
// constructor.
absl::optional Start(Factory promise_factory)
- ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu()) {
ScopedActivity scoped_activity(this);
ScopedContext contexts(this);
Construct(&promise_holder_.promise, promise_factory.Once());
@@ -465,7 +475,7 @@ class PromiseActivity final : public Activity,
// Until there are no wakeups from within and the promise is incomplete:
// poll the promise.
- absl::optional StepLoop() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ absl::optional StepLoop() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu()) {
GPR_ASSERT(is_current());
while (true) {
// Run the promise.
@@ -495,7 +505,7 @@ class PromiseActivity final : public Activity,
// Callback on completion of the promise.
GPR_NO_UNIQUE_ADDRESS OnDone on_done_;
// Has execution completed?
- GPR_NO_UNIQUE_ADDRESS bool done_ ABSL_GUARDED_BY(mu_) = false;
+ GPR_NO_UNIQUE_ADDRESS bool done_ ABSL_GUARDED_BY(mu()) = false;
// Is there a wakeup scheduled?
GPR_NO_UNIQUE_ADDRESS std::atomic wakeup_scheduled_{false};
// We wrap the promise in a union to allow control over the construction
@@ -506,7 +516,7 @@ class PromiseActivity final : public Activity,
~PromiseHolder() {}
GPR_NO_UNIQUE_ADDRESS Promise promise;
};
- GPR_NO_UNIQUE_ADDRESS PromiseHolder promise_holder_ ABSL_GUARDED_BY(mu_);
+ GPR_NO_UNIQUE_ADDRESS PromiseHolder promise_holder_ ABSL_GUARDED_BY(mu());
};
} // namespace promise_detail
diff --git a/src/core/lib/promise/arena_promise.h b/src/core/lib/promise/arena_promise.h
index 5a1bc3fa521..14db9843d9e 100644
--- a/src/core/lib/promise/arena_promise.h
+++ b/src/core/lib/promise/arena_promise.h
@@ -69,7 +69,7 @@ class CallableImpl final : public ImplInterface {
public:
explicit CallableImpl(Callable&& callable) : callable_(std::move(callable)) {}
// Forward polls to the callable object.
- Poll PollOnce() override { return callable_(); }
+ Poll PollOnce() override { return poll_cast(callable_()); }
// Destroy destructs the callable object.
void Destroy() override { this->~CallableImpl(); }
@@ -152,7 +152,8 @@ class ArenaPromise {
template ::value>>
- explicit ArenaPromise(Callable&& callable)
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ ArenaPromise(Callable&& callable)
: impl_(arena_promise_detail::MakeImplForCallable(
std::forward(callable))) {}
@@ -164,6 +165,7 @@ class ArenaPromise {
other.impl_ = arena_promise_detail::NullImpl::Get();
}
ArenaPromise& operator=(ArenaPromise&& other) noexcept {
+ impl_->Destroy();
impl_ = other.impl_;
other.impl_ = arena_promise_detail::NullImpl::Get();
return *this;
diff --git a/src/core/lib/promise/detail/basic_seq.h b/src/core/lib/promise/detail/basic_seq.h
index 59ac80f79dc..d3029f10ee1 100644
--- a/src/core/lib/promise/detail/basic_seq.h
+++ b/src/core/lib/promise/detail/basic_seq.h
@@ -401,6 +401,95 @@ class BasicSeq {
}
};
+// As above, but models a sequence of unknown size
+// At each element, the accumulator A and the current value V is passed to some
+// function of type F as f(V, A); f is expected to return a promise that
+// resolves to Traits::WrappedType.
+template class Traits, typename F, typename Arg,
+ typename Iter>
+class BasicSeqIter {
+ private:
+ using IterValue = decltype(*std::declval());
+ using StateCreated = decltype(std::declval()(std::declval(),
+ std::declval()));
+ using State = PromiseLike;
+ using Wrapped = typename State::Result;
+
+ public:
+ BasicSeqIter(Iter begin, Iter end, F f, Arg arg)
+ : cur_(begin), end_(end), f_(std::move(f)) {
+ if (cur_ == end_) {
+ Construct(&result_, std::move(arg));
+ } else {
+ Construct(&state_, f_(*cur_, std::move(arg)));
+ }
+ }
+
+ ~BasicSeqIter() {
+ if (cur_ == end_) {
+ Destruct(&result_);
+ } else {
+ Destruct(&state_);
+ }
+ }
+
+ BasicSeqIter(const BasicSeqIter& other) = delete;
+ BasicSeqIter& operator=(const BasicSeqIter&) = delete;
+
+ BasicSeqIter(BasicSeqIter&& other) noexcept
+ : cur_(other.cur_), end_(other.end_), f_(std::move(other.f_)) {
+ if (cur_ == end_) {
+ Construct(&result_, std::move(other.result_));
+ } else {
+ Construct(&state_, std::move(other.state_));
+ }
+ }
+ BasicSeqIter& operator=(BasicSeqIter&& other) noexcept {
+ cur_ = other.cur_;
+ end_ = other.end_;
+ if (cur_ == end_) {
+ Construct(&result_, std::move(other.result_));
+ } else {
+ Construct(&state_, std::move(other.state_));
+ }
+ return *this;
+ }
+
+ Poll operator()() {
+ if (cur_ == end_) {
+ return std::move(result_);
+ }
+ return PollNonEmpty();
+ }
+
+ private:
+ Poll PollNonEmpty() {
+ Poll r = state_();
+ if (absl::holds_alternative(r)) return r;
+ return Traits::template CheckResultAndRunNext(
+ std::move(absl::get(r)), [this](Wrapped arg) -> Poll {
+ auto next = cur_;
+ ++next;
+ if (next == end_) {
+ return std::move(arg);
+ }
+ cur_ = next;
+ state_.~State();
+ Construct(&state_,
+ Traits::CallSeqFactory(f_, *cur_, std::move(arg)));
+ return PollNonEmpty();
+ });
+ }
+
+ Iter cur_;
+ const Iter end_;
+ GPR_NO_UNIQUE_ADDRESS F f_;
+ union {
+ GPR_NO_UNIQUE_ADDRESS State state_;
+ GPR_NO_UNIQUE_ADDRESS Arg result_;
+ };
+};
+
} // namespace promise_detail
} // namespace grpc_core
diff --git a/src/core/lib/promise/detail/promise_factory.h b/src/core/lib/promise/detail/promise_factory.h
index 567bfccee02..e37e2e696c0 100644
--- a/src/core/lib/promise/detail/promise_factory.h
+++ b/src/core/lib/promise/detail/promise_factory.h
@@ -88,7 +88,7 @@ class Curried {
: f_(std::forward(f)), arg_(std::forward(arg)) {}
Curried(const F& f, Arg&& arg) : f_(f), arg_(std::forward(arg)) {}
using Result = decltype(std::declval()(std::declval()));
- Result operator()() { return f_(arg_); }
+ Result operator()() { return f_(std::move(arg_)); }
private:
GPR_NO_UNIQUE_ADDRESS F f_;
diff --git a/src/core/lib/promise/intra_activity_waiter.h b/src/core/lib/promise/intra_activity_waiter.h
index 889323bf3ec..137db5fd6dd 100644
--- a/src/core/lib/promise/intra_activity_waiter.h
+++ b/src/core/lib/promise/intra_activity_waiter.h
@@ -36,7 +36,7 @@ class IntraActivityWaiter {
void Wake() {
if (waiting_) {
waiting_ = false;
- Activity::WakeupCurrent();
+ Activity::current()->ForceImmediateRepoll();
}
}
diff --git a/src/core/lib/promise/poll.h b/src/core/lib/promise/poll.h
index 16fb74e4dfd..e891bf728e9 100644
--- a/src/core/lib/promise/poll.h
+++ b/src/core/lib/promise/poll.h
@@ -37,6 +37,12 @@ struct Pending {
template
using Poll = absl::variant;
+template
+Poll poll_cast(Poll poll) {
+ if (absl::holds_alternative(poll)) return Pending{};
+ return std::move(absl::get(poll));
+}
+
// Variant of Poll that serves as a ready value
static constexpr size_t kPollReadyIdx = 1;
diff --git a/src/core/lib/promise/promise.h b/src/core/lib/promise/promise.h
index 5ae27d42ee7..1e414314f44 100644
--- a/src/core/lib/promise/promise.h
+++ b/src/core/lib/promise/promise.h
@@ -20,6 +20,7 @@
#include
#include
+#include "absl/status/status.h"
#include "absl/types/optional.h"
#include "absl/types/variant.h"
@@ -64,7 +65,6 @@ class Immediate {
private:
T value_;
};
-
} // namespace promise_detail
// Return \a value immediately
@@ -73,6 +73,11 @@ promise_detail::Immediate Immediate(T value) {
return promise_detail::Immediate(std::move(value));
}
+// Return status Ok immediately
+struct ImmediateOkStatus {
+ Poll operator()() { return absl::OkStatus(); }
+};
+
// Typecheck that a promise returns the expected return type.
// usage: auto promise = WithResult([]() { return 3; });
// NOTE: there are tests in promise_test.cc that are commented out because they
diff --git a/src/core/lib/promise/seq.h b/src/core/lib/promise/seq.h
index 250c6eb39ff..8ad2c549590 100644
--- a/src/core/lib/promise/seq.h
+++ b/src/core/lib/promise/seq.h
@@ -37,7 +37,11 @@ struct SeqTraits {
-> decltype(next->Once(std::forward(value))) {
return next->Once(std::forward(value));
}
-
+ template
+ static auto CallSeqFactory(F& f, Elem&& elem, T&& value)
+ -> decltype(f(std::forward(elem), std::forward(value))) {
+ return f(std::forward(elem), std::forward(value));
+ }
template
static Poll CheckResultAndRunNext(PriorResult prior,
RunNext run_next) {
@@ -66,6 +70,20 @@ F Seq(F functor) {
return functor;
}
+// Execute a sequence of operations of unknown length.
+// Asynchronously:
+// for (element in (begin, end)) {
+// argument = wait_for factory(element, argument);
+// }
+// return argument;
+template
+promise_detail::BasicSeqIter
+SeqIter(Iter begin, Iter end, Argument argument, Factory factory) {
+ return promise_detail::BasicSeqIter(
+ begin, end, std::move(factory), std::move(argument));
+}
+
} // namespace grpc_core
#endif // GRPC_CORE_LIB_PROMISE_SEQ_H
diff --git a/src/core/lib/promise/try_seq.h b/src/core/lib/promise/try_seq.h
index f31c3cc19c2..be7800aefbb 100644
--- a/src/core/lib/promise/try_seq.h
+++ b/src/core/lib/promise/try_seq.h
@@ -41,6 +41,11 @@ struct TrySeqTraitsWithSfinae {
-> decltype(next->Once(std::forward(value))) {
return next->Once(std::forward(value));
}
+ template
+ static auto CallSeqFactory(F& f, Elem&& elem, T&& value)
+ -> decltype(f(std::forward(elem), std::forward(value))) {
+ return f(std::forward(elem), std::forward(value));
+ }
template
static Poll CheckResultAndRunNext(T prior, RunNext run_next) {
return run_next(std::move(prior));
@@ -56,6 +61,11 @@ struct TrySeqTraitsWithSfinae> {
-> decltype(next->Once(std::move(*status))) {
return next->Once(std::move(*status));
}
+ template
+ static auto CallSeqFactory(F& f, Elem&& elem, absl::StatusOr value)
+ -> decltype(f(std::forward(elem), std::move(*value))) {
+ return f(std::forward(elem), std::move(*value));
+ }
template
static Poll CheckResultAndRunNext(absl::StatusOr prior,
RunNext run_next) {
@@ -109,6 +119,23 @@ promise_detail::TrySeq TrySeq(Functors... functors) {
return promise_detail::TrySeq(std::move(functors)...);
}
+// Try a sequence of operations of unknown length.
+// Asynchronously:
+// for (element in (begin, end)) {
+// auto r = wait_for factory(element, argument);
+// if (!r.ok()) return r;
+// argument = *r;
+// }
+// return argument;
+template
+promise_detail::BasicSeqIter
+TrySeqIter(Iter begin, Iter end, Argument argument, Factory factory) {
+ return promise_detail::BasicSeqIter(
+ begin, end, std::move(factory), std::move(argument));
+}
+
} // namespace grpc_core
#endif // GRPC_CORE_LIB_PROMISE_TRY_SEQ_H
diff --git a/src/core/lib/resource_quota/memory_quota.cc b/src/core/lib/resource_quota/memory_quota.cc
index b2d9040d12b..d4799095bac 100644
--- a/src/core/lib/resource_quota/memory_quota.cc
+++ b/src/core/lib/resource_quota/memory_quota.cc
@@ -135,7 +135,7 @@ Poll> ReclaimerQueue::PollNext() {
if (!empty) {
// If we don't, but the queue is probably not empty, schedule an immediate
// repoll.
- Activity::WakeupCurrent();
+ Activity::current()->ForceImmediateRepoll();
} else {
// Otherwise, schedule a wakeup for whenever something is pushed.
state_->waker = Activity::current()->MakeNonOwningWaker();
diff --git a/src/core/lib/security/credentials/call_creds_util.cc b/src/core/lib/security/credentials/call_creds_util.cc
new file mode 100644
index 00000000000..ecb79a2b839
--- /dev/null
+++ b/src/core/lib/security/credentials/call_creds_util.cc
@@ -0,0 +1,87 @@
+//
+// 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 "src/core/lib/security/credentials/call_creds_util.h"
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
+namespace grpc_core {
+
+namespace {
+
+struct ServiceUrlAndMethod {
+ std::string service_url;
+ absl::string_view method_name;
+};
+
+ServiceUrlAndMethod MakeServiceUrlAndMethod(
+ const ClientInitialMetadata& initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs* args) {
+ auto service =
+ initial_metadata->get_pointer(HttpPathMetadata())->as_string_view();
+ auto last_slash = service.find_last_of('/');
+ absl::string_view method_name;
+ if (last_slash == absl::string_view::npos) {
+ gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
+ service = "";
+ method_name = "";
+ } else if (last_slash == 0) {
+ method_name = "";
+ } else {
+ method_name = service.substr(last_slash + 1);
+ service = service.substr(0, last_slash);
+ }
+ auto host_and_port =
+ initial_metadata->get_pointer(HttpAuthorityMetadata())->as_string_view();
+ absl::string_view url_scheme = args->security_connector->url_scheme();
+ if (url_scheme == GRPC_SSL_URL_SCHEME) {
+ // Remove the port if it is 443.
+ auto port_delimiter = host_and_port.find_last_of(':');
+ if (port_delimiter != absl::string_view::npos &&
+ host_and_port.substr(port_delimiter + 1) == "443") {
+ host_and_port = host_and_port.substr(0, port_delimiter);
+ }
+ }
+ return ServiceUrlAndMethod{
+ absl::StrCat(url_scheme, "://", host_and_port, service), method_name};
+}
+
+} // namespace
+
+std::string MakeJwtServiceUrl(
+ const ClientInitialMetadata& initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs* args) {
+ return MakeServiceUrlAndMethod(initial_metadata, args).service_url;
+}
+
+grpc_auth_metadata_context MakePluginAuthMetadataContext(
+ const ClientInitialMetadata& initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs* args) {
+ auto fields = MakeServiceUrlAndMethod(initial_metadata, args);
+ grpc_auth_metadata_context ctx;
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.channel_auth_context = args->auth_context != nullptr
+ ? args->auth_context->Ref().release()
+ : nullptr;
+ ctx.service_url = gpr_strdup(fields.service_url.c_str());
+ ctx.method_name = gpr_strdup(std::string(fields.method_name).c_str());
+ return ctx;
+}
+
+} // namespace grpc_core
diff --git a/src/core/lib/security/credentials/call_creds_util.h b/src/core/lib/security/credentials/call_creds_util.h
new file mode 100644
index 00000000000..84072ba4bd9
--- /dev/null
+++ b/src/core/lib/security/credentials/call_creds_util.h
@@ -0,0 +1,42 @@
+//
+// 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.
+//
+
+#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_CALL_CREDS_UTIL_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_CALL_CREDS_UTIL_H
+
+#include
+
+#include
+
+#include
+
+#include "src/core/lib/security/credentials/credentials.h"
+
+namespace grpc_core {
+
+// Helper function to construct service URL for jwt call creds.
+std::string MakeJwtServiceUrl(
+ const ClientInitialMetadata& initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs* args);
+
+// Helper function to construct context for plugin call creds.
+grpc_auth_metadata_context MakePluginAuthMetadataContext(
+ const ClientInitialMetadata& initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs* args);
+
+} // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_CALL_CREDS_UTIL_H */
diff --git a/src/core/lib/security/credentials/composite/composite_credentials.cc b/src/core/lib/security/credentials/composite/composite_credentials.cc
index dad03165ae9..cd63139bcbd 100644
--- a/src/core/lib/security/credentials/composite/composite_credentials.cc
+++ b/src/core/lib/security/credentials/composite/composite_credentials.cc
@@ -33,7 +33,9 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/polling_entity.h"
+#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/transport/transport.h"
namespace grpc_core {
const char kCredentialsTypeComposite[] = "composite";
@@ -41,87 +43,17 @@ const char kCredentialsTypeComposite[] = "composite";
/* -- Composite call credentials. -- */
-static void composite_call_metadata_cb(void* arg, grpc_error_handle error);
-
-namespace {
-struct grpc_composite_call_credentials_metadata_context {
- grpc_composite_call_credentials_metadata_context(
- grpc_composite_call_credentials* composite_creds,
- grpc_polling_entity* pollent, grpc_auth_metadata_context auth_md_context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata)
- : composite_creds(composite_creds),
- pollent(pollent),
- auth_md_context(auth_md_context),
- md_array(md_array),
- on_request_metadata(on_request_metadata) {
- GRPC_CLOSURE_INIT(&internal_on_request_metadata, composite_call_metadata_cb,
- this, grpc_schedule_on_exec_ctx);
- }
-
- grpc_composite_call_credentials* composite_creds;
- size_t creds_index = 0;
- grpc_polling_entity* pollent;
- grpc_auth_metadata_context auth_md_context;
- grpc_core::CredentialsMetadataArray* md_array;
- grpc_closure* on_request_metadata;
- grpc_closure internal_on_request_metadata;
-};
-} // namespace
-
-static void composite_call_metadata_cb(void* arg, grpc_error_handle error) {
- grpc_composite_call_credentials_metadata_context* ctx =
- static_cast(arg);
- if (error == GRPC_ERROR_NONE) {
- const grpc_composite_call_credentials::CallCredentialsList& inner =
- ctx->composite_creds->inner();
- /* See if we need to get some more metadata. */
- if (ctx->creds_index < inner.size()) {
- if (inner[ctx->creds_index++]->get_request_metadata(
- ctx->pollent, ctx->auth_md_context, ctx->md_array,
- &ctx->internal_on_request_metadata, &error)) {
- // Synchronous response, so call ourselves recursively.
- composite_call_metadata_cb(arg, error);
- GRPC_ERROR_UNREF(error);
- }
- return;
- }
- // We're done!
- }
- grpc_core::ExecCtx::Run(DEBUG_LOCATION, ctx->on_request_metadata,
- GRPC_ERROR_REF(error));
- delete ctx;
-}
-
-bool grpc_composite_call_credentials::get_request_metadata(
- grpc_polling_entity* pollent, grpc_auth_metadata_context auth_md_context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata, grpc_error_handle* error) {
- grpc_composite_call_credentials_metadata_context* ctx;
- ctx = new grpc_composite_call_credentials_metadata_context(
- this, pollent, auth_md_context, md_array, on_request_metadata);
- bool synchronous = true;
- const CallCredentialsList& inner = ctx->composite_creds->inner();
- while (ctx->creds_index < inner.size()) {
- if (inner[ctx->creds_index++]->get_request_metadata(
- ctx->pollent, ctx->auth_md_context, ctx->md_array,
- &ctx->internal_on_request_metadata, error)) {
- if (*error != GRPC_ERROR_NONE) break;
- } else {
- synchronous = false; // Async return.
- break;
- }
- }
- if (synchronous) delete ctx;
- return synchronous;
-}
-
-void grpc_composite_call_credentials::cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* md_array, grpc_error_handle error) {
- for (size_t i = 0; i < inner_.size(); ++i) {
- inner_[i]->cancel_get_request_metadata(md_array, GRPC_ERROR_REF(error));
- }
- GRPC_ERROR_UNREF(error);
+grpc_core::ArenaPromise>
+grpc_composite_call_credentials::GetRequestMetadata(
+ grpc_core::ClientInitialMetadata initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs* args) {
+ auto self = Ref();
+ return TrySeqIter(
+ inner_.begin(), inner_.end(), std::move(initial_metadata),
+ [self, args](const grpc_core::RefCountedPtr& creds,
+ grpc_core::ClientInitialMetadata initial_metadata) {
+ return creds->GetRequestMetadata(std::move(initial_metadata), args);
+ });
}
std::string grpc_composite_call_credentials::debug_string() {
diff --git a/src/core/lib/security/credentials/composite/composite_credentials.h b/src/core/lib/security/credentials/composite/composite_credentials.h
index ab6bbe35dca..e200d9a3a9a 100644
--- a/src/core/lib/security/credentials/composite/composite_credentials.h
+++ b/src/core/lib/security/credentials/composite/composite_credentials.h
@@ -90,15 +90,9 @@ class grpc_composite_call_credentials : public grpc_call_credentials {
grpc_core::RefCountedPtr creds2);
~grpc_composite_call_credentials() override = default;
- bool get_request_metadata(grpc_polling_entity* pollent,
- grpc_auth_metadata_context context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata,
- grpc_error_handle* error) override;
-
- void cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_error_handle error) override;
+ grpc_core::ArenaPromise>
+ GetRequestMetadata(grpc_core::ClientInitialMetadata initial_metadata,
+ const GetRequestMetadataArgs* args) override;
grpc_security_level min_security_level() const override {
return min_security_level_;
diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h
index 59ae767586d..6bb62a31141 100644
--- a/src/core/lib/security/credentials/credentials.h
+++ b/src/core/lib/security/credentials/credentials.h
@@ -31,8 +31,11 @@
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/iomgr/polling_entity.h"
+#include "src/core/lib/promise/arena_promise.h"
+#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/security_connector/security_connector.h"
#include "src/core/lib/transport/metadata_batch.h"
+#include "src/core/lib/transport/transport.h"
struct grpc_http_response;
@@ -185,6 +188,16 @@ using CredentialsMetadataArray = std::vector>;
struct grpc_call_credentials
: public grpc_core::RefCounted {
public:
+ // TODO(roth): Consider whether security connector actually needs to
+ // be part of this interface. Currently, it is here only for the
+ // url_scheme() method, which we might be able to instead add as an
+ // auth context property.
+ struct GetRequestMetadataArgs {
+ grpc_core::RefCountedPtr
+ security_connector;
+ grpc_core::RefCountedPtr auth_context;
+ };
+
explicit grpc_call_credentials(
const char* type,
grpc_security_level min_security_level = GRPC_PRIVACY_AND_INTEGRITY)
@@ -192,21 +205,10 @@ struct grpc_call_credentials
~grpc_call_credentials() override = default;
- // Returns true if completed synchronously, in which case \a error will
- // be set to indicate the result. Otherwise, \a on_request_metadata will
- // be invoked asynchronously when complete. \a md_array will be populated
- // with the resulting metadata once complete.
- virtual bool get_request_metadata(
- grpc_polling_entity* pollent, grpc_auth_metadata_context context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata, grpc_error_handle* error) = 0;
-
- // Cancels a pending asynchronous operation started by
- // grpc_call_credentials_get_request_metadata() with the corresponding
- // value of \a md_array.
- virtual void cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_error_handle error) = 0;
+ virtual grpc_core::ArenaPromise<
+ absl::StatusOr>
+ GetRequestMetadata(grpc_core::ClientInitialMetadata initial_metadata,
+ const GetRequestMetadataArgs* args) = 0;
virtual grpc_security_level min_security_level() const {
return min_security_level_;
@@ -240,7 +242,7 @@ struct grpc_call_credentials
/* Metadata-only credentials with the specified key and value where
asynchronicity can be simulated for testing. */
grpc_call_credentials* grpc_md_only_test_credentials_create(
- const char* md_key, const char* md_value, bool is_async);
+ const char* md_key, const char* md_value);
/* --- grpc_server_credentials. --- */
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.cc b/src/core/lib/security/credentials/fake/fake_credentials.cc
index 5a9fbcbb1d8..52d00a45523 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.cc
+++ b/src/core/lib/security/credentials/fake/fake_credentials.cc
@@ -29,6 +29,7 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/executor.h"
+#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/security_connector/fake/fake_security_connector.h"
/* -- Fake transport security credentials. -- */
@@ -96,26 +97,17 @@ const char* grpc_fake_transport_get_expected_targets(
/* -- Metadata-only test credentials. -- */
-bool grpc_md_only_test_credentials::get_request_metadata(
- grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context /*context*/,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata, grpc_error_handle* /*error*/) {
- md_array->emplace_back(key_.Ref(), value_.Ref());
- if (is_async_) {
- grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_request_metadata,
- GRPC_ERROR_NONE);
- return false;
- }
- return true;
-}
-
-void grpc_md_only_test_credentials::cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* /*md_array*/,
- grpc_error_handle error) {
- GRPC_ERROR_UNREF(error);
+grpc_core::ArenaPromise>
+grpc_md_only_test_credentials::GetRequestMetadata(
+ grpc_core::ClientInitialMetadata initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs*) {
+ initial_metadata->Append(
+ key_.as_string_view(), value_.Ref(),
+ [](absl::string_view, const grpc_core::Slice&) { abort(); });
+ return grpc_core::Immediate(std::move(initial_metadata));
}
grpc_call_credentials* grpc_md_only_test_credentials_create(
- const char* md_key, const char* md_value, bool is_async) {
- return new grpc_md_only_test_credentials(md_key, md_value, is_async);
+ const char* md_key, const char* md_value) {
+ return new grpc_md_only_test_credentials(md_key, md_value);
}
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.h b/src/core/lib/security/credentials/fake/fake_credentials.h
index 95a96fff1fe..f55e9863aa9 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.h
+++ b/src/core/lib/security/credentials/fake/fake_credentials.h
@@ -59,23 +59,15 @@ const char* grpc_fake_transport_get_expected_targets(
class grpc_md_only_test_credentials : public grpc_call_credentials {
public:
- grpc_md_only_test_credentials(const char* md_key, const char* md_value,
- bool is_async)
+ grpc_md_only_test_credentials(const char* md_key, const char* md_value)
: grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_OAUTH2,
GRPC_SECURITY_NONE),
key_(grpc_core::Slice::FromCopiedString(md_key)),
- value_(grpc_core::Slice::FromCopiedString(md_value)),
- is_async_(is_async) {}
+ value_(grpc_core::Slice::FromCopiedString(md_value)) {}
- bool get_request_metadata(grpc_polling_entity* pollent,
- grpc_auth_metadata_context context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata,
- grpc_error_handle* error) override;
-
- void cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_error_handle error) override;
+ grpc_core::ArenaPromise>
+ GetRequestMetadata(grpc_core::ClientInitialMetadata initial_metadata,
+ const GetRequestMetadataArgs* args) override;
std::string debug_string() override { return "MD only Test Credentials"; };
@@ -88,7 +80,6 @@ class grpc_md_only_test_credentials : public grpc_call_credentials {
grpc_core::Slice key_;
grpc_core::Slice value_;
- bool is_async_;
};
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/iam/iam_credentials.cc b/src/core/lib/security/credentials/iam/iam_credentials.cc
index d4d8c43495c..f010e51210e 100644
--- a/src/core/lib/security/credentials/iam/iam_credentials.cc
+++ b/src/core/lib/security/credentials/iam/iam_credentials.cc
@@ -28,27 +28,22 @@
#include
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/promise/promise.h"
#include "src/core/lib/surface/api_trace.h"
-bool grpc_google_iam_credentials::get_request_metadata(
- grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context /*context*/,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* /*on_request_metadata*/, grpc_error_handle* /*error*/) {
+grpc_core::ArenaPromise>
+grpc_google_iam_credentials::GetRequestMetadata(
+ grpc_core::ClientInitialMetadata initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs*) {
if (token_.has_value()) {
- md_array->emplace_back(grpc_core::Slice::FromStaticString(
- GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY),
- token_->Ref());
+ initial_metadata->Append(
+ GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token_->Ref(),
+ [](absl::string_view, const grpc_core::Slice&) { abort(); });
}
- md_array->emplace_back(grpc_core::Slice::FromStaticString(
- GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY),
- authority_selector_.Ref());
- return true;
-}
-
-void grpc_google_iam_credentials::cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* /*md_array*/,
- grpc_error_handle error) {
- GRPC_ERROR_UNREF(error);
+ initial_metadata->Append(
+ GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector_.Ref(),
+ [](absl::string_view, const grpc_core::Slice&) { abort(); });
+ return grpc_core::Immediate(std::move(initial_metadata));
}
grpc_google_iam_credentials::grpc_google_iam_credentials(
diff --git a/src/core/lib/security/credentials/iam/iam_credentials.h b/src/core/lib/security/credentials/iam/iam_credentials.h
index 6f6d1fa73ed..2724ad80c7a 100644
--- a/src/core/lib/security/credentials/iam/iam_credentials.h
+++ b/src/core/lib/security/credentials/iam/iam_credentials.h
@@ -30,15 +30,10 @@ class grpc_google_iam_credentials : public grpc_call_credentials {
grpc_google_iam_credentials(const char* token,
const char* authority_selector);
- bool get_request_metadata(grpc_polling_entity* pollent,
- grpc_auth_metadata_context context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata,
- grpc_error_handle* error) override;
-
- void cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_error_handle error) override;
+ grpc_core::ArenaPromise>
+ GetRequestMetadata(grpc_core::ClientInitialMetadata initial_metadata,
+ const GetRequestMetadataArgs* args) override;
+
std::string debug_string() override { return debug_string_; }
private:
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.cc b/src/core/lib/security/credentials/jwt/jwt_credentials.cc
index 4e7e9005f6f..8b3e76eeaa2 100644
--- a/src/core/lib/security/credentials/jwt/jwt_credentials.cc
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.cc
@@ -34,6 +34,8 @@
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/promise/promise.h"
+#include "src/core/lib/security/credentials/call_creds_util.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/transport/error_utils.h"
@@ -47,22 +49,21 @@ grpc_service_account_jwt_access_credentials::
gpr_mu_destroy(&cache_mu_);
}
-bool grpc_service_account_jwt_access_credentials::get_request_metadata(
- grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* /*on_request_metadata*/, grpc_error_handle* error) {
+grpc_core::ArenaPromise>
+grpc_service_account_jwt_access_credentials::GetRequestMetadata(
+ grpc_core::ClientInitialMetadata initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs* args) {
gpr_timespec refresh_threshold = gpr_time_from_seconds(
GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
// Remove service name from service_url to follow the audience format
// dictated in https://google.aip.dev/auth/4111.
- absl::StatusOr uri =
- grpc_core::RemoveServiceNameFromJwtUri(context.service_url);
+ absl::StatusOr uri = grpc_core::RemoveServiceNameFromJwtUri(
+ grpc_core::MakeJwtServiceUrl(initial_metadata, args));
if (!uri.ok()) {
- *error = absl_status_to_grpc_error(uri.status());
- return true;
+ return grpc_core::Immediate(uri.status());
}
- /* See if we can return a cached jwt. */
+ // See if we can return a cached jwt.
absl::optional jwt_value;
{
gpr_mu_lock(&cache_mu_);
@@ -77,7 +78,7 @@ bool grpc_service_account_jwt_access_credentials::get_request_metadata(
if (!jwt_value.has_value()) {
char* jwt = nullptr;
- /* Generate a new jwt. */
+ // Generate a new jwt.
gpr_mu_lock(&cache_mu_);
cached_.reset();
jwt = grpc_jwt_encode_and_sign(&key_, uri->c_str(), jwt_lifetime_, nullptr);
@@ -91,20 +92,15 @@ bool grpc_service_account_jwt_access_credentials::get_request_metadata(
gpr_mu_unlock(&cache_mu_);
}
- if (jwt_value.has_value()) {
- md_array->emplace_back(
- grpc_core::Slice::FromStaticString(GRPC_AUTHORIZATION_METADATA_KEY),
- std::move(*jwt_value));
- } else {
- *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT.");
+ if (!jwt_value.has_value()) {
+ return grpc_core::Immediate(
+ absl::UnauthenticatedError("Could not generate JWT."));
}
- return true;
-}
-void grpc_service_account_jwt_access_credentials::cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* /*md_array*/,
- grpc_error_handle error) {
- GRPC_ERROR_UNREF(error);
+ initial_metadata->Append(
+ GRPC_AUTHORIZATION_METADATA_KEY, std::move(*jwt_value),
+ [](absl::string_view, const grpc_core::Slice&) { abort(); });
+ return grpc_core::Immediate(std::move(initial_metadata));
}
grpc_service_account_jwt_access_credentials::
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.h b/src/core/lib/security/credentials/jwt/jwt_credentials.h
index 1fc1d42f730..e2df0040f29 100644
--- a/src/core/lib/security/credentials/jwt/jwt_credentials.h
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.h
@@ -38,15 +38,9 @@ class grpc_service_account_jwt_access_credentials
gpr_timespec token_lifetime);
~grpc_service_account_jwt_access_credentials() override;
- bool get_request_metadata(grpc_polling_entity* pollent,
- grpc_auth_metadata_context context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata,
- grpc_error_handle* error) override;
-
- void cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_error_handle error) override;
+ grpc_core::ArenaPromise>
+ GetRequestMetadata(grpc_core::ClientInitialMetadata initial_metadata,
+ const GetRequestMetadataArgs* args) override;
const gpr_timespec& jwt_lifetime() const { return jwt_lifetime_; }
const grpc_auth_json_key& key() const { return key_; }
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc b/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
index 1faaa56d3a0..77a76130e94 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
@@ -22,7 +22,10 @@
#include
+#include
+
#include "absl/container/inlined_vector.h"
+#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
@@ -35,14 +38,18 @@
#include
#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gprpp/capture.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/http/httpcli_ssl_credentials.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/json/json.h"
+#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/util/json_util.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/transport/error_utils.h"
+#include "src/core/lib/transport/transport.h"
#include "src/core/lib/uri/uri_parser.h"
using grpc_core::Json;
@@ -252,34 +259,33 @@ void grpc_oauth2_token_fetcher_credentials::on_http_response(
gpr_mu_unlock(&mu_);
// Invoke callbacks for all pending requests.
while (pending_request != nullptr) {
- grpc_error_handle new_error = GRPC_ERROR_NONE;
if (status == GRPC_CREDENTIALS_OK) {
- pending_request->md_array->emplace_back(
- grpc_core::Slice::FromStaticString(GRPC_AUTHORIZATION_METADATA_KEY),
- access_token_value->Ref());
+ pending_request->md->Append(
+ GRPC_AUTHORIZATION_METADATA_KEY, access_token_value->Ref(),
+ [](absl::string_view, const grpc_core::Slice&) { abort(); });
+ pending_request->result = std::move(pending_request->md);
} else {
- new_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+ auto err = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Error occurred when fetching oauth2 token.", &error, 1);
+ pending_request->result = grpc_error_to_absl_status(err);
+ GRPC_ERROR_UNREF(err);
}
- grpc_core::ExecCtx::Run(DEBUG_LOCATION,
- pending_request->on_request_metadata, new_error);
+ pending_request->done.store(true, std::memory_order_release);
+ pending_request->waker.Wakeup();
grpc_polling_entity_del_from_pollset_set(
pending_request->pollent, grpc_polling_entity_pollset_set(&pollent_));
grpc_oauth2_pending_get_request_metadata* prev = pending_request;
pending_request = pending_request->next;
- gpr_free(prev);
+ prev->Unref();
}
- Unref();
delete r;
}
-bool grpc_oauth2_token_fetcher_credentials::get_request_metadata(
- grpc_polling_entity* pollent, grpc_auth_metadata_context /*context*/,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata, grpc_error_handle* /*error*/) {
+grpc_core::ArenaPromise>
+grpc_oauth2_token_fetcher_credentials::GetRequestMetadata(
+ grpc_core::ClientInitialMetadata initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs*) {
// Check if we can use the cached token.
- grpc_core::Duration refresh_threshold =
- grpc_core::Duration::Seconds(GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS);
absl::optional cached_access_token_value;
gpr_mu_lock(&mu_);
if (access_token_value_.has_value() &&
@@ -291,23 +297,24 @@ bool grpc_oauth2_token_fetcher_credentials::get_request_metadata(
}
if (cached_access_token_value.has_value()) {
gpr_mu_unlock(&mu_);
- md_array->emplace_back(
- grpc_core::Slice::FromStaticString(GRPC_AUTHORIZATION_METADATA_KEY),
- std::move(*cached_access_token_value));
- return true;
+ initial_metadata->Append(
+ GRPC_AUTHORIZATION_METADATA_KEY, std::move(*cached_access_token_value),
+ [](absl::string_view, const grpc_core::Slice&) { abort(); });
+ return grpc_core::Immediate(std::move(initial_metadata));
}
// Couldn't get the token from the cache.
// Add request to pending_requests_ and start a new fetch if needed.
- grpc_oauth2_pending_get_request_metadata* pending_request =
- static_cast(
- gpr_malloc(sizeof(*pending_request)));
- pending_request->md_array = md_array;
- pending_request->on_request_metadata = on_request_metadata;
- pending_request->pollent = pollent;
+ grpc_core::Duration refresh_threshold =
+ grpc_core::Duration::Seconds(GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS);
+ auto pending_request =
+ grpc_core::MakeRefCounted();
+ pending_request->pollent = grpc_core::GetContext();
+ pending_request->waker = grpc_core::Activity::current()->MakeNonOwningWaker();
grpc_polling_entity_add_to_pollset_set(
- pollent, grpc_polling_entity_pollset_set(&pollent_));
+ pending_request->pollent, grpc_polling_entity_pollset_set(&pollent_));
pending_request->next = pending_requests_;
- pending_requests_ = pending_request;
+ pending_request->md = std::move(initial_metadata);
+ pending_requests_ = pending_request->Ref().release();
bool start_fetch = false;
if (!token_fetch_pending_) {
token_fetch_pending_ = true;
@@ -315,39 +322,18 @@ bool grpc_oauth2_token_fetcher_credentials::get_request_metadata(
}
gpr_mu_unlock(&mu_);
if (start_fetch) {
- Ref().release();
- fetch_oauth2(new grpc_credentials_metadata_request(this->Ref()), &pollent_,
+ fetch_oauth2(new grpc_credentials_metadata_request(Ref()), &pollent_,
on_oauth2_token_fetcher_http_response,
grpc_core::ExecCtx::Get()->Now() + refresh_threshold);
}
- return false;
-}
-
-void grpc_oauth2_token_fetcher_credentials::cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* md_array, grpc_error_handle error) {
- gpr_mu_lock(&mu_);
- grpc_oauth2_pending_get_request_metadata* prev = nullptr;
- grpc_oauth2_pending_get_request_metadata* pending_request = pending_requests_;
- while (pending_request != nullptr) {
- if (pending_request->md_array == md_array) {
- // Remove matching pending request from the list.
- if (prev != nullptr) {
- prev->next = pending_request->next;
- } else {
- pending_requests_ = pending_request->next;
- }
- // Invoke the callback immediately with an error.
- grpc_core::ExecCtx::Run(DEBUG_LOCATION,
- pending_request->on_request_metadata,
- GRPC_ERROR_REF(error));
- gpr_free(pending_request);
- break;
- }
- prev = pending_request;
- pending_request = pending_request->next;
- }
- gpr_mu_unlock(&mu_);
- GRPC_ERROR_UNREF(error);
+ return
+ [pending_request]()
+ -> grpc_core::Poll> {
+ if (!pending_request->done.load(std::memory_order_acquire)) {
+ return grpc_core::Pending{};
+ }
+ return std::move(pending_request->result);
+ };
}
grpc_oauth2_token_fetcher_credentials::grpc_oauth2_token_fetcher_credentials()
@@ -710,20 +696,14 @@ grpc_call_credentials* grpc_sts_credentials_create(
// Oauth2 Access Token credentials.
//
-bool grpc_access_token_credentials::get_request_metadata(
- grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context /*context*/,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* /*on_request_metadata*/, grpc_error_handle* /*error*/) {
- md_array->emplace_back(
- grpc_core::Slice::FromStaticString(GRPC_AUTHORIZATION_METADATA_KEY),
- access_token_value_.Ref());
- return true;
-}
-
-void grpc_access_token_credentials::cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* /*md_array*/,
- grpc_error_handle error) {
- GRPC_ERROR_UNREF(error);
+grpc_core::ArenaPromise>
+grpc_access_token_credentials::GetRequestMetadata(
+ grpc_core::ClientInitialMetadata initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs*) {
+ initial_metadata->Append(
+ GRPC_AUTHORIZATION_METADATA_KEY, access_token_value_.Ref(),
+ [](absl::string_view, const grpc_core::Slice&) { abort(); });
+ return grpc_core::Immediate(std::move(initial_metadata));
}
grpc_access_token_credentials::grpc_access_token_credentials(
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
index 5faf26b6a84..30fc30899bb 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
@@ -25,6 +25,7 @@
#include
+#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/http/httpcli.h"
#include "src/core/lib/json/json.h"
#include "src/core/lib/security/credentials/credentials.h"
@@ -73,11 +74,14 @@ struct grpc_credentials_metadata_request {
grpc_http_response response;
};
-struct grpc_oauth2_pending_get_request_metadata {
- grpc_core::CredentialsMetadataArray* md_array;
- grpc_closure* on_request_metadata;
+struct grpc_oauth2_pending_get_request_metadata
+ : public grpc_core::RefCounted {
+ std::atomic done{false};
+ grpc_core::Waker waker;
grpc_polling_entity* pollent;
+ grpc_core::ClientInitialMetadata md;
struct grpc_oauth2_pending_get_request_metadata* next;
+ absl::StatusOr result;
};
// -- Oauth2 Token Fetcher credentials --
@@ -90,15 +94,9 @@ class grpc_oauth2_token_fetcher_credentials : public grpc_call_credentials {
grpc_oauth2_token_fetcher_credentials();
~grpc_oauth2_token_fetcher_credentials() override;
- bool get_request_metadata(grpc_polling_entity* pollent,
- grpc_auth_metadata_context context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata,
- grpc_error_handle* error) override;
-
- void cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_error_handle error) override;
+ grpc_core::ArenaPromise>
+ GetRequestMetadata(grpc_core::ClientInitialMetadata initial_metadata,
+ const GetRequestMetadataArgs* args) override;
void on_http_response(grpc_credentials_metadata_request* r,
grpc_error_handle error);
@@ -154,15 +152,9 @@ class grpc_access_token_credentials final : public grpc_call_credentials {
public:
explicit grpc_access_token_credentials(const char* access_token);
- bool get_request_metadata(grpc_polling_entity* pollent,
- grpc_auth_metadata_context context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata,
- grpc_error_handle* error) override;
-
- void cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_error_handle error) override;
+ grpc_core::ArenaPromise>
+ GetRequestMetadata(grpc_core::ClientInitialMetadata initial_metadata,
+ const GetRequestMetadataArgs* args) override;
std::string debug_string() override;
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.cc b/src/core/lib/security/credentials/plugin/plugin_credentials.cc
index a627dae6cd9..2414d322951 100644
--- a/src/core/lib/security/credentials/plugin/plugin_credentials.cc
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.cc
@@ -22,6 +22,8 @@
#include
+#include
+
#include "absl/strings/str_cat.h"
#include
@@ -30,6 +32,8 @@
#include
#include "src/core/lib/gprpp/memory.h"
+#include "src/core/lib/promise/promise.h"
+#include "src/core/lib/security/credentials/plugin/plugin_credentials.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/surface/api_trace.h"
@@ -38,7 +42,6 @@
grpc_core::TraceFlag grpc_plugin_credentials_trace(false, "plugin_credentials");
grpc_plugin_credentials::~grpc_plugin_credentials() {
- gpr_mu_destroy(&mu_);
if (plugin_.state != nullptr && plugin_.destroy != nullptr) {
plugin_.destroy(plugin_.state);
}
@@ -57,38 +60,12 @@ std::string grpc_plugin_credentials::debug_string() {
return debug_str;
}
-void grpc_plugin_credentials::pending_request_remove_locked(
- pending_request* pending_request) {
- if (pending_request->prev == nullptr) {
- pending_requests_ = pending_request->next;
- } else {
- pending_request->prev->next = pending_request->next;
- }
- if (pending_request->next != nullptr) {
- pending_request->next->prev = pending_request->prev;
- }
-}
-
-// Checks if the request has been cancelled.
-// If not, removes it from the pending list, so that it cannot be
-// cancelled out from under us.
-// When this returns, r->cancelled indicates whether the request was
-// cancelled before completion.
-void grpc_plugin_credentials::pending_request_complete(pending_request* r) {
- GPR_DEBUG_ASSERT(r->creds == this);
- gpr_mu_lock(&mu_);
- if (!r->cancelled) pending_request_remove_locked(r);
- gpr_mu_unlock(&mu_);
- // Ref to credentials not needed anymore.
- Unref();
-}
-
-static grpc_error_handle process_plugin_result(
- grpc_plugin_credentials::pending_request* r, const grpc_metadata* md,
- size_t num_md, grpc_status_code status, const char* error_details) {
- grpc_error_handle error = GRPC_ERROR_NONE;
+absl::StatusOr
+grpc_plugin_credentials::PendingRequest::ProcessPluginResult(
+ const grpc_metadata* md, size_t num_md, grpc_status_code status,
+ const char* error_details) {
if (status != GRPC_STATUS_OK) {
- error = GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
+ return absl::UnavailableError(absl::StrCat(
"Getting metadata from plugin failed with error: ", error_details));
} else {
bool seen_illegal_header = false;
@@ -107,154 +84,120 @@ static grpc_error_handle process_plugin_result(
}
}
if (seen_illegal_header) {
- error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Illegal metadata");
+ return absl::UnavailableError("Illegal metadata");
} else {
+ absl::Status error;
for (size_t i = 0; i < num_md; ++i) {
- r->md_array->emplace_back(
- grpc_core::Slice(grpc_slice_ref_internal(md[i].key)),
- grpc_core::Slice(grpc_slice_ref_internal(md[i].value)));
+ md_->Append(
+ grpc_core::StringViewFromSlice(md[i].key),
+ grpc_core::Slice(grpc_slice_ref_internal(md[i].value)),
+ [&error](absl::string_view message, const grpc_core::Slice&) {
+ error = absl::UnavailableError(message);
+ });
}
+ if (!error.ok()) return std::move(error);
+ return grpc_core::ClientInitialMetadata(std::move(md_));
}
}
- return error;
}
-static void plugin_md_request_metadata_ready(void* request,
- const grpc_metadata* md,
- size_t num_md,
- grpc_status_code status,
- const char* error_details) {
+grpc_core::Poll>
+grpc_plugin_credentials::PendingRequest::PollAsyncResult() {
+ if (!ready_.load(std::memory_order_acquire)) {
+ return grpc_core::Pending{};
+ }
+ return ProcessPluginResult(metadata_.data(), metadata_.size(), status_,
+ error_details_.c_str());
+}
+
+void grpc_plugin_credentials::PendingRequest::RequestMetadataReady(
+ void* request, const grpc_metadata* md, size_t num_md,
+ grpc_status_code status, const char* error_details) {
/* called from application code */
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
grpc_core::ExecCtx exec_ctx(GRPC_EXEC_CTX_FLAG_IS_FINISHED |
GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP);
- grpc_plugin_credentials::pending_request* r =
- static_cast(request);
+ grpc_core::RefCountedPtr r(
+ static_cast(request));
if (GRPC_TRACE_FLAG_ENABLED(grpc_plugin_credentials_trace)) {
gpr_log(GPR_INFO,
"plugin_credentials[%p]: request %p: plugin returned "
"asynchronously",
- r->creds, r);
+ r->creds(), r.get());
}
- // Remove request from pending list if not previously cancelled.
- r->creds->pending_request_complete(r);
- // If it has not been cancelled, process it.
- if (!r->cancelled) {
- grpc_error_handle error =
- process_plugin_result(r, md, num_md, status, error_details);
- grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_request_metadata, error);
- } else if (GRPC_TRACE_FLAG_ENABLED(grpc_plugin_credentials_trace)) {
- gpr_log(GPR_INFO,
- "plugin_credentials[%p]: request %p: plugin was previously "
- "cancelled",
- r->creds, r);
+ for (size_t i = 0; i < num_md; ++i) {
+ grpc_metadata p;
+ p.key = grpc_slice_ref_internal(md[i].key);
+ p.value = grpc_slice_ref_internal(md[i].value);
+ r->metadata_.push_back(p);
}
- gpr_free(r);
+ r->error_details_ = error_details == nullptr ? "" : error_details;
+ r->status_ = status;
+ r->ready_.store(true, std::memory_order_release);
+ r->waker_.Wakeup();
}
-bool grpc_plugin_credentials::get_request_metadata(
- grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata, grpc_error_handle* error) {
- bool retval = true; // Synchronous return.
- if (plugin_.get_metadata != nullptr) {
- // Create pending_request object.
- pending_request* request = grpc_core::Zalloc();
- request->creds = this;
- request->md_array = md_array;
- request->on_request_metadata = on_request_metadata;
- // Add it to the pending list.
- gpr_mu_lock(&mu_);
- if (pending_requests_ != nullptr) {
- pending_requests_->prev = request;
- }
- request->next = pending_requests_;
- pending_requests_ = request;
- gpr_mu_unlock(&mu_);
- // Invoke the plugin. The callback holds a ref to us.
- if (GRPC_TRACE_FLAG_ENABLED(grpc_plugin_credentials_trace)) {
- gpr_log(GPR_INFO, "plugin_credentials[%p]: request %p: invoking plugin",
- this, request);
- }
- Ref().release();
- grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX];
- size_t num_creds_md = 0;
- grpc_status_code status = GRPC_STATUS_OK;
- const char* error_details = nullptr;
- if (!plugin_.get_metadata(
- plugin_.state, context, plugin_md_request_metadata_ready, request,
- creds_md, &num_creds_md, &status, &error_details)) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_plugin_credentials_trace)) {
- gpr_log(GPR_INFO,
- "plugin_credentials[%p]: request %p: plugin will return "
- "asynchronously",
- this, request);
- }
- return false; // Asynchronous return.
- }
- // Returned synchronously.
- // Remove request from pending list if not previously cancelled.
- request->creds->pending_request_complete(request);
- // If the request was cancelled, the error will have been returned
- // asynchronously by plugin_cancel_get_request_metadata(), so return
- // false. Otherwise, process the result.
- if (request->cancelled) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_plugin_credentials_trace)) {
- gpr_log(GPR_INFO,
- "plugin_credentials[%p]: request %p was cancelled, error "
- "will be returned asynchronously",
- this, request);
- }
- retval = false;
- } else {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_plugin_credentials_trace)) {
- gpr_log(GPR_INFO,
- "plugin_credentials[%p]: request %p: plugin returned "
- "synchronously",
- this, request);
- }
- *error = process_plugin_result(request, creds_md, num_creds_md, status,
- error_details);
- }
- // Clean up.
- for (size_t i = 0; i < num_creds_md; ++i) {
- grpc_slice_unref_internal(creds_md[i].key);
- grpc_slice_unref_internal(creds_md[i].value);
- }
- gpr_free(const_cast(error_details));
- gpr_free(request);
+grpc_core::ArenaPromise>
+grpc_plugin_credentials::GetRequestMetadata(
+ grpc_core::ClientInitialMetadata initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs* args) {
+ if (plugin_.get_metadata == nullptr) {
+ return grpc_core::Immediate(std::move(initial_metadata));
}
- return retval;
-}
-void grpc_plugin_credentials::cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* md_array, grpc_error_handle error) {
- gpr_mu_lock(&mu_);
- for (pending_request* pending_request = pending_requests_;
- pending_request != nullptr; pending_request = pending_request->next) {
- if (pending_request->md_array == md_array) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_plugin_credentials_trace)) {
- gpr_log(GPR_INFO, "plugin_credentials[%p]: cancelling request %p", this,
- pending_request);
- }
- pending_request->cancelled = true;
- grpc_core::ExecCtx::Run(DEBUG_LOCATION,
- pending_request->on_request_metadata,
- GRPC_ERROR_REF(error));
- pending_request_remove_locked(pending_request);
- break;
+ // Create pending_request object.
+ auto request = grpc_core::MakeRefCounted(
+ Ref(), std::move(initial_metadata), args);
+ // Invoke the plugin. The callback holds a ref to us.
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_plugin_credentials_trace)) {
+ gpr_log(GPR_INFO, "plugin_credentials[%p]: request %p: invoking plugin",
+ this, request.get());
+ }
+ grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX];
+ size_t num_creds_md = 0;
+ grpc_status_code status = GRPC_STATUS_OK;
+ const char* error_details = nullptr;
+ // Add an extra ref to the request object for the async callback.
+ // If the request completes synchronously, we'll drop this later.
+ // If the request completes asynchronously, it will own a ref to the request
+ // object (which we release from our ownership below).
+ auto child_request = request->Ref();
+ if (!plugin_.get_metadata(plugin_.state, request->context(),
+ PendingRequest::RequestMetadataReady,
+ child_request.get(), creds_md, &num_creds_md,
+ &status, &error_details)) {
+ child_request.release();
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_plugin_credentials_trace)) {
+ gpr_log(GPR_INFO,
+ "plugin_credentials[%p]: request %p: plugin will return "
+ "asynchronously",
+ this, request.get());
}
+ return [request] { return request->PollAsyncResult(); };
+ }
+ // Synchronous return.
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_plugin_credentials_trace)) {
+ gpr_log(GPR_INFO,
+ "plugin_credentials[%p]: request %p: plugin returned "
+ "synchronously",
+ this, request.get());
+ }
+ auto result = request->ProcessPluginResult(creds_md, num_creds_md, status,
+ error_details);
+ // Clean up.
+ for (size_t i = 0; i < num_creds_md; ++i) {
+ grpc_slice_unref_internal(creds_md[i].key);
+ grpc_slice_unref_internal(creds_md[i].value);
}
- gpr_mu_unlock(&mu_);
- GRPC_ERROR_UNREF(error);
+ gpr_free(const_cast(error_details));
+
+ return grpc_core::Immediate(std::move(result));
}
grpc_plugin_credentials::grpc_plugin_credentials(
grpc_metadata_credentials_plugin plugin,
grpc_security_level min_security_level)
- : grpc_call_credentials(plugin.type, min_security_level), plugin_(plugin) {
- gpr_mu_init(&mu_);
-}
+ : grpc_call_credentials(plugin.type, min_security_level), plugin_(plugin) {}
grpc_call_credentials* grpc_metadata_credentials_create_from_plugin(
grpc_metadata_credentials_plugin plugin,
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.h b/src/core/lib/security/credentials/plugin/plugin_credentials.h
index 869e817fc69..2ed2cd977cd 100644
--- a/src/core/lib/security/credentials/plugin/plugin_credentials.h
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.h
@@ -21,6 +21,7 @@
#include
+#include "src/core/lib/security/credentials/call_creds_util.h"
#include "src/core/lib/security/credentials/credentials.h"
extern grpc_core::TraceFlag grpc_plugin_credentials_trace;
@@ -30,50 +31,69 @@ extern grpc_core::TraceFlag grpc_plugin_credentials_trace;
// -Wmismatched-tags.
struct grpc_plugin_credentials final : public grpc_call_credentials {
public:
- struct pending_request {
- bool cancelled;
- struct grpc_plugin_credentials* creds;
- grpc_core::CredentialsMetadataArray* md_array;
- grpc_closure* on_request_metadata;
- struct pending_request* prev;
- struct pending_request* next;
- };
-
explicit grpc_plugin_credentials(grpc_metadata_credentials_plugin plugin,
grpc_security_level min_security_level);
~grpc_plugin_credentials() override;
- bool get_request_metadata(grpc_polling_entity* pollent,
- grpc_auth_metadata_context context,
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_closure* on_request_metadata,
- grpc_error_handle* error) override;
-
- void cancel_get_request_metadata(
- grpc_core::CredentialsMetadataArray* md_array,
- grpc_error_handle error) override;
-
- // Checks if the request has been cancelled.
- // If not, removes it from the pending list, so that it cannot be
- // cancelled out from under us.
- // When this returns, r->cancelled indicates whether the request was
- // cancelled before completion.
- void pending_request_complete(pending_request* r);
+ grpc_core::ArenaPromise>
+ GetRequestMetadata(grpc_core::ClientInitialMetadata initial_metadata,
+ const GetRequestMetadataArgs* args) override;
std::string debug_string() override;
private:
+ class PendingRequest : public grpc_core::RefCounted {
+ public:
+ PendingRequest(grpc_core::RefCountedPtr creds,
+ grpc_core::ClientInitialMetadata initial_metadata,
+ const grpc_call_credentials::GetRequestMetadataArgs* args)
+ : call_creds_(std::move(creds)),
+ context_(
+ grpc_core::MakePluginAuthMetadataContext(initial_metadata, args)),
+ md_(std::move(initial_metadata)) {}
+
+ ~PendingRequest() override {
+ grpc_auth_metadata_context_reset(&context_);
+ for (size_t i = 0; i < metadata_.size(); i++) {
+ grpc_slice_unref_internal(metadata_[i].key);
+ grpc_slice_unref_internal(metadata_[i].value);
+ }
+ }
+
+ absl::StatusOr ProcessPluginResult(
+ const grpc_metadata* md, size_t num_md, grpc_status_code status,
+ const char* error_details);
+
+ grpc_core::Poll>
+ PollAsyncResult();
+
+ static void RequestMetadataReady(void* request, const grpc_metadata* md,
+ size_t num_md, grpc_status_code status,
+ const char* error_details);
+
+ grpc_auth_metadata_context context() const { return context_; }
+ grpc_plugin_credentials* creds() const { return call_creds_.get(); }
+
+ private:
+ std::atomic ready_{false};
+ grpc_core::Waker waker_{
+ grpc_core::Activity::current()->MakeNonOwningWaker()};
+ grpc_core::RefCountedPtr call_creds_;
+ grpc_auth_metadata_context context_;
+ grpc_core::ClientInitialMetadata md_;
+ // final status
+ absl::InlinedVector metadata_;
+ std::string error_details_;
+ grpc_status_code status_;
+ };
+
int cmp_impl(const grpc_call_credentials* other) const override {
// TODO(yashykt): Check if we can do something better here
return grpc_core::QsortCompare(
static_cast(this), other);
}
- void pending_request_remove_locked(pending_request* pending_request);
-
grpc_metadata_credentials_plugin plugin_;
- gpr_mu mu_;
- pending_request* pending_requests_ = nullptr;
};
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_PLUGIN_CREDENTIALS_H */
diff --git a/src/core/lib/security/security_connector/alts/alts_security_connector.cc b/src/core/lib/security/security_connector/alts/alts_security_connector.cc
index 442dfe6cf94..9590698165a 100644
--- a/src/core/lib/security/security_connector/alts/alts_security_connector.cc
+++ b/src/core/lib/security/security_connector/alts/alts_security_connector.cc
@@ -29,6 +29,7 @@
#include
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/credentials/alts/alts_credentials.h"
#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/slice/slice_internal.h"
@@ -116,20 +117,13 @@ class grpc_alts_channel_security_connector final
return strcmp(target_name_, other->target_name_);
}
- bool check_call_host(absl::string_view host,
- grpc_auth_context* /*auth_context*/,
- grpc_closure* /*on_call_host_checked*/,
- grpc_error_handle* error) override {
+ grpc_core::ArenaPromise CheckCallHost(
+ absl::string_view host, grpc_auth_context*) override {
if (host.empty() || host != target_name_) {
- *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "ALTS call host does not match target name");
+ return grpc_core::Immediate(absl::UnauthenticatedError(
+ "ALTS call host does not match target name"));
}
- return true;
- }
-
- void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/,
- grpc_error_handle error) override {
- GRPC_ERROR_UNREF(error);
+ return grpc_core::ImmediateOkStatus();
}
private:
diff --git a/src/core/lib/security/security_connector/fake/fake_security_connector.cc b/src/core/lib/security/security_connector/fake/fake_security_connector.cc
index 375cac46972..ef3eaaf6947 100644
--- a/src/core/lib/security/security_connector/fake/fake_security_connector.cc
+++ b/src/core/lib/security/security_connector/fake/fake_security_connector.cc
@@ -34,6 +34,7 @@
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/credentials/fake/fake_credentials.h"
@@ -105,10 +106,8 @@ class grpc_fake_channel_security_connector final
tsi_create_fake_handshaker(/*is_client=*/true), this, args));
}
- bool check_call_host(absl::string_view host,
- grpc_auth_context* /*auth_context*/,
- grpc_closure* /*on_call_host_checked*/,
- grpc_error_handle* /*error*/) override {
+ grpc_core::ArenaPromise CheckCallHost(
+ absl::string_view host, grpc_auth_context*) override {
absl::string_view authority_hostname;
absl::string_view authority_ignored_port;
absl::string_view target_hostname;
@@ -134,12 +133,7 @@ class grpc_fake_channel_security_connector final
target_);
abort();
}
- return true;
- }
-
- void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/,
- grpc_error_handle error) override {
- GRPC_ERROR_UNREF(error);
+ return grpc_core::ImmediateOkStatus();
}
char* target() const { return target_; }
diff --git a/src/core/lib/security/security_connector/insecure/insecure_security_connector.cc b/src/core/lib/security/security_connector/insecure/insecure_security_connector.cc
index 3118092c0a3..4fc0df7728f 100644
--- a/src/core/lib/security/security_connector/insecure/insecure_security_connector.cc
+++ b/src/core/lib/security/security_connector/insecure/insecure_security_connector.cc
@@ -21,6 +21,7 @@
#include "src/core/lib/security/security_connector/insecure/insecure_security_connector.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/tsi/local_transport_security.h"
@@ -48,18 +49,9 @@ RefCountedPtr TestOnlyMakeInsecureAuthContext() {
return MakeAuthContext();
}
-// check_call_host and cancel_check_call_host are no-ops since we want to
-// provide an insecure channel.
-bool InsecureChannelSecurityConnector::check_call_host(
- absl::string_view /*host*/, grpc_auth_context* /*auth_context*/,
- grpc_closure* /*on_call_host_checked*/, grpc_error_handle* error) {
- *error = GRPC_ERROR_NONE;
- return true;
-}
-
-void InsecureChannelSecurityConnector::cancel_check_call_host(
- grpc_closure* /*on_call_host_checked*/, grpc_error_handle error) {
- GRPC_ERROR_UNREF(error);
+ArenaPromise InsecureChannelSecurityConnector::CheckCallHost(
+ absl::string_view, grpc_auth_context*) {
+ return ImmediateOkStatus();
}
// add_handshakers should have been a no-op but we need to add a minimalist
diff --git a/src/core/lib/security/security_connector/insecure/insecure_security_connector.h b/src/core/lib/security/security_connector/insecure/insecure_security_connector.h
index ef888079efd..2b716bcb0fc 100644
--- a/src/core/lib/security/security_connector/insecure/insecure_security_connector.h
+++ b/src/core/lib/security/security_connector/insecure/insecure_security_connector.h
@@ -41,16 +41,11 @@ class InsecureChannelSecurityConnector
InsecureChannelSecurityConnector(
RefCountedPtr channel_creds,
RefCountedPtr request_metadata_creds)
- : grpc_channel_security_connector(/* url_scheme */ nullptr,
- std::move(channel_creds),
+ : grpc_channel_security_connector("", std::move(channel_creds),
std::move(request_metadata_creds)) {}
- bool check_call_host(absl::string_view host, grpc_auth_context* auth_context,
- grpc_closure* on_call_host_checked,
- grpc_error_handle* error) override;
-
- void cancel_check_call_host(grpc_closure* on_call_host_checked,
- grpc_error_handle error) override;
+ ArenaPromise CheckCallHost(
+ absl::string_view host, grpc_auth_context* auth_context) override;
void add_handshakers(const grpc_channel_args* args,
grpc_pollset_set* /* interested_parties */,
@@ -72,7 +67,7 @@ class InsecureServerSecurityConnector : public grpc_server_security_connector {
public:
explicit InsecureServerSecurityConnector(
RefCountedPtr server_creds)
- : grpc_server_security_connector(nullptr /* url_scheme */,
+ : grpc_server_security_connector("" /* url_scheme */,
std::move(server_creds)) {}
void add_handshakers(const grpc_channel_args* args,
diff --git a/src/core/lib/security/security_connector/local/local_security_connector.cc b/src/core/lib/security/security_connector/local/local_security_connector.cc
index 23296f7782e..952189868fe 100644
--- a/src/core/lib/security/security_connector/local/local_security_connector.cc
+++ b/src/core/lib/security/security_connector/local/local_security_connector.cc
@@ -38,6 +38,7 @@
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/socket_utils.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
+#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/credentials/local/local_credentials.h"
#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/uri/uri_parser.h"
@@ -189,20 +190,13 @@ class grpc_local_channel_security_connector final
GRPC_ERROR_UNREF(error);
}
- bool check_call_host(absl::string_view host,
- grpc_auth_context* /*auth_context*/,
- grpc_closure* /*on_call_host_checked*/,
- grpc_error_handle* error) override {
+ grpc_core::ArenaPromise CheckCallHost(
+ absl::string_view host, grpc_auth_context*) override {
if (host.empty() || host != target_name_) {
- *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "local call host does not match target name");
+ return grpc_core::Immediate(absl::UnauthenticatedError(
+ "local call host does not match target name"));
}
- return true;
- }
-
- void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/,
- grpc_error_handle error) override {
- GRPC_ERROR_UNREF(error);
+ return grpc_core::ImmediateOkStatus();
}
const char* target_name() const { return target_name_; }
diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc
index d7f16cca386..aff35e97b96 100644
--- a/src/core/lib/security/security_connector/security_connector.cc
+++ b/src/core/lib/security/security_connector/security_connector.cc
@@ -37,7 +37,7 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_security_connector_refcount(
false, "security_connector_refcount");
grpc_server_security_connector::grpc_server_security_connector(
- const char* url_scheme,
+ absl::string_view url_scheme,
grpc_core::RefCountedPtr server_creds)
: grpc_security_connector(url_scheme),
server_creds_(std::move(server_creds)) {}
@@ -45,7 +45,7 @@ grpc_server_security_connector::grpc_server_security_connector(
grpc_server_security_connector::~grpc_server_security_connector() = default;
grpc_channel_security_connector::grpc_channel_security_connector(
- const char* url_scheme,
+ absl::string_view url_scheme,
grpc_core::RefCountedPtr channel_creds,
grpc_core::RefCountedPtr request_metadata_creds)
: grpc_security_connector(url_scheme),
diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h
index caccaf3481e..6c1add9d875 100644
--- a/src/core/lib/security/security_connector/security_connector.h
+++ b/src/core/lib/security/security_connector/security_connector.h
@@ -30,6 +30,7 @@
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/iomgr/tcp_server.h"
+#include "src/core/lib/promise/arena_promise.h"
#include "src/core/tsi/transport_security_interface.h"
extern grpc_core::DebugOnlyTraceFlag grpc_trace_security_connector_refcount;
@@ -51,7 +52,7 @@ typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status;
class grpc_security_connector
: public grpc_core::RefCounted {
public:
- explicit grpc_security_connector(const char* url_scheme)
+ explicit grpc_security_connector(absl::string_view url_scheme)
: grpc_core::RefCounted(
GRPC_TRACE_FLAG_ENABLED(grpc_trace_security_connector_refcount)
? "security_connector_refcount"
@@ -74,10 +75,10 @@ class grpc_security_connector
/* Compares two security connectors. */
virtual int cmp(const grpc_security_connector* other) const = 0;
- const char* url_scheme() const { return url_scheme_; }
+ absl::string_view url_scheme() const { return url_scheme_; }
private:
- const char* url_scheme_;
+ absl::string_view url_scheme_;
};
/* Util to encapsulate the connector in a channel arg. */
@@ -98,26 +99,16 @@ grpc_security_connector* grpc_security_connector_find_in_args(
class grpc_channel_security_connector : public grpc_security_connector {
public:
grpc_channel_security_connector(
- const char* url_scheme,
+ absl::string_view url_scheme,
grpc_core::RefCountedPtr channel_creds,
- grpc_core::RefCountedPtr request_metadata_creds
- /*,
- grpc_channel_args* channel_args = nullptr*/);
+ grpc_core::RefCountedPtr request_metadata_creds);
~grpc_channel_security_connector() override;
/// Checks that the host that will be set for a call is acceptable.
- /// Returns true if completed synchronously, in which case \a error will
- /// be set to indicate the result. Otherwise, \a on_call_host_checked
- /// will be invoked when complete.
- virtual bool check_call_host(absl::string_view host,
- grpc_auth_context* auth_context,
- grpc_closure* on_call_host_checked,
- grpc_error_handle* error) = 0;
- /// Cancels a pending asynchronous call to
- /// grpc_channel_security_connector_check_call_host() with
- /// \a on_call_host_checked as its callback.
- virtual void cancel_check_call_host(grpc_closure* on_call_host_checked,
- grpc_error_handle error) = 0;
+ /// Returns ok if the host is acceptable, otherwise returns an error.
+ virtual grpc_core::ArenaPromise CheckCallHost(
+ absl::string_view host, grpc_auth_context* auth_context) = 0;
+
/// Registers handshakers with \a handshake_mgr.
virtual void add_handshakers(const grpc_channel_args* args,
grpc_pollset_set* interested_parties,
@@ -160,7 +151,7 @@ class grpc_channel_security_connector : public grpc_security_connector {
class grpc_server_security_connector : public grpc_security_connector {
public:
grpc_server_security_connector(
- const char* url_scheme,
+ absl::string_view url_scheme,
grpc_core::RefCountedPtr server_creds);
~grpc_server_security_connector() override;
diff --git a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
index c8581490912..2f3c1942335 100644
--- a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
+++ b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
@@ -35,6 +35,7 @@
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/sync.h"
+#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/credentials/ssl/ssl_credentials.h"
@@ -185,17 +186,11 @@ class grpc_ssl_channel_security_connector final
return overridden_target_name_.compare(other->overridden_target_name_);
}
- bool check_call_host(absl::string_view host, grpc_auth_context* auth_context,
- grpc_closure* /*on_call_host_checked*/,
- grpc_error_handle* error) override {
- return grpc_ssl_check_call_host(host, target_name_.c_str(),
- overridden_target_name_.c_str(),
- auth_context, error);
- }
-
- void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/,
- grpc_error_handle error) override {
- GRPC_ERROR_UNREF(error);
+ grpc_core::ArenaPromise CheckCallHost(
+ absl::string_view host, grpc_auth_context* auth_context) override {
+ return grpc_core::Immediate(
+ SslCheckCallHost(host, target_name_.c_str(),
+ overridden_target_name_.c_str(), auth_context));
}
private:
diff --git a/src/core/lib/security/security_connector/ssl_utils.cc b/src/core/lib/security/security_connector/ssl_utils.cc
index 3b0a90533a0..07983c3b29b 100644
--- a/src/core/lib/security/security_connector/ssl_utils.cc
+++ b/src/core/lib/security/security_connector/ssl_utils.cc
@@ -165,11 +165,12 @@ void grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_ssl_pem_key_cert_pair* kp,
gpr_free(kp);
}
-bool grpc_ssl_check_call_host(absl::string_view host,
+namespace grpc_core {
+
+absl::Status SslCheckCallHost(absl::string_view host,
absl::string_view target_name,
absl::string_view overridden_target_name,
- grpc_auth_context* auth_context,
- grpc_error_handle* error) {
+ grpc_auth_context* auth_context) {
grpc_security_status status = GRPC_SECURITY_ERROR;
tsi_peer peer = grpc_shallow_peer_from_ssl_auth_context(auth_context);
if (grpc_ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK;
@@ -180,14 +181,17 @@ bool grpc_ssl_check_call_host(absl::string_view host,
status = GRPC_SECURITY_OK;
}
if (status != GRPC_SECURITY_OK) {
- *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "call host does not match SSL server name");
gpr_log(GPR_ERROR, "call host does not match SSL server name");
+ grpc_shallow_peer_destruct(&peer);
+ return absl::UnauthenticatedError(
+ "call host does not match SSL server name");
}
grpc_shallow_peer_destruct(&peer);
- return true;
+ return absl::OkStatus();
}
+} // namespace grpc_core
+
const char** grpc_fill_alpn_protocol_strings(size_t* num_alpn_protocols) {
GPR_ASSERT(num_alpn_protocols != nullptr);
*num_alpn_protocols = grpc_chttp2_num_alpn_versions();
diff --git a/src/core/lib/security/security_connector/ssl_utils.h b/src/core/lib/security/security_connector/ssl_utils.h
index d8ff8d84c52..cc0825dd58a 100644
--- a/src/core/lib/security/security_connector/ssl_utils.h
+++ b/src/core/lib/security/security_connector/ssl_utils.h
@@ -51,12 +51,15 @@ int grpc_ssl_cmp_target_name(absl::string_view target_name,
absl::string_view other_target_name,
absl::string_view overridden_target_name,
absl::string_view other_overridden_target_name);
+
+namespace grpc_core {
/* Check the host that will be set for a call is acceptable.*/
-bool grpc_ssl_check_call_host(absl::string_view host,
+absl::Status SslCheckCallHost(absl::string_view host,
absl::string_view target_name,
absl::string_view overridden_target_name,
- grpc_auth_context* auth_context,
- grpc_error_handle* error);
+ grpc_auth_context* auth_context);
+} // namespace grpc_core
+
/* Return HTTP2-compliant cipher suites that gRPC accepts by default. */
const char* grpc_get_ssl_cipher_suites(void);
diff --git a/src/core/lib/security/security_connector/tls/tls_security_connector.cc b/src/core/lib/security/security_connector/tls/tls_security_connector.cc
index 06ba7148429..5f5f7c8d5b3 100644
--- a/src/core/lib/security/security_connector/tls/tls_security_connector.cc
+++ b/src/core/lib/security/security_connector/tls/tls_security_connector.cc
@@ -34,6 +34,7 @@
#include
#include "src/core/lib/gprpp/host_port.h"
+#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/credentials/tls/tls_credentials.h"
#include "src/core/lib/security/security_connector/ssl_utils.h"
#include "src/core/lib/security/transport/security_handshaker.h"
@@ -408,20 +409,14 @@ int TlsChannelSecurityConnector::cmp(
return 0;
}
-bool TlsChannelSecurityConnector::check_call_host(
- absl::string_view host, grpc_auth_context* auth_context,
- grpc_closure* /*on_call_host_checked*/, grpc_error_handle* error) {
+ArenaPromise TlsChannelSecurityConnector::CheckCallHost(
+ absl::string_view host, grpc_auth_context* auth_context) {
if (options_->check_call_host()) {
- return grpc_ssl_check_call_host(host, target_name_.c_str(),
- overridden_target_name_.c_str(),
- auth_context, error);
+ return Immediate(SslCheckCallHost(host, target_name_.c_str(),
+ overridden_target_name_.c_str(),
+ auth_context));
}
- return true;
-}
-
-void TlsChannelSecurityConnector::cancel_check_call_host(
- grpc_closure* /*on_call_host_checked*/, grpc_error_handle error) {
- GRPC_ERROR_UNREF(error);
+ return ImmediateOkStatus();
}
void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::
diff --git a/src/core/lib/security/security_connector/tls/tls_security_connector.h b/src/core/lib/security/security_connector/tls/tls_security_connector.h
index 73b87254062..b42da8f8e88 100644
--- a/src/core/lib/security/security_connector/tls/tls_security_connector.h
+++ b/src/core/lib/security/security_connector/tls/tls_security_connector.h
@@ -67,12 +67,8 @@ class TlsChannelSecurityConnector final
int cmp(const grpc_security_connector* other_sc) const override;
- bool check_call_host(absl::string_view host, grpc_auth_context* auth_context,
- grpc_closure* on_call_host_checked,
- grpc_error_handle* error) override;
-
- void cancel_check_call_host(grpc_closure* on_call_host_checked,
- grpc_error_handle error) override;
+ ArenaPromise CheckCallHost(
+ absl::string_view host, grpc_auth_context* auth_context) override;
tsi_ssl_client_handshaker_factory* ClientHandshakerFactoryForTesting() {
MutexLock lock(&mu_);
diff --git a/src/core/lib/security/transport/auth_filters.h b/src/core/lib/security/transport/auth_filters.h
index 9608c1633a0..084e7125e70 100644
--- a/src/core/lib/security/transport/auth_filters.h
+++ b/src/core/lib/security/transport/auth_filters.h
@@ -24,14 +24,40 @@
#include
#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/channel/promise_based_filter.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/security_connector/security_connector.h"
+#include "src/core/lib/transport/transport.h"
extern const grpc_channel_filter grpc_client_auth_filter;
extern const grpc_channel_filter grpc_server_auth_filter;
-void grpc_auth_metadata_context_build(
- const char* url_scheme, const grpc_slice& call_host,
- const grpc_slice& call_method, grpc_auth_context* auth_context,
- grpc_auth_metadata_context* auth_md_context);
+namespace grpc_core {
+
+// Handles calling out to credentials to fill in metadata per call.
+class ClientAuthFilter final : public ChannelFilter {
+ public:
+ static absl::StatusOr Create(const grpc_channel_args* args,
+ ChannelFilter::Args);
+
+ // Construct a promise for one call.
+ ArenaPromise MakeCallPromise(
+ ClientInitialMetadata initial_metadata,
+ NextPromiseFactory next_promise_factory) override;
+
+ private:
+ ClientAuthFilter(
+ RefCountedPtr security_connector,
+ RefCountedPtr auth_context);
+
+ ArenaPromise> GetCallCredsMetadata(
+ ClientInitialMetadata initial_metadata);
+
+ // Contains refs to security connector and auth context.
+ grpc_call_credentials::GetRequestMetadataArgs args_;
+};
+
+} // namespace grpc_core
// Exposed for testing purposes only.
// Check if the channel's security level is higher or equal to
diff --git a/src/core/lib/security/transport/client_auth_filter.cc b/src/core/lib/security/transport/client_auth_filter.cc
index 0965dbef0f0..f4da0d63a8d 100644
--- a/src/core/lib/security/transport/client_auth_filter.cc
+++ b/src/core/lib/security/transport/client_auth_filter.cc
@@ -29,9 +29,12 @@
#include
#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/promise/promise.h"
+#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/security_connector/security_connector.h"
@@ -39,83 +42,10 @@
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/surface/call.h"
+#include "src/core/lib/transport/transport.h"
#define MAX_CREDENTIALS_METADATA_COUNT 4
-namespace {
-
-/* We can have a per-channel credentials. */
-struct channel_data {
- channel_data(grpc_channel_security_connector* security_connector,
- grpc_auth_context* auth_context)
- : security_connector(
- security_connector->Ref(DEBUG_LOCATION, "client_auth_filter")),
- auth_context(auth_context->Ref(DEBUG_LOCATION, "client_auth_filter")) {}
- ~channel_data() {
- security_connector.reset(DEBUG_LOCATION, "client_auth_filter");
- auth_context.reset(DEBUG_LOCATION, "client_auth_filter");
- }
-
- grpc_core::RefCountedPtr security_connector;
- grpc_core::RefCountedPtr auth_context;
-};
-
-/* We can have a per-call credentials. */
-struct call_data {
- call_data(grpc_call_element* elem, const grpc_call_element_args& args)
- : owning_call(args.call_stack), call_combiner(args.call_combiner) {
- host.Init();
- method.Init();
- md_array.Init();
- channel_data* chand = static_cast(elem->channel_data);
- GPR_ASSERT(args.context != nullptr);
- if (args.context[GRPC_CONTEXT_SECURITY].value == nullptr) {
- args.context[GRPC_CONTEXT_SECURITY].value =
- grpc_client_security_context_create(args.arena, /*creds=*/nullptr);
- args.context[GRPC_CONTEXT_SECURITY].destroy =
- grpc_client_security_context_destroy;
- }
- grpc_client_security_context* sec_ctx =
- static_cast(
- args.context[GRPC_CONTEXT_SECURITY].value);
- sec_ctx->auth_context.reset(DEBUG_LOCATION, "client_auth_filter");
- sec_ctx->auth_context =
- chand->auth_context->Ref(DEBUG_LOCATION, "client_auth_filter");
- }
-
- // This method is technically the dtor of this class. However, since
- // `get_request_metadata_cancel_closure` can run in parallel to
- // `destroy_call_elem`, we cannot call the dtor in them. Otherwise,
- // fields will be accessed after calling dtor, and msan correctly complains
- // that the memory is not initialized.
- void destroy() {
- md_array.Destroy();
- creds.reset();
- grpc_auth_metadata_context_reset(&auth_md_context);
- host.Destroy();
- method.Destroy();
- }
-
- grpc_call_stack* owning_call;
- grpc_core::CallCombiner* call_combiner;
- grpc_core::RefCountedPtr creds;
- grpc_core::ManualConstructor host;
- grpc_core::ManualConstructor method;
- /* pollset{_set} bound to this call; if we need to make external
- network requests, they should be done under a pollset added to this
- pollset_set so that work can progress when this call wants work to progress
- */
- grpc_polling_entity* pollent = nullptr;
- grpc_core::ManualConstructor md_array;
- grpc_auth_metadata_context auth_md_context =
- grpc_auth_metadata_context(); // Zero-initialize the C struct.
- grpc_closure async_result_closure;
- grpc_closure check_call_host_cancel_closure;
- grpc_closure get_request_metadata_cancel_closure;
-};
-
-} // namespace
-
void grpc_auth_metadata_context_copy(grpc_auth_metadata_context* from,
grpc_auth_metadata_context* to) {
grpc_auth_metadata_context_reset(to);
@@ -146,98 +76,6 @@ void grpc_auth_metadata_context_reset(
}
}
-static void add_error(grpc_error_handle* combined, grpc_error_handle error) {
- if (error == GRPC_ERROR_NONE) return;
- if (*combined == GRPC_ERROR_NONE) {
- *combined = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "Client auth metadata plugin error");
- }
- *combined = grpc_error_add_child(*combined, error);
-}
-
-static void on_credentials_metadata(void* arg, grpc_error_handle input_error) {
- grpc_transport_stream_op_batch* batch =
- static_cast(arg);
- grpc_call_element* elem =
- static_cast(batch->handler_private.extra_arg);
- call_data* calld = static_cast(elem->call_data);
- grpc_auth_metadata_context_reset(&calld->auth_md_context);
- grpc_error_handle error = GRPC_ERROR_REF(input_error);
- if (error == GRPC_ERROR_NONE) {
- GPR_ASSERT(calld->md_array->size() <= MAX_CREDENTIALS_METADATA_COUNT);
- GPR_ASSERT(batch->send_initial_metadata);
- grpc_metadata_batch* mdb =
- batch->payload->send_initial_metadata.send_initial_metadata;
- for (const auto& md : *calld->md_array) {
- mdb->Append(
- md.first.as_string_view(), md.second.Ref(),
- [&](absl::string_view error_message, const grpc_core::Slice& value) {
- add_error(&error, GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
- "on_credentials_metadata: ", error_message,
- ": ", md.first.as_string_view(), ": ",
- value.as_string_view())));
- });
- }
- grpc_call_next_op(elem, batch);
- } else {
- error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
- GRPC_STATUS_UNAVAILABLE);
- grpc_transport_stream_op_batch_finish_with_failure(batch, error,
- calld->call_combiner);
- }
- GRPC_CALL_STACK_UNREF(calld->owning_call, "get_request_metadata");
-}
-
-void grpc_auth_metadata_context_build(
- const char* url_scheme, const grpc_slice& call_host,
- const grpc_slice& call_method, grpc_auth_context* auth_context,
- grpc_auth_metadata_context* auth_md_context) {
- char* service = grpc_slice_to_c_string(call_method);
- char* last_slash = strrchr(service, '/');
- char* method_name = nullptr;
- char* service_url = nullptr;
- grpc_auth_metadata_context_reset(auth_md_context);
- if (last_slash == nullptr) {
- gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
- service[0] = '\0';
- method_name = gpr_strdup("");
- } else if (last_slash == service) {
- method_name = gpr_strdup("");
- } else {
- *last_slash = '\0';
- method_name = gpr_strdup(last_slash + 1);
- }
- char* host_and_port = grpc_slice_to_c_string(call_host);
- if (url_scheme != nullptr && strcmp(url_scheme, GRPC_SSL_URL_SCHEME) == 0) {
- /* Remove the port if it is 443. */
- char* port_delimiter = strrchr(host_and_port, ':');
- if (port_delimiter != nullptr && strcmp(port_delimiter + 1, "443") == 0) {
- *port_delimiter = '\0';
- }
- }
- gpr_asprintf(&service_url, "%s://%s%s",
- url_scheme == nullptr ? "" : url_scheme, host_and_port, service);
- auth_md_context->service_url = service_url;
- auth_md_context->method_name = method_name;
- auth_md_context->channel_auth_context =
- auth_context == nullptr
- ? nullptr
- : auth_context->Ref(DEBUG_LOCATION, "grpc_auth_metadata_context")
- .release();
- gpr_free(service);
- gpr_free(host_and_port);
-}
-
-static void cancel_get_request_metadata(void* arg, grpc_error_handle error) {
- grpc_call_element* elem = static_cast(arg);
- call_data* calld = static_cast(elem->call_data);
- if (error != GRPC_ERROR_NONE) {
- calld->creds->cancel_get_request_metadata(&*calld->md_array,
- GRPC_ERROR_REF(error));
- }
- GRPC_CALL_STACK_UNREF(calld->owning_call, "cancel_get_request_metadata");
-}
-
static grpc_security_level convert_security_level_string_to_enum(
const char* security_level) {
if (strcmp(security_level, "TSI_INTEGRITY_ONLY") == 0) {
@@ -253,242 +91,112 @@ bool grpc_check_security_level(grpc_security_level channel_level,
return static_cast(channel_level) >= static_cast(call_cred_level);
}
-static void send_security_metadata(grpc_call_element* elem,
- grpc_transport_stream_op_batch* batch) {
- call_data* calld = static_cast(elem->call_data);
- channel_data* chand = static_cast(elem->channel_data);
- grpc_client_security_context* ctx =
- static_cast(
- batch->payload->context[GRPC_CONTEXT_SECURITY].value);
+namespace grpc_core {
+
+ClientAuthFilter::ClientAuthFilter(
+ RefCountedPtr security_connector,
+ RefCountedPtr auth_context)
+ : args_{std::move(security_connector), std::move(auth_context)} {}
+
+ArenaPromise>
+ClientAuthFilter::GetCallCredsMetadata(ClientInitialMetadata initial_metadata) {
+ auto* ctx = static_cast