Merge branch 'master' into chttp2transportcomment

pull/23575/head
Yash Tibrewal 5 years ago
commit 51daf9701a
  1. 1
      BUILD
  2. 1
      BUILD.gn
  3. 19
      CMakeLists.txt
  4. 10
      Makefile
  5. 2
      build_autogenerated.yaml
  6. 13
      config.m4
  7. 13
      config.w32
  8. 1
      doc/python/sphinx/grpc.rst
  9. 1
      gRPC-C++.podspec
  10. 1
      gRPC-Core.podspec
  11. 2
      grpc.def
  12. 37
      grpc.gemspec
  13. 2
      grpc.gyp
  14. 45
      include/grpc/grpc_security.h
  15. 37
      package.xml
  16. 29
      src/core/ext/filters/client_channel/client_channel.cc
  17. 6
      src/core/ext/filters/client_channel/health/health_check_client.cc
  18. 2
      src/core/ext/filters/client_channel/lb_policy.h
  19. 10
      src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
  20. 28
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  21. 32
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
  22. 39
      src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
  23. 9
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
  24. 29
      src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
  25. 28
      src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
  26. 30
      src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
  27. 23
      src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
  28. 20
      src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
  29. 9
      src/core/ext/filters/client_channel/resolving_lb_policy.cc
  30. 66
      src/core/ext/filters/client_channel/subchannel.cc
  31. 11
      src/core/ext/filters/client_channel/subchannel.h
  32. 2
      src/core/ext/filters/client_channel/xds/xds_channel_secure.cc
  33. 8
      src/core/ext/filters/client_channel/xds/xds_client.cc
  34. 3
      src/core/ext/filters/max_age/max_age_filter.cc
  35. 18
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  36. 3
      src/core/ext/transport/inproc/inproc_transport.cc
  37. 94
      src/core/lib/security/credentials/google_default/google_default_credentials.cc
  38. 3
      src/core/lib/surface/server.cc
  39. 31
      src/core/lib/transport/connectivity_state.cc
  40. 24
      src/core/lib/transport/connectivity_state.h
  41. 13
      src/core/lib/transport/error_utils.cc
  42. 6
      src/core/lib/transport/error_utils.h
  43. 3
      src/cpp/client/secure_credentials.cc
  44. 2
      src/php/ext/grpc/channel_credentials.c
  45. 17
      src/python/grpcio/grpc/__init__.py
  46. 19
      src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
  47. 2
      src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
  48. 10
      src/python/grpcio/grpc_core_dependencies.py
  49. 9
      src/python/grpcio_tests/tests/interop/BUILD.bazel
  50. 39
      src/python/grpcio_tests/tests/interop/client.py
  51. 2
      src/python/grpcio_tests/tests_aio/interop/BUILD.bazel
  52. 2
      src/python/grpcio_tests/tests_aio/interop/client.py
  53. 4
      src/ruby/ext/grpc/rb_grpc_imports.generated.c
  54. 8
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  55. 3
      templates/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh.template
  56. 117
      test/core/security/credentials_test.cc
  57. 3
      test/core/surface/lame_client_test.cc
  58. 2
      test/core/surface/public_headers_must_be_c89.c
  59. 3
      test/core/transport/chttp2/too_many_pings_test.cc
  60. 81
      test/core/transport/connectivity_state_test.cc
  61. 8
      test/core/util/test_lb_policies.cc
  62. 3
      tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh
  63. 4
      tools/run_tests/run_interop_tests.py

@ -956,6 +956,7 @@ grpc_cc_library(
external_deps = [ external_deps = [
"madler_zlib", "madler_zlib",
"absl/container:inlined_vector", "absl/container:inlined_vector",
"absl/status",
"absl/types:optional", "absl/types:optional",
], ],
language = "c++", language = "c++",

@ -991,6 +991,7 @@ config("grpc_config") {
":upb", ":upb",
":absl/types:optional", ":absl/types:optional",
":absl/strings:strings", ":absl/strings:strings",
":absl/status:status",
":absl/container:inlined_vector", ":absl/container:inlined_vector",
"//third_party/cares", "//third_party/cares",
":address_sorting", ":address_sorting",

@ -111,23 +111,32 @@ set(gRPC_ABSL_USED_TARGETS
absl_civil_time absl_civil_time
absl_compressed_tuple absl_compressed_tuple
absl_config absl_config
absl_cord
absl_core_headers absl_core_headers
absl_debugging_internal
absl_demangle_internal
absl_dynamic_annotations absl_dynamic_annotations
absl_endian absl_endian
absl_errno_saver absl_errno_saver
absl_fixed_array
absl_function_ref
absl_inlined_vector absl_inlined_vector
absl_inlined_vector_internal absl_inlined_vector_internal
absl_int128 absl_int128
absl_log_severity absl_log_severity
absl_malloc_internal
absl_memory absl_memory
absl_optional absl_optional
absl_raw_logging_internal absl_raw_logging_internal
absl_span absl_span
absl_spinlock_wait absl_spinlock_wait
absl_stacktrace
absl_status
absl_str_format absl_str_format
absl_str_format_internal absl_str_format_internal
absl_strings absl_strings
absl_strings_internal absl_strings_internal
absl_symbolize
absl_throw_delegate absl_throw_delegate
absl_time absl_time
absl_time_zone absl_time_zone
@ -1793,6 +1802,7 @@ target_link_libraries(grpc
upb upb
absl::optional absl::optional
absl::strings absl::strings
absl::status
absl::inlined_vector absl::inlined_vector
) )
if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC) if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
@ -2395,6 +2405,7 @@ target_link_libraries(grpc_unsecure
upb upb
absl::optional absl::optional
absl::strings absl::strings
absl::status
absl::inlined_vector absl::inlined_vector
) )
if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC) if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
@ -15546,7 +15557,7 @@ generate_pkgconfig(
"high performance general RPC framework" "high performance general RPC framework"
"${gRPC_CORE_VERSION}" "${gRPC_CORE_VERSION}"
"gpr openssl" "gpr openssl"
"-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations" "-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
"" ""
"grpc.pc") "grpc.pc")
@ -15556,7 +15567,7 @@ generate_pkgconfig(
"high performance general RPC framework without SSL" "high performance general RPC framework without SSL"
"${gRPC_CORE_VERSION}" "${gRPC_CORE_VERSION}"
"gpr" "gpr"
"-lgrpc_unsecure -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations" "-lgrpc_unsecure -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
"" ""
"grpc_unsecure.pc") "grpc_unsecure.pc")
@ -15566,7 +15577,7 @@ generate_pkgconfig(
"C++ wrapper for gRPC" "C++ wrapper for gRPC"
"${gRPC_CPP_VERSION}" "${gRPC_CPP_VERSION}"
"grpc" "grpc"
"-lgrpc++ -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations" "-lgrpc++ -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
"" ""
"grpc++.pc") "grpc++.pc")
@ -15576,6 +15587,6 @@ generate_pkgconfig(
"C++ wrapper for gRPC without SSL" "C++ wrapper for gRPC without SSL"
"${gRPC_CPP_VERSION}" "${gRPC_CPP_VERSION}"
"grpc_unsecure" "grpc_unsecure"
"-lgrpc++_unsecure -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations" "-lgrpc++_unsecure -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
"" ""
"grpc++_unsecure.pc") "grpc++_unsecure.pc")

@ -6236,6 +6236,7 @@ endif
LIBGRPC_ABSEIL_SRC = \ LIBGRPC_ABSEIL_SRC = \
third_party/abseil-cpp/absl/base/dynamic_annotations.cc \ third_party/abseil-cpp/absl/base/dynamic_annotations.cc \
third_party/abseil-cpp/absl/base/internal/cycleclock.cc \ third_party/abseil-cpp/absl/base/internal/cycleclock.cc \
third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc \
third_party/abseil-cpp/absl/base/internal/raw_logging.cc \ third_party/abseil-cpp/absl/base/internal/raw_logging.cc \
third_party/abseil-cpp/absl/base/internal/spinlock.cc \ third_party/abseil-cpp/absl/base/internal/spinlock.cc \
third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc \ third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc \
@ -6244,9 +6245,18 @@ LIBGRPC_ABSEIL_SRC = \
third_party/abseil-cpp/absl/base/internal/throw_delegate.cc \ third_party/abseil-cpp/absl/base/internal/throw_delegate.cc \
third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc \ third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc \
third_party/abseil-cpp/absl/base/log_severity.cc \ third_party/abseil-cpp/absl/base/log_severity.cc \
third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc \
third_party/abseil-cpp/absl/debugging/internal/demangle.cc \
third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc \
third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc \
third_party/abseil-cpp/absl/debugging/stacktrace.cc \
third_party/abseil-cpp/absl/debugging/symbolize.cc \
third_party/abseil-cpp/absl/numeric/int128.cc \ third_party/abseil-cpp/absl/numeric/int128.cc \
third_party/abseil-cpp/absl/status/status.cc \
third_party/abseil-cpp/absl/status/status_payload_printer.cc \
third_party/abseil-cpp/absl/strings/ascii.cc \ third_party/abseil-cpp/absl/strings/ascii.cc \
third_party/abseil-cpp/absl/strings/charconv.cc \ third_party/abseil-cpp/absl/strings/charconv.cc \
third_party/abseil-cpp/absl/strings/cord.cc \
third_party/abseil-cpp/absl/strings/escaping.cc \ third_party/abseil-cpp/absl/strings/escaping.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc \ third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc \ third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc \

@ -1163,6 +1163,7 @@ libs:
- upb - upb
- absl/types:optional - absl/types:optional
- absl/strings:strings - absl/strings:strings
- absl/status:status
- absl/container:inlined_vector - absl/container:inlined_vector
baselib: true baselib: true
deps_linkage: static deps_linkage: static
@ -1952,6 +1953,7 @@ libs:
- upb - upb
- absl/types:optional - absl/types:optional
- absl/strings:strings - absl/strings:strings
- absl/status:status
- absl/container:inlined_vector - absl/container:inlined_vector
baselib: true baselib: true
deps_linkage: static deps_linkage: static

@ -509,6 +509,7 @@ if test "$PHP_GRPC" != "no"; then
src/php/ext/grpc/timeval.c \ src/php/ext/grpc/timeval.c \
third_party/abseil-cpp/absl/base/dynamic_annotations.cc \ third_party/abseil-cpp/absl/base/dynamic_annotations.cc \
third_party/abseil-cpp/absl/base/internal/cycleclock.cc \ third_party/abseil-cpp/absl/base/internal/cycleclock.cc \
third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc \
third_party/abseil-cpp/absl/base/internal/raw_logging.cc \ third_party/abseil-cpp/absl/base/internal/raw_logging.cc \
third_party/abseil-cpp/absl/base/internal/spinlock.cc \ third_party/abseil-cpp/absl/base/internal/spinlock.cc \
third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc \ third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc \
@ -517,9 +518,18 @@ if test "$PHP_GRPC" != "no"; then
third_party/abseil-cpp/absl/base/internal/throw_delegate.cc \ third_party/abseil-cpp/absl/base/internal/throw_delegate.cc \
third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc \ third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc \
third_party/abseil-cpp/absl/base/log_severity.cc \ third_party/abseil-cpp/absl/base/log_severity.cc \
third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc \
third_party/abseil-cpp/absl/debugging/internal/demangle.cc \
third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc \
third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc \
third_party/abseil-cpp/absl/debugging/stacktrace.cc \
third_party/abseil-cpp/absl/debugging/symbolize.cc \
third_party/abseil-cpp/absl/numeric/int128.cc \ third_party/abseil-cpp/absl/numeric/int128.cc \
third_party/abseil-cpp/absl/status/status.cc \
third_party/abseil-cpp/absl/status/status_payload_printer.cc \
third_party/abseil-cpp/absl/strings/ascii.cc \ third_party/abseil-cpp/absl/strings/ascii.cc \
third_party/abseil-cpp/absl/strings/charconv.cc \ third_party/abseil-cpp/absl/strings/charconv.cc \
third_party/abseil-cpp/absl/strings/cord.cc \
third_party/abseil-cpp/absl/strings/escaping.cc \ third_party/abseil-cpp/absl/strings/escaping.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc \ third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc \ third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc \
@ -971,7 +981,10 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc) PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/base) PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/base)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/base/internal) PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/base/internal)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/debugging)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/debugging/internal)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/numeric) PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/numeric)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/status)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings) PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings/internal) PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings/internal)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings/internal/str_format) PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings/internal/str_format)

@ -477,6 +477,7 @@ if (PHP_GRPC != "no") {
"src\\php\\ext\\grpc\\timeval.c " + "src\\php\\ext\\grpc\\timeval.c " +
"third_party\\abseil-cpp\\absl\\base\\dynamic_annotations.cc " + "third_party\\abseil-cpp\\absl\\base\\dynamic_annotations.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\cycleclock.cc " + "third_party\\abseil-cpp\\absl\\base\\internal\\cycleclock.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\low_level_alloc.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\raw_logging.cc " + "third_party\\abseil-cpp\\absl\\base\\internal\\raw_logging.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\spinlock.cc " + "third_party\\abseil-cpp\\absl\\base\\internal\\spinlock.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\spinlock_wait.cc " + "third_party\\abseil-cpp\\absl\\base\\internal\\spinlock_wait.cc " +
@ -485,9 +486,18 @@ if (PHP_GRPC != "no") {
"third_party\\abseil-cpp\\absl\\base\\internal\\throw_delegate.cc " + "third_party\\abseil-cpp\\absl\\base\\internal\\throw_delegate.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\unscaledcycleclock.cc " + "third_party\\abseil-cpp\\absl\\base\\internal\\unscaledcycleclock.cc " +
"third_party\\abseil-cpp\\absl\\base\\log_severity.cc " + "third_party\\abseil-cpp\\absl\\base\\log_severity.cc " +
"third_party\\abseil-cpp\\absl\\debugging\\internal\\address_is_readable.cc " +
"third_party\\abseil-cpp\\absl\\debugging\\internal\\demangle.cc " +
"third_party\\abseil-cpp\\absl\\debugging\\internal\\elf_mem_image.cc " +
"third_party\\abseil-cpp\\absl\\debugging\\internal\\vdso_support.cc " +
"third_party\\abseil-cpp\\absl\\debugging\\stacktrace.cc " +
"third_party\\abseil-cpp\\absl\\debugging\\symbolize.cc " +
"third_party\\abseil-cpp\\absl\\numeric\\int128.cc " + "third_party\\abseil-cpp\\absl\\numeric\\int128.cc " +
"third_party\\abseil-cpp\\absl\\status\\status.cc " +
"third_party\\abseil-cpp\\absl\\status\\status_payload_printer.cc " +
"third_party\\abseil-cpp\\absl\\strings\\ascii.cc " + "third_party\\abseil-cpp\\absl\\strings\\ascii.cc " +
"third_party\\abseil-cpp\\absl\\strings\\charconv.cc " + "third_party\\abseil-cpp\\absl\\strings\\charconv.cc " +
"third_party\\abseil-cpp\\absl\\strings\\cord.cc " +
"third_party\\abseil-cpp\\absl\\strings\\escaping.cc " + "third_party\\abseil-cpp\\absl\\strings\\escaping.cc " +
"third_party\\abseil-cpp\\absl\\strings\\internal\\charconv_bigint.cc " + "third_party\\abseil-cpp\\absl\\strings\\internal\\charconv_bigint.cc " +
"third_party\\abseil-cpp\\absl\\strings\\internal\\charconv_parse.cc " + "third_party\\abseil-cpp\\absl\\strings\\internal\\charconv_parse.cc " +
@ -1007,7 +1017,10 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\base"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\base");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\base\\internal"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\base\\internal");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\debugging");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\debugging\\internal");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\numeric"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\numeric");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\status");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings\\internal"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings\\internal");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings\\internal\\str_format"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings\\internal\\str_format");

@ -41,6 +41,7 @@ Create Client Credentials
.. autofunction:: composite_call_credentials .. autofunction:: composite_call_credentials
.. autofunction:: composite_channel_credentials .. autofunction:: composite_channel_credentials
.. autofunction:: local_channel_credentials(local_connect_type=grpc.LocalConnectionType.LOCAL_TCP) .. autofunction:: local_channel_credentials(local_connect_type=grpc.LocalConnectionType.LOCAL_TCP)
.. autofunction:: compute_engine_channel_credentials
Create Server Create Server

@ -210,6 +210,7 @@ Pod::Spec.new do |s|
abseil_version = '1.20200225.0' abseil_version = '1.20200225.0'
ss.dependency 'abseil/container/inlined_vector', abseil_version ss.dependency 'abseil/container/inlined_vector', abseil_version
ss.dependency 'abseil/memory/memory', abseil_version ss.dependency 'abseil/memory/memory', abseil_version
ss.dependency 'abseil/status/status', abseil_version
ss.dependency 'abseil/strings/str_format', abseil_version ss.dependency 'abseil/strings/str_format', abseil_version
ss.dependency 'abseil/strings/strings', abseil_version ss.dependency 'abseil/strings/strings', abseil_version
ss.dependency 'abseil/time/time', abseil_version ss.dependency 'abseil/time/time', abseil_version

@ -176,6 +176,7 @@ Pod::Spec.new do |s|
abseil_version = '1.20200225.0' abseil_version = '1.20200225.0'
ss.dependency 'abseil/container/inlined_vector', abseil_version ss.dependency 'abseil/container/inlined_vector', abseil_version
ss.dependency 'abseil/memory/memory', abseil_version ss.dependency 'abseil/memory/memory', abseil_version
ss.dependency 'abseil/status/status', abseil_version
ss.dependency 'abseil/strings/str_format', abseil_version ss.dependency 'abseil/strings/str_format', abseil_version
ss.dependency 'abseil/strings/strings', abseil_version ss.dependency 'abseil/strings/strings', abseil_version
ss.dependency 'abseil/time/time', abseil_version ss.dependency 'abseil/time/time', abseil_version

@ -97,12 +97,12 @@ EXPORTS
grpc_ssl_session_cache_create_lru grpc_ssl_session_cache_create_lru
grpc_ssl_session_cache_destroy grpc_ssl_session_cache_destroy
grpc_ssl_session_cache_create_channel_arg grpc_ssl_session_cache_create_channel_arg
grpc_call_credentials_release
grpc_channel_credentials_release grpc_channel_credentials_release
grpc_google_default_credentials_create grpc_google_default_credentials_create
grpc_set_ssl_roots_override_callback grpc_set_ssl_roots_override_callback
grpc_ssl_credentials_create grpc_ssl_credentials_create
grpc_ssl_credentials_create_ex grpc_ssl_credentials_create_ex
grpc_call_credentials_release
grpc_composite_channel_credentials_create grpc_composite_channel_credentials_create
grpc_composite_call_credentials_create grpc_composite_call_credentials_create
grpc_google_compute_engine_credentials_create grpc_google_compute_engine_credentials_create

@ -969,12 +969,15 @@ Gem::Specification.new do |s|
s.files += %w( third_party/abseil-cpp/absl/base/internal/bits.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/bits.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/cycleclock.cc ) s.files += %w( third_party/abseil-cpp/absl/base/internal/cycleclock.cc )
s.files += %w( third_party/abseil-cpp/absl/base/internal/cycleclock.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/cycleclock.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/direct_mmap.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/endian.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/endian.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/errno_saver.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/errno_saver.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/hide_ptr.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/hide_ptr.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/identity.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/identity.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/inline_variable.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/inline_variable.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/invoke.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/invoke.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc )
s.files += %w( third_party/abseil-cpp/absl/base/internal/low_level_alloc.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/per_thread_tls.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/per_thread_tls.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/raw_logging.cc ) s.files += %w( third_party/abseil-cpp/absl/base/internal/raw_logging.cc )
@ -1007,19 +1010,52 @@ Gem::Specification.new do |s|
s.files += %w( third_party/abseil-cpp/absl/base/policy_checks.h ) s.files += %w( third_party/abseil-cpp/absl/base/policy_checks.h )
s.files += %w( third_party/abseil-cpp/absl/base/port.h ) s.files += %w( third_party/abseil-cpp/absl/base/port.h )
s.files += %w( third_party/abseil-cpp/absl/base/thread_annotations.h ) s.files += %w( third_party/abseil-cpp/absl/base/thread_annotations.h )
s.files += %w( third_party/abseil-cpp/absl/container/fixed_array.h )
s.files += %w( third_party/abseil-cpp/absl/container/inlined_vector.h ) s.files += %w( third_party/abseil-cpp/absl/container/inlined_vector.h )
s.files += %w( third_party/abseil-cpp/absl/container/internal/compressed_tuple.h ) s.files += %w( third_party/abseil-cpp/absl/container/internal/compressed_tuple.h )
s.files += %w( third_party/abseil-cpp/absl/container/internal/inlined_vector.h ) s.files += %w( third_party/abseil-cpp/absl/container/internal/inlined_vector.h )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/address_is_readable.h )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/demangle.cc )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/demangle.h )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/symbolize.h )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc )
s.files += %w( third_party/abseil-cpp/absl/debugging/internal/vdso_support.h )
s.files += %w( third_party/abseil-cpp/absl/debugging/stacktrace.cc )
s.files += %w( third_party/abseil-cpp/absl/debugging/stacktrace.h )
s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize.cc )
s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize.h )
s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize_elf.inc )
s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize_unimplemented.inc )
s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize_win32.inc )
s.files += %w( third_party/abseil-cpp/absl/functional/function_ref.h )
s.files += %w( third_party/abseil-cpp/absl/functional/internal/function_ref.h )
s.files += %w( third_party/abseil-cpp/absl/memory/memory.h ) s.files += %w( third_party/abseil-cpp/absl/memory/memory.h )
s.files += %w( third_party/abseil-cpp/absl/meta/type_traits.h ) s.files += %w( third_party/abseil-cpp/absl/meta/type_traits.h )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128.cc ) s.files += %w( third_party/abseil-cpp/absl/numeric/int128.cc )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128.h ) s.files += %w( third_party/abseil-cpp/absl/numeric/int128.h )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc ) s.files += %w( third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc ) s.files += %w( third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc )
s.files += %w( third_party/abseil-cpp/absl/status/status.cc )
s.files += %w( third_party/abseil-cpp/absl/status/status.h )
s.files += %w( third_party/abseil-cpp/absl/status/status_payload_printer.cc )
s.files += %w( third_party/abseil-cpp/absl/status/status_payload_printer.h )
s.files += %w( third_party/abseil-cpp/absl/strings/ascii.cc ) s.files += %w( third_party/abseil-cpp/absl/strings/ascii.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/ascii.h ) s.files += %w( third_party/abseil-cpp/absl/strings/ascii.h )
s.files += %w( third_party/abseil-cpp/absl/strings/charconv.cc ) s.files += %w( third_party/abseil-cpp/absl/strings/charconv.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/charconv.h ) s.files += %w( third_party/abseil-cpp/absl/strings/charconv.h )
s.files += %w( third_party/abseil-cpp/absl/strings/cord.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/cord.h )
s.files += %w( third_party/abseil-cpp/absl/strings/escaping.cc ) s.files += %w( third_party/abseil-cpp/absl/strings/escaping.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/escaping.h ) s.files += %w( third_party/abseil-cpp/absl/strings/escaping.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/char_map.h ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/char_map.h )
@ -1027,6 +1063,7 @@ Gem::Specification.new do |s|
s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_parse.h ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_parse.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/cord_internal.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/escaping.cc ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/escaping.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/escaping.h ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/escaping.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/memutil.cc ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/memutil.cc )

@ -432,6 +432,7 @@
'upb', 'upb',
'absl/types:optional', 'absl/types:optional',
'absl/strings:strings', 'absl/strings:strings',
'absl/status:status',
'absl/container:inlined_vector', 'absl/container:inlined_vector',
], ],
'sources': [ 'sources': [
@ -941,6 +942,7 @@
'upb', 'upb',
'absl/types:optional', 'absl/types:optional',
'absl/strings:strings', 'absl/strings:strings',
'absl/status:status',
'absl/container:inlined_vector', 'absl/container:inlined_vector',
], ],
'sources': [ 'sources': [

@ -119,6 +119,18 @@ GRPCAPI void grpc_ssl_session_cache_destroy(grpc_ssl_session_cache* cache);
GRPCAPI grpc_arg GRPCAPI grpc_arg
grpc_ssl_session_cache_create_channel_arg(grpc_ssl_session_cache* cache); grpc_ssl_session_cache_create_channel_arg(grpc_ssl_session_cache* cache);
/** --- grpc_call_credentials object.
A call credentials object represents a way to authenticate on a particular
call. These credentials can be composed with a channel credentials object
so that they are sent with every call on this channel. */
typedef struct grpc_call_credentials grpc_call_credentials;
/** Releases a call credentials object.
The creator of the credentials object is responsible for its release. */
GRPCAPI void grpc_call_credentials_release(grpc_call_credentials* creds);
/** --- grpc_channel_credentials object. --- /** --- grpc_channel_credentials object. ---
A channel credentials object represents a way to authenticate a client on a A channel credentials object represents a way to authenticate a client on a
@ -133,8 +145,23 @@ GRPCAPI void grpc_channel_credentials_release(grpc_channel_credentials* creds);
/** Creates default credentials to connect to a google gRPC service. /** Creates default credentials to connect to a google gRPC service.
WARNING: Do NOT use this credentials to connect to a non-google service as WARNING: Do NOT use this credentials to connect to a non-google service as
this could result in an oauth2 token leak. The security level of the this could result in an oauth2 token leak. The security level of the
resulting connection is GRPC_PRIVACY_AND_INTEGRITY. */ resulting connection is GRPC_PRIVACY_AND_INTEGRITY.
GRPCAPI grpc_channel_credentials* grpc_google_default_credentials_create(void);
If specified, the supplied call credentials object will be attached to the
returned channel credentials object. The call_credentials object must remain
valid throughout the lifetime of the returned grpc_channel_credentials
object. It is expected that the call credentials object was generated
according to the Application Default Credentials mechanism and asserts the
identity of the default service account of the machine. Supplying any other
sort of call credential will result in undefined behavior, up to and
including the sudden and unexpected failure of RPCs.
If nullptr is supplied, the returned channel credentials object will use a
call credentials object based on the Application Default Credentials
mechanism.
*/
GRPCAPI grpc_channel_credentials* grpc_google_default_credentials_create(
grpc_call_credentials* call_credentials);
/** Callback for getting the SSL roots override from the application. /** Callback for getting the SSL roots override from the application.
In case of success, *pem_roots_certs must be set to a NULL terminated string In case of success, *pem_roots_certs must be set to a NULL terminated string
@ -272,24 +299,14 @@ GRPCAPI grpc_channel_credentials* grpc_ssl_credentials_create_ex(
const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
const grpc_ssl_verify_peer_options* verify_options, void* reserved); const grpc_ssl_verify_peer_options* verify_options, void* reserved);
/** --- grpc_call_credentials object.
A call credentials object represents a way to authenticate on a particular
call. These credentials can be composed with a channel credentials object
so that they are sent with every call on this channel. */
typedef struct grpc_call_credentials grpc_call_credentials;
/** Releases a call credentials object.
The creator of the credentials object is responsible for its release. */
GRPCAPI void grpc_call_credentials_release(grpc_call_credentials* creds);
/** Creates a composite channel credentials object. The security level of /** Creates a composite channel credentials object. The security level of
* resulting connection is determined by channel_creds. */ * resulting connection is determined by channel_creds. */
GRPCAPI grpc_channel_credentials* grpc_composite_channel_credentials_create( GRPCAPI grpc_channel_credentials* grpc_composite_channel_credentials_create(
grpc_channel_credentials* channel_creds, grpc_call_credentials* call_creds, grpc_channel_credentials* channel_creds, grpc_call_credentials* call_creds,
void* reserved); void* reserved);
/** --- composite credentials. */
/** Creates a composite call credentials object. */ /** Creates a composite call credentials object. */
GRPCAPI grpc_call_credentials* grpc_composite_call_credentials_create( GRPCAPI grpc_call_credentials* grpc_composite_call_credentials_create(
grpc_call_credentials* creds1, grpc_call_credentials* creds2, grpc_call_credentials* creds1, grpc_call_credentials* creds2,

@ -971,12 +971,15 @@
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/bits.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/bits.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/cycleclock.cc" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/cycleclock.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/cycleclock.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/cycleclock.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/direct_mmap.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/endian.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/endian.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/errno_saver.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/errno_saver.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/hide_ptr.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/hide_ptr.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/identity.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/identity.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/inline_variable.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/inline_variable.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/invoke.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/invoke.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/low_level_alloc.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/per_thread_tls.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/per_thread_tls.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/raw_logging.cc" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/raw_logging.cc" role="src" />
@ -1009,19 +1012,52 @@
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/policy_checks.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/policy_checks.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/port.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/port.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/thread_annotations.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/thread_annotations.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/fixed_array.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/inlined_vector.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/inlined_vector.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/internal/compressed_tuple.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/internal/compressed_tuple.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/internal/inlined_vector.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/internal/inlined_vector.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/address_is_readable.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/demangle.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/demangle.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/symbolize.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/vdso_support.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/stacktrace.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/stacktrace.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/symbolize.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/symbolize.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/symbolize_elf.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/symbolize_unimplemented.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/symbolize_win32.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/functional/function_ref.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/functional/internal/function_ref.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/memory/memory.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/memory/memory.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/meta/type_traits.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/meta/type_traits.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128.cc" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/status/status.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/status/status.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/status/status_payload_printer.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/status/status_payload_printer.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/ascii.cc" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/ascii.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/ascii.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/ascii.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/charconv.cc" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/charconv.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/charconv.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/charconv.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/cord.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/cord.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/escaping.cc" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/escaping.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/escaping.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/escaping.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/char_map.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/char_map.h" role="src" />
@ -1029,6 +1065,7 @@
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/charconv_parse.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/charconv_parse.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/cord_internal.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/escaping.cc" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/escaping.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/escaping.h" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/escaping.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/memutil.cc" role="src" /> <file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/memutil.cc" role="src" />

@ -214,7 +214,8 @@ class ChannelData {
grpc_closure* on_complete, grpc_closure* on_complete,
bool cancel); bool cancel);
void Notify(grpc_connectivity_state state) override; void Notify(grpc_connectivity_state state,
const absl::Status& /* status */) override;
void Cancel(); void Cancel();
@ -260,7 +261,8 @@ class ChannelData {
~ChannelData(); ~ChannelData();
void UpdateStateAndPickerLocked( void UpdateStateAndPickerLocked(
grpc_connectivity_state state, const char* reason, grpc_connectivity_state state, const absl::Status& status,
const char* reason,
std::unique_ptr<LoadBalancingPolicy::SubchannelPicker> picker); std::unique_ptr<LoadBalancingPolicy::SubchannelPicker> picker);
void UpdateServiceConfigInDataPlaneLocked( void UpdateServiceConfigInDataPlaneLocked(
@ -1212,7 +1214,7 @@ void ChannelData::ExternalConnectivityWatcher::
} }
void ChannelData::ExternalConnectivityWatcher::Notify( void ChannelData::ExternalConnectivityWatcher::Notify(
grpc_connectivity_state state) { grpc_connectivity_state state, const absl::Status& /* status */) {
bool done = false; bool done = false;
if (!done_.CompareExchangeStrong(&done, true, MemoryOrder::RELAXED, if (!done_.CompareExchangeStrong(&done, true, MemoryOrder::RELAXED,
MemoryOrder::RELAXED)) { MemoryOrder::RELAXED)) {
@ -1352,19 +1354,21 @@ class ChannelData::ClientChannelControlHelper
} }
void UpdateState( void UpdateState(
grpc_connectivity_state state, grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<LoadBalancingPolicy::SubchannelPicker> picker) override { std::unique_ptr<LoadBalancingPolicy::SubchannelPicker> picker) override {
grpc_error* disconnect_error = chand_->disconnect_error(); grpc_error* disconnect_error = chand_->disconnect_error();
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
const char* extra = disconnect_error == GRPC_ERROR_NONE const char* extra = disconnect_error == GRPC_ERROR_NONE
? "" ? ""
: " (ignoring -- channel shutting down)"; : " (ignoring -- channel shutting down)";
gpr_log(GPR_INFO, "chand=%p: update: state=%s picker=%p%s", chand_, gpr_log(GPR_INFO, "chand=%p: update: state=%s status=(%s) picker=%p%s",
ConnectivityStateName(state), picker.get(), extra); chand_, ConnectivityStateName(state), status.ToString().c_str(),
picker.get(), extra);
} }
// Do update only if not shutting down. // Do update only if not shutting down.
if (disconnect_error == GRPC_ERROR_NONE) { if (disconnect_error == GRPC_ERROR_NONE) {
chand_->UpdateStateAndPickerLocked(state, "helper", std::move(picker)); chand_->UpdateStateAndPickerLocked(state, status, "helper",
std::move(picker));
} }
} }
@ -1701,7 +1705,8 @@ ChannelData::~ChannelData() {
} }
void ChannelData::UpdateStateAndPickerLocked( void ChannelData::UpdateStateAndPickerLocked(
grpc_connectivity_state state, const char* reason, grpc_connectivity_state state, const absl::Status& status,
const char* reason,
std::unique_ptr<LoadBalancingPolicy::SubchannelPicker> picker) { std::unique_ptr<LoadBalancingPolicy::SubchannelPicker> picker) {
// Clean the control plane when entering IDLE. // Clean the control plane when entering IDLE.
if (picker_ == nullptr) { if (picker_ == nullptr) {
@ -1711,7 +1716,7 @@ void ChannelData::UpdateStateAndPickerLocked(
received_first_resolver_result_ = false; received_first_resolver_result_ = false;
} }
// Update connectivity state. // Update connectivity state.
state_tracker_.SetState(state, reason); state_tracker_.SetState(state, status, reason);
if (channelz_node_ != nullptr) { if (channelz_node_ != nullptr) {
channelz_node_->SetConnectivityState(state); channelz_node_->SetConnectivityState(state);
channelz_node_->AddTraceEvent( channelz_node_->AddTraceEvent(
@ -1938,8 +1943,8 @@ void ChannelData::StartTransportOpLocked(grpc_transport_op* op) {
static_cast<grpc_connectivity_state>(value) == GRPC_CHANNEL_IDLE) { static_cast<grpc_connectivity_state>(value) == GRPC_CHANNEL_IDLE) {
if (disconnect_error() == GRPC_ERROR_NONE) { if (disconnect_error() == GRPC_ERROR_NONE) {
// Enter IDLE state. // Enter IDLE state.
UpdateStateAndPickerLocked(GRPC_CHANNEL_IDLE, "channel entering IDLE", UpdateStateAndPickerLocked(GRPC_CHANNEL_IDLE, absl::Status(),
nullptr); "channel entering IDLE", nullptr);
} }
GRPC_ERROR_UNREF(op->disconnect_with_error); GRPC_ERROR_UNREF(op->disconnect_with_error);
} else { } else {
@ -1948,7 +1953,7 @@ void ChannelData::StartTransportOpLocked(grpc_transport_op* op) {
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
disconnect_error_.Store(op->disconnect_with_error, MemoryOrder::RELEASE); disconnect_error_.Store(op->disconnect_with_error, MemoryOrder::RELEASE);
UpdateStateAndPickerLocked( UpdateStateAndPickerLocked(
GRPC_CHANNEL_SHUTDOWN, "shutdown from API", GRPC_CHANNEL_SHUTDOWN, absl::Status(), "shutdown from API",
absl::make_unique<LoadBalancingPolicy::TransientFailurePicker>( absl::make_unique<LoadBalancingPolicy::TransientFailurePicker>(
GRPC_ERROR_REF(op->disconnect_with_error))); GRPC_ERROR_REF(op->disconnect_with_error)));
} }

@ -91,7 +91,11 @@ void HealthCheckClient::SetHealthStatusLocked(grpc_connectivity_state state,
gpr_log(GPR_INFO, "HealthCheckClient %p: setting state=%s reason=%s", this, gpr_log(GPR_INFO, "HealthCheckClient %p: setting state=%s reason=%s", this,
ConnectivityStateName(state), reason); ConnectivityStateName(state), reason);
} }
if (watcher_ != nullptr) watcher_->Notify(state); if (watcher_ != nullptr)
watcher_->Notify(state,
state == GRPC_CHANNEL_TRANSIENT_FAILURE
? absl::Status(absl::StatusCode::kUnavailable, reason)
: absl::Status());
} }
void HealthCheckClient::Orphan() { void HealthCheckClient::Orphan() {

@ -24,6 +24,7 @@
#include <functional> #include <functional>
#include <iterator> #include <iterator>
#include "absl/status/status.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/server_address.h"
@ -283,6 +284,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// Sets the connectivity state and returns a new picker to be used /// Sets the connectivity state and returns a new picker to be used
/// by the client channel. /// by the client channel.
virtual void UpdateState(grpc_connectivity_state state, virtual void UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker>) = 0; std::unique_ptr<SubchannelPicker>) = 0;
/// Requests that the resolver re-resolve. /// Requests that the resolver re-resolve.

@ -45,7 +45,7 @@ class ChildPolicyHandler::Helper
return parent_->channel_control_helper()->CreateSubchannel(args); return parent_->channel_control_helper()->CreateSubchannel(args);
} }
void UpdateState(grpc_connectivity_state state, void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override { std::unique_ptr<SubchannelPicker> picker) override {
if (parent_->shutting_down_) return; if (parent_->shutting_down_) return;
// If this request is from the pending child policy, ignore it until // If this request is from the pending child policy, ignore it until
@ -55,8 +55,9 @@ class ChildPolicyHandler::Helper
if (GRPC_TRACE_FLAG_ENABLED(*(parent_->tracer_))) { if (GRPC_TRACE_FLAG_ENABLED(*(parent_->tracer_))) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[child_policy_handler %p] helper %p: pending child policy %p " "[child_policy_handler %p] helper %p: pending child policy %p "
"reports state=%s", "reports state=%s (%s)",
parent_.get(), this, child_, ConnectivityStateName(state)); parent_.get(), this, child_, ConnectivityStateName(state),
status.ToString().c_str());
} }
if (state == GRPC_CHANNEL_CONNECTING) return; if (state == GRPC_CHANNEL_CONNECTING) return;
grpc_pollset_set_del_pollset_set( grpc_pollset_set_del_pollset_set(
@ -67,7 +68,8 @@ class ChildPolicyHandler::Helper
// This request is from an outdated child, so ignore it. // This request is from an outdated child, so ignore it.
return; return;
} }
parent_->channel_control_helper()->UpdateState(state, std::move(picker)); parent_->channel_control_helper()->UpdateState(state, status,
std::move(picker));
} }
void RequestReresolution() override { void RequestReresolution() override {

@ -304,7 +304,7 @@ class GrpcLb : public LoadBalancingPolicy {
RefCountedPtr<SubchannelInterface> CreateSubchannel( RefCountedPtr<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override; const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state, void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override; std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override; void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, void AddTraceEvent(TraceSeverity severity,
@ -323,15 +323,16 @@ class GrpcLb : public LoadBalancingPolicy {
~StateWatcher() { parent_.reset(DEBUG_LOCATION, "StateWatcher"); } ~StateWatcher() { parent_.reset(DEBUG_LOCATION, "StateWatcher"); }
private: private:
void OnConnectivityStateChange(grpc_connectivity_state new_state) override { void OnConnectivityStateChange(grpc_connectivity_state new_state,
const absl::Status& status) override {
if (parent_->fallback_at_startup_checks_pending_ && if (parent_->fallback_at_startup_checks_pending_ &&
new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
// In TRANSIENT_FAILURE. Cancel the fallback timer and go into // In TRANSIENT_FAILURE. Cancel the fallback timer and go into
// fallback mode immediately. // fallback mode immediately.
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[grpclb %p] balancer channel in state TRANSIENT_FAILURE; " "[grpclb %p] balancer channel in state:TRANSIENT_FAILURE (%s); "
"entering fallback mode", "entering fallback mode",
parent_.get()); parent_.get(), status.ToString().c_str());
parent_->fallback_at_startup_checks_pending_ = false; parent_->fallback_at_startup_checks_pending_ = false;
grpc_timer_cancel(&parent_->lb_fallback_timer_); grpc_timer_cancel(&parent_->lb_fallback_timer_);
parent_->fallback_mode_ = true; parent_->fallback_mode_ = true;
@ -660,6 +661,7 @@ RefCountedPtr<SubchannelInterface> GrpcLb::Helper::CreateSubchannel(
} }
void GrpcLb::Helper::UpdateState(grpc_connectivity_state state, void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) { std::unique_ptr<SubchannelPicker> picker) {
if (parent_->shutting_down_) return; if (parent_->shutting_down_) return;
// Record whether child policy reports READY. // Record whether child policy reports READY.
@ -690,16 +692,22 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
state != GRPC_CHANNEL_READY)) { state != GRPC_CHANNEL_READY)) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[grpclb %p helper %p] state=%s passing child picker %p as-is", "[grpclb %p helper %p] state=%s (%s) passing "
parent_.get(), this, ConnectivityStateName(state), picker.get()); "child picker %p as-is",
parent_.get(), this, ConnectivityStateName(state),
status.ToString().c_str(), picker.get());
} }
parent_->channel_control_helper()->UpdateState(state, std::move(picker)); parent_->channel_control_helper()->UpdateState(state, status,
std::move(picker));
return; return;
} }
// Cases 2 and 3a: wrap picker from the child in our own picker. // Cases 2 and 3a: wrap picker from the child in our own picker.
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO, "[grpclb %p helper %p] state=%s wrapping child picker %p", gpr_log(GPR_INFO,
parent_.get(), this, ConnectivityStateName(state), picker.get()); "[grpclb %p helper %p] state=%s (%s) wrapping child "
"picker %p",
parent_.get(), this, ConnectivityStateName(state),
status.ToString().c_str(), picker.get());
} }
RefCountedPtr<GrpcLbClientStats> client_stats; RefCountedPtr<GrpcLbClientStats> client_stats;
if (parent_->lb_calld_ != nullptr && if (parent_->lb_calld_ != nullptr &&
@ -707,7 +715,7 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
client_stats = parent_->lb_calld_->client_stats()->Ref(); client_stats = parent_->lb_calld_->client_stats()->Ref();
} }
parent_->channel_control_helper()->UpdateState( parent_->channel_control_helper()->UpdateState(
state, state, status,
absl::make_unique<Picker>(parent_.get(), parent_->serverlist_, absl::make_unique<Picker>(parent_.get(), parent_->serverlist_,
std::move(picker), std::move(client_stats))); std::move(picker), std::move(client_stats)));
} }

@ -30,6 +30,7 @@
#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/error_utils.h"
namespace grpc_core { namespace grpc_core {
@ -200,7 +201,7 @@ void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() {
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"), grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
channel_control_helper()->UpdateState( channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>(error)); absl::make_unique<TransientFailurePicker>(error));
return; return;
} }
@ -318,12 +319,13 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
"selected subchannel failed; switching to pending update"), "selected subchannel failed; switching to pending update"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
p->channel_control_helper()->UpdateState( p->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>(error)); absl::make_unique<TransientFailurePicker>(error));
} else { } else {
p->channel_control_helper()->UpdateState( p->channel_control_helper()->UpdateState(
GRPC_CHANNEL_CONNECTING, absl::make_unique<QueuePicker>(p->Ref( GRPC_CHANNEL_CONNECTING, absl::Status(),
DEBUG_LOCATION, "QueuePicker"))); absl::make_unique<QueuePicker>(
p->Ref(DEBUG_LOCATION, "QueuePicker")));
} }
} else { } else {
if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
@ -338,20 +340,22 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
p->selected_ = nullptr; p->selected_ = nullptr;
p->subchannel_list_.reset(); p->subchannel_list_.reset();
p->channel_control_helper()->UpdateState( p->channel_control_helper()->UpdateState(
GRPC_CHANNEL_IDLE, absl::make_unique<QueuePicker>( GRPC_CHANNEL_IDLE, absl::Status(),
p->Ref(DEBUG_LOCATION, "QueuePicker"))); absl::make_unique<QueuePicker>(
p->Ref(DEBUG_LOCATION, "QueuePicker")));
} else { } else {
// This is unlikely but can happen when a subchannel has been asked // This is unlikely but can happen when a subchannel has been asked
// to reconnect by a different channel and this channel has dropped // to reconnect by a different channel and this channel has dropped
// some connectivity state notifications. // some connectivity state notifications.
if (connectivity_state == GRPC_CHANNEL_READY) { if (connectivity_state == GRPC_CHANNEL_READY) {
p->channel_control_helper()->UpdateState( p->channel_control_helper()->UpdateState(
GRPC_CHANNEL_READY, GRPC_CHANNEL_READY, absl::Status(),
absl::make_unique<Picker>(subchannel()->Ref())); absl::make_unique<Picker>(subchannel()->Ref()));
} else { // CONNECTING } else { // CONNECTING
p->channel_control_helper()->UpdateState( p->channel_control_helper()->UpdateState(
connectivity_state, absl::make_unique<QueuePicker>( connectivity_state, absl::Status(),
p->Ref(DEBUG_LOCATION, "QueuePicker"))); absl::make_unique<QueuePicker>(
p->Ref(DEBUG_LOCATION, "QueuePicker")));
} }
} }
} }
@ -394,7 +398,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
"failed to connect to all addresses"), "failed to connect to all addresses"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
p->channel_control_helper()->UpdateState( p->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>(error)); absl::make_unique<TransientFailurePicker>(error));
} }
} }
@ -406,8 +410,9 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
// Only update connectivity state in case 1. // Only update connectivity state in case 1.
if (subchannel_list() == p->subchannel_list_.get()) { if (subchannel_list() == p->subchannel_list_.get()) {
p->channel_control_helper()->UpdateState( p->channel_control_helper()->UpdateState(
GRPC_CHANNEL_CONNECTING, absl::make_unique<QueuePicker>(p->Ref( GRPC_CHANNEL_CONNECTING, absl::Status(),
DEBUG_LOCATION, "QueuePicker"))); absl::make_unique<QueuePicker>(
p->Ref(DEBUG_LOCATION, "QueuePicker")));
} }
break; break;
} }
@ -446,7 +451,8 @@ void PickFirst::PickFirstSubchannelData::ProcessUnselectedReadyLocked() {
} }
p->selected_ = this; p->selected_ = this;
p->channel_control_helper()->UpdateState( p->channel_control_helper()->UpdateState(
GRPC_CHANNEL_READY, absl::make_unique<Picker>(subchannel()->Ref())); GRPC_CHANNEL_READY, absl::Status(),
absl::make_unique<Picker>(subchannel()->Ref()));
for (size_t i = 0; i < subchannel_list()->num_subchannels(); ++i) { for (size_t i = 0; i < subchannel_list()->num_subchannels(); ++i) {
if (i != Index()) { if (i != Index()) {
subchannel_list()->subchannel(i)->ShutdownLocked(); subchannel_list()->subchannel(i)->ShutdownLocked();

@ -20,6 +20,7 @@
#include <limits.h> #include <limits.h>
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
@ -33,6 +34,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h" #include "src/core/lib/iomgr/work_serializer.h"
#include "src/core/lib/transport/error_utils.h"
namespace grpc_core { namespace grpc_core {
@ -113,6 +115,11 @@ class PriorityLb : public LoadBalancingPolicy {
grpc_connectivity_state connectivity_state() const { grpc_connectivity_state connectivity_state() const {
return connectivity_state_; return connectivity_state_;
} }
const absl::Status& connectivity_status() const {
return connectivity_status_;
}
bool failover_timer_callback_pending() const { bool failover_timer_callback_pending() const {
return failover_timer_callback_pending_; return failover_timer_callback_pending_;
} }
@ -150,6 +157,7 @@ class PriorityLb : public LoadBalancingPolicy {
RefCountedPtr<SubchannelInterface> CreateSubchannel( RefCountedPtr<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override; const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state, void UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override; std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override; void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, void AddTraceEvent(TraceSeverity severity,
@ -164,7 +172,7 @@ class PriorityLb : public LoadBalancingPolicy {
const grpc_channel_args* args); const grpc_channel_args* args);
void OnConnectivityStateUpdateLocked( void OnConnectivityStateUpdateLocked(
grpc_connectivity_state state, grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker); std::unique_ptr<SubchannelPicker> picker);
void StartFailoverTimerLocked(); void StartFailoverTimerLocked();
@ -180,6 +188,7 @@ class PriorityLb : public LoadBalancingPolicy {
OrphanablePtr<LoadBalancingPolicy> child_policy_; OrphanablePtr<LoadBalancingPolicy> child_policy_;
grpc_connectivity_state connectivity_state_ = GRPC_CHANNEL_CONNECTING; grpc_connectivity_state connectivity_state_ = GRPC_CHANNEL_CONNECTING;
absl::Status connectivity_status_;
RefCountedPtr<RefCountedPicker> picker_wrapper_; RefCountedPtr<RefCountedPicker> picker_wrapper_;
// States for delayed removal. // States for delayed removal.
@ -334,6 +343,7 @@ void PriorityLb::HandleChildConnectivityStateChangeLocked(
// If it's still READY or IDLE, we stick with this child, so pass // If it's still READY or IDLE, we stick with this child, so pass
// the new picker up to our parent. // the new picker up to our parent.
channel_control_helper()->UpdateState(child->connectivity_state(), channel_control_helper()->UpdateState(child->connectivity_state(),
child->connectivity_status(),
child->GetPicker()); child->GetPicker());
} else { } else {
// If it's no longer READY or IDLE, we should stop using it. // If it's no longer READY or IDLE, we should stop using it.
@ -380,6 +390,7 @@ void PriorityLb::HandleChildConnectivityStateChangeLocked(
// The current priority has returned a new picker, so pass it up to // The current priority has returned a new picker, so pass it up to
// our parent. // our parent.
channel_control_helper()->UpdateState(child->connectivity_state(), channel_control_helper()->UpdateState(child->connectivity_state(),
child->connectivity_status(),
child->GetPicker()); child->GetPicker());
} }
@ -409,7 +420,7 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) {
if (child == nullptr) { if (child == nullptr) {
if (report_connecting) { if (report_connecting) {
channel_control_helper()->UpdateState( channel_control_helper()->UpdateState(
GRPC_CHANNEL_CONNECTING, GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker"))); absl::make_unique<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker")));
} }
child = MakeOrphanable<ChildPriority>( child = MakeOrphanable<ChildPriority>(
@ -436,7 +447,7 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) {
} }
if (report_connecting) { if (report_connecting) {
channel_control_helper()->UpdateState( channel_control_helper()->UpdateState(
GRPC_CHANNEL_CONNECTING, GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker"))); absl::make_unique<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker")));
} }
return; return;
@ -456,7 +467,7 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) {
GRPC_ERROR_CREATE_FROM_STATIC_STRING("no ready priority"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("no ready priority"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
channel_control_helper()->UpdateState( channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>(error)); absl::make_unique<TransientFailurePicker>(error));
} }
@ -476,6 +487,7 @@ void PriorityLb::SelectPriorityLocked(uint32_t priority) {
// Update picker. // Update picker.
auto& child = children_[config_->priorities()[priority]]; auto& child = children_[config_->priorities()[priority]];
channel_control_helper()->UpdateState(child->connectivity_state(), channel_control_helper()->UpdateState(child->connectivity_state(),
child->connectivity_status(),
child->GetPicker()); child->GetPicker());
} }
@ -584,15 +596,18 @@ void PriorityLb::ChildPriority::ResetBackoffLocked() {
} }
void PriorityLb::ChildPriority::OnConnectivityStateUpdateLocked( void PriorityLb::ChildPriority::OnConnectivityStateUpdateLocked(
grpc_connectivity_state state, std::unique_ptr<SubchannelPicker> picker) { grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[priority_lb %p] child %s (%p): state update: %s, picker %p", "[priority_lb %p] child %s (%p): state update: %s (%s) picker %p",
priority_policy_.get(), name_.c_str(), this, priority_policy_.get(), name_.c_str(), this,
ConnectivityStateName(state), picker.get()); ConnectivityStateName(state), status.ToString().c_str(),
picker.get());
} }
// Store the state and picker. // Store the state and picker.
connectivity_state_ = state; connectivity_state_ = state;
connectivity_status_ = status;
picker_wrapper_ = MakeRefCounted<RefCountedPicker>(std::move(picker)); picker_wrapper_ = MakeRefCounted<RefCountedPicker>(std::move(picker));
// If READY or TRANSIENT_FAILURE, cancel failover timer. // If READY or TRANSIENT_FAILURE, cancel failover timer.
if (state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_TRANSIENT_FAILURE) { if (state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
@ -646,7 +661,10 @@ void PriorityLb::ChildPriority::OnFailoverTimerLocked(grpc_error* error) {
priority_policy_.get(), name_.c_str(), this); priority_policy_.get(), name_.c_str(), this);
} }
failover_timer_callback_pending_ = false; failover_timer_callback_pending_ = false;
OnConnectivityStateUpdateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, nullptr); OnConnectivityStateUpdateLocked(
GRPC_CHANNEL_TRANSIENT_FAILURE,
absl::Status(absl::StatusCode::kUnavailable, "failover timer fired"),
nullptr);
} }
Unref(DEBUG_LOCATION, "ChildPriority+OnFailoverTimerLocked"); Unref(DEBUG_LOCATION, "ChildPriority+OnFailoverTimerLocked");
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
@ -725,10 +743,11 @@ PriorityLb::ChildPriority::Helper::CreateSubchannel(
} }
void PriorityLb::ChildPriority::Helper::UpdateState( void PriorityLb::ChildPriority::Helper::UpdateState(
grpc_connectivity_state state, std::unique_ptr<SubchannelPicker> picker) { grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) {
if (priority_->priority_policy_->shutting_down_) return; if (priority_->priority_policy_->shutting_down_) return;
// Notify the priority. // Notify the priority.
priority_->OnConnectivityStateUpdateLocked(state, std::move(picker)); priority_->OnConnectivityStateUpdateLocked(state, status, std::move(picker));
} }
void PriorityLb::ChildPriority::Helper::AddTraceEvent( void PriorityLb::ChildPriority::Helper::AddTraceEvent(

@ -40,6 +40,7 @@
#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
namespace grpc_core { namespace grpc_core {
@ -322,11 +323,11 @@ void RoundRobin::RoundRobinSubchannelList::
if (num_ready_ > 0) { if (num_ready_ > 0) {
/* 1) READY */ /* 1) READY */
p->channel_control_helper()->UpdateState( p->channel_control_helper()->UpdateState(
GRPC_CHANNEL_READY, absl::make_unique<Picker>(p, this)); GRPC_CHANNEL_READY, absl::Status(), absl::make_unique<Picker>(p, this));
} else if (num_connecting_ > 0) { } else if (num_connecting_ > 0) {
/* 2) CONNECTING */ /* 2) CONNECTING */
p->channel_control_helper()->UpdateState( p->channel_control_helper()->UpdateState(
GRPC_CHANNEL_CONNECTING, GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique<QueuePicker>(p->Ref(DEBUG_LOCATION, "QueuePicker"))); absl::make_unique<QueuePicker>(p->Ref(DEBUG_LOCATION, "QueuePicker")));
} else if (num_transient_failure_ == num_subchannels()) { } else if (num_transient_failure_ == num_subchannels()) {
/* 3) TRANSIENT_FAILURE */ /* 3) TRANSIENT_FAILURE */
@ -335,7 +336,7 @@ void RoundRobin::RoundRobinSubchannelList::
"connections to all backends failing"), "connections to all backends failing"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
p->channel_control_helper()->UpdateState( p->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>(error)); absl::make_unique<TransientFailurePicker>(error));
} }
} }
@ -452,7 +453,7 @@ void RoundRobin::UpdateLocked(UpdateArgs args) {
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"), grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
channel_control_helper()->UpdateState( channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>(error)); absl::make_unique<TransientFailurePicker>(error));
subchannel_list_ = std::move(latest_pending_subchannel_list_); subchannel_list_ = std::move(latest_pending_subchannel_list_);
} else if (subchannel_list_ == nullptr) { } else if (subchannel_list_ == nullptr) {

@ -36,6 +36,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h" #include "src/core/lib/iomgr/work_serializer.h"
#include "src/core/lib/transport/error_utils.h"
namespace grpc_core { namespace grpc_core {
@ -146,6 +147,7 @@ class WeightedTargetLb : public LoadBalancingPolicy {
RefCountedPtr<SubchannelInterface> CreateSubchannel( RefCountedPtr<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override; const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state, void UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override; std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override; void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, void AddTraceEvent(TraceSeverity severity,
@ -160,7 +162,7 @@ class WeightedTargetLb : public LoadBalancingPolicy {
const grpc_channel_args* args); const grpc_channel_args* args);
void OnConnectivityStateUpdateLocked( void OnConnectivityStateUpdateLocked(
grpc_connectivity_state state, grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker); std::unique_ptr<SubchannelPicker> picker);
static void OnDelayedRemovalTimer(void* arg, grpc_error* error); static void OnDelayedRemovalTimer(void* arg, grpc_error* error);
@ -375,6 +377,7 @@ void WeightedTargetLb::UpdateStateLocked() {
this, ConnectivityStateName(connectivity_state)); this, ConnectivityStateName(connectivity_state));
} }
std::unique_ptr<SubchannelPicker> picker; std::unique_ptr<SubchannelPicker> picker;
absl::Status status;
switch (connectivity_state) { switch (connectivity_state) {
case GRPC_CHANNEL_READY: case GRPC_CHANNEL_READY:
picker = absl::make_unique<WeightedPicker>(std::move(picker_list)); picker = absl::make_unique<WeightedPicker>(std::move(picker_list));
@ -385,11 +388,15 @@ void WeightedTargetLb::UpdateStateLocked() {
absl::make_unique<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker")); absl::make_unique<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker"));
break; break;
default: default:
picker = absl::make_unique<TransientFailurePicker>( grpc_error* error = grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING( GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"weighted_target: all children report state TRANSIENT_FAILURE")); "weighted_target: all children report state TRANSIENT_FAILURE"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
status = grpc_error_to_absl_status(error);
picker = absl::make_unique<TransientFailurePicker>(error);
} }
channel_control_helper()->UpdateState(connectivity_state, std::move(picker)); channel_control_helper()->UpdateState(connectivity_state, status,
std::move(picker));
} }
// //
@ -508,15 +515,17 @@ void WeightedTargetLb::WeightedChild::ResetBackoffLocked() {
} }
void WeightedTargetLb::WeightedChild::OnConnectivityStateUpdateLocked( void WeightedTargetLb::WeightedChild::OnConnectivityStateUpdateLocked(
grpc_connectivity_state state, std::unique_ptr<SubchannelPicker> picker) { grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) {
// Cache the picker in the WeightedChild. // Cache the picker in the WeightedChild.
picker_wrapper_ = MakeRefCounted<ChildPickerWrapper>(std::move(picker)); picker_wrapper_ = MakeRefCounted<ChildPickerWrapper>(std::move(picker));
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_weighted_target_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_weighted_target_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[weighted_target_lb %p] WeightedChild %p %s: connectivity " "[weighted_target_lb %p] WeightedChild %p %s: connectivity "
"state update: state=%s picker_wrapper=%p", "state update: state=%s (%s) picker_wrapper=%p",
weighted_target_policy_.get(), this, name_.c_str(), weighted_target_policy_.get(), this, name_.c_str(),
ConnectivityStateName(state), picker_wrapper_.get()); ConnectivityStateName(state), status.ToString().c_str(),
picker_wrapper_.get());
} }
// If the child reports IDLE, immediately tell it to exit idle. // If the child reports IDLE, immediately tell it to exit idle.
if (state == GRPC_CHANNEL_IDLE) child_policy_->ExitIdleLocked(); if (state == GRPC_CHANNEL_IDLE) child_policy_->ExitIdleLocked();
@ -589,9 +598,11 @@ WeightedTargetLb::WeightedChild::Helper::CreateSubchannel(
} }
void WeightedTargetLb::WeightedChild::Helper::UpdateState( void WeightedTargetLb::WeightedChild::Helper::UpdateState(
grpc_connectivity_state state, std::unique_ptr<SubchannelPicker> picker) { grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) {
if (weighted_child_->weighted_target_policy_->shutting_down_) return; if (weighted_child_->weighted_target_policy_->shutting_down_) return;
weighted_child_->OnConnectivityStateUpdateLocked(state, std::move(picker)); weighted_child_->OnConnectivityStateUpdateLocked(state, status,
std::move(picker));
} }
void WeightedTargetLb::WeightedChild::Helper::RequestReresolution() { void WeightedTargetLb::WeightedChild::Helper::RequestReresolution() {

@ -29,6 +29,7 @@
#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/transport/error_utils.h"
namespace grpc_core { namespace grpc_core {
@ -79,7 +80,7 @@ class CdsLb : public LoadBalancingPolicy {
explicit Helper(RefCountedPtr<CdsLb> parent) : parent_(std::move(parent)) {} explicit Helper(RefCountedPtr<CdsLb> parent) : parent_(std::move(parent)) {}
RefCountedPtr<SubchannelInterface> CreateSubchannel( RefCountedPtr<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override; const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state, void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override; std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override; void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, void AddTraceEvent(TraceSeverity severity,
@ -209,7 +210,7 @@ void CdsLb::ClusterWatcher::OnError(grpc_error* error) {
// we keep running with the data we had previously. // we keep running with the data we had previously.
if (parent_->child_policy_ == nullptr) { if (parent_->child_policy_ == nullptr) {
parent_->channel_control_helper()->UpdateState( parent_->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>(error)); absl::make_unique<TransientFailurePicker>(error));
} else { } else {
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
@ -221,13 +222,15 @@ void CdsLb::ClusterWatcher::OnResourceDoesNotExist() {
"[cdslb %p] CDS resource for %s does not exist -- reporting " "[cdslb %p] CDS resource for %s does not exist -- reporting "
"TRANSIENT_FAILURE", "TRANSIENT_FAILURE",
parent_.get(), parent_->config_->cluster().c_str()); parent_.get(), parent_->config_->cluster().c_str());
grpc_error* error = grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("CDS resource \"", parent_->config_->cluster(),
"\" does not exist")
.c_str()),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
parent_->channel_control_helper()->UpdateState( parent_->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>( absl::make_unique<TransientFailurePicker>(error));
GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("CDS resource \"", parent_->config_->cluster(),
"\" does not exist")
.c_str())));
parent_->MaybeDestroyChildPolicyLocked(); parent_->MaybeDestroyChildPolicyLocked();
} }
@ -242,13 +245,16 @@ RefCountedPtr<SubchannelInterface> CdsLb::Helper::CreateSubchannel(
} }
void CdsLb::Helper::UpdateState(grpc_connectivity_state state, void CdsLb::Helper::UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) { std::unique_ptr<SubchannelPicker> picker) {
if (parent_->shutting_down_ || parent_->child_policy_ == nullptr) return; if (parent_->shutting_down_ || parent_->child_policy_ == nullptr) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
gpr_log(GPR_INFO, "[cdslb %p] state updated by child: %s", this, gpr_log(GPR_INFO,
ConnectivityStateName(state)); "[cdslb %p] state updated by child: %s message_state: (%s)", this,
ConnectivityStateName(state), status.ToString().c_str());
} }
parent_->channel_control_helper()->UpdateState(state, std::move(picker)); parent_->channel_control_helper()->UpdateState(state, status,
std::move(picker));
} }
void CdsLb::Helper::RequestReresolution() { void CdsLb::Helper::RequestReresolution() {

@ -40,6 +40,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h" #include "src/core/lib/iomgr/work_serializer.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/uri/uri_parser.h" #include "src/core/lib/uri/uri_parser.h"
#define GRPC_EDS_DEFAULT_FALLBACK_TIMEOUT 10000 #define GRPC_EDS_DEFAULT_FALLBACK_TIMEOUT 10000
@ -133,7 +134,7 @@ class EdsLb : public LoadBalancingPolicy {
RefCountedPtr<SubchannelInterface> CreateSubchannel( RefCountedPtr<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override; const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state, void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override; std::unique_ptr<SubchannelPicker> picker) override;
// This is a no-op, because we get the addresses from the xds // This is a no-op, because we get the addresses from the xds
// client, which is a watch-based API. // client, which is a watch-based API.
@ -214,6 +215,7 @@ class EdsLb : public LoadBalancingPolicy {
// The latest state and picker returned from the child policy. // The latest state and picker returned from the child policy.
grpc_connectivity_state child_state_; grpc_connectivity_state child_state_;
absl::Status child_status_;
RefCountedPtr<ChildPickerWrapper> child_picker_; RefCountedPtr<ChildPickerWrapper> child_picker_;
}; };
@ -265,16 +267,21 @@ RefCountedPtr<SubchannelInterface> EdsLb::Helper::CreateSubchannel(
} }
void EdsLb::Helper::UpdateState(grpc_connectivity_state state, void EdsLb::Helper::UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) { std::unique_ptr<SubchannelPicker> picker) {
if (eds_policy_->shutting_down_ || eds_policy_->child_policy_ == nullptr) { if (eds_policy_->shutting_down_ || eds_policy_->child_policy_ == nullptr) {
return; return;
} }
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
gpr_log(GPR_INFO, "[edslb %p] child policy updated state=%s picker=%p", gpr_log(GPR_INFO,
eds_policy_.get(), ConnectivityStateName(state), picker.get()); "[edslb %p] child policy updated state=%s (%s) "
"picker=%p",
eds_policy_.get(), ConnectivityStateName(state),
status.ToString().c_str(), picker.get());
} }
// Save the state and picker. // Save the state and picker.
eds_policy_->child_state_ = state; eds_policy_->child_state_ = state;
eds_policy_->child_status_ = status;
eds_policy_->child_picker_ = eds_policy_->child_picker_ =
MakeRefCounted<ChildPickerWrapper>(std::move(picker)); MakeRefCounted<ChildPickerWrapper>(std::move(picker));
// Wrap the picker in a DropPicker and pass it up. // Wrap the picker in a DropPicker and pass it up.
@ -339,7 +346,7 @@ class EdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
// we keep running with the data we had previously. // we keep running with the data we had previously.
if (eds_policy_->child_policy_ == nullptr) { if (eds_policy_->child_policy_ == nullptr) {
eds_policy_->channel_control_helper()->UpdateState( eds_policy_->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>(error)); absl::make_unique<TransientFailurePicker>(error));
} else { } else {
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
@ -351,11 +358,12 @@ class EdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
GPR_ERROR, GPR_ERROR,
"[edslb %p] EDS resource does not exist -- reporting TRANSIENT_FAILURE", "[edslb %p] EDS resource does not exist -- reporting TRANSIENT_FAILURE",
eds_policy_.get()); eds_policy_.get());
grpc_error* error = grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("EDS resource does not exist"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
eds_policy_->channel_control_helper()->UpdateState( eds_policy_->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>( absl::make_unique<TransientFailurePicker>(error));
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"EDS resource does not exist")));
eds_policy_->MaybeDestroyChildPolicyLocked(); eds_policy_->MaybeDestroyChildPolicyLocked();
} }
@ -688,7 +696,7 @@ EdsLb::CreateChildPolicyConfigLocked() {
error), error),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL); GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL);
channel_control_helper()->UpdateState( channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>(error)); absl::make_unique<TransientFailurePicker>(error));
return nullptr; return nullptr;
} }
@ -769,13 +777,13 @@ void EdsLb::MaybeUpdateDropPickerLocked() {
// If we're dropping all calls, report READY, regardless of what (or // If we're dropping all calls, report READY, regardless of what (or
// whether) the child has reported. // whether) the child has reported.
if (drop_config_ != nullptr && drop_config_->drop_all()) { if (drop_config_ != nullptr && drop_config_->drop_all()) {
channel_control_helper()->UpdateState(GRPC_CHANNEL_READY, channel_control_helper()->UpdateState(GRPC_CHANNEL_READY, absl::Status(),
absl::make_unique<DropPicker>(this)); absl::make_unique<DropPicker>(this));
return; return;
} }
// Update only if we have a child picker. // Update only if we have a child picker.
if (child_picker_ != nullptr) { if (child_picker_ != nullptr) {
channel_control_helper()->UpdateState(child_state_, channel_control_helper()->UpdateState(child_state_, child_status_,
absl::make_unique<DropPicker>(this)); absl::make_unique<DropPicker>(this));
} }
} }

@ -120,7 +120,7 @@ class LrsLb : public LoadBalancingPolicy {
RefCountedPtr<SubchannelInterface> CreateSubchannel( RefCountedPtr<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override; const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state, void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override; std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override; void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, void AddTraceEvent(TraceSeverity severity,
@ -157,6 +157,7 @@ class LrsLb : public LoadBalancingPolicy {
// Latest state and picker reported by the child policy. // Latest state and picker reported by the child policy.
grpc_connectivity_state state_ = GRPC_CHANNEL_IDLE; grpc_connectivity_state state_ = GRPC_CHANNEL_IDLE;
absl::Status status_;
RefCountedPtr<RefCountedPicker> picker_; RefCountedPtr<RefCountedPicker> picker_;
}; };
@ -266,10 +267,14 @@ void LrsLb::MaybeUpdatePickerLocked() {
auto lrs_picker = auto lrs_picker =
absl::make_unique<LoadReportingPicker>(picker_, locality_stats_); absl::make_unique<LoadReportingPicker>(picker_, locality_stats_);
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) {
gpr_log(GPR_INFO, "[lrs_lb %p] updating connectivity: state=%s picker=%p", gpr_log(
this, ConnectivityStateName(state_), lrs_picker.get()); GPR_INFO,
"[lrs_lb %p] updating connectivity: state=%s status=(%s) picker=%p",
this, ConnectivityStateName(state_), status_.ToString().c_str(),
lrs_picker.get());
} }
channel_control_helper()->UpdateState(state_, std::move(lrs_picker)); channel_control_helper()->UpdateState(state_, status_,
std::move(lrs_picker));
} }
} }
@ -325,15 +330,19 @@ RefCountedPtr<SubchannelInterface> LrsLb::Helper::CreateSubchannel(
} }
void LrsLb::Helper::UpdateState(grpc_connectivity_state state, void LrsLb::Helper::UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) { std::unique_ptr<SubchannelPicker> picker) {
if (lrs_policy_->shutting_down_) return; if (lrs_policy_->shutting_down_) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) {
gpr_log(GPR_INFO, gpr_log(
"[lrs_lb %p] child connectivity state update: state=%s picker=%p", GPR_INFO,
lrs_policy_.get(), ConnectivityStateName(state), picker.get()); "[lrs_lb %p] child connectivity state update: state=%s (%s) picker=%p",
lrs_policy_.get(), ConnectivityStateName(state),
status.ToString().c_str(), picker.get());
} }
// Save the state and picker. // Save the state and picker.
lrs_policy_->state_ = state; lrs_policy_->state_ = state;
lrs_policy_->status_ = status;
lrs_policy_->picker_ = MakeRefCounted<RefCountedPicker>(std::move(picker)); lrs_policy_->picker_ = MakeRefCounted<RefCountedPicker>(std::move(picker));
// Wrap the picker and return it to the channel. // Wrap the picker and return it to the channel.
lrs_policy_->MaybeUpdatePickerLocked(); lrs_policy_->MaybeUpdatePickerLocked();

@ -42,6 +42,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h" #include "src/core/lib/iomgr/work_serializer.h"
#include "src/core/lib/transport/error_utils.h"
#define GRPC_XDS_ROUTING_CHILD_RETENTION_INTERVAL_MS (15 * 60 * 1000) #define GRPC_XDS_ROUTING_CHILD_RETENTION_INTERVAL_MS (15 * 60 * 1000)
@ -165,6 +166,7 @@ class XdsRoutingLb : public LoadBalancingPolicy {
RefCountedPtr<SubchannelInterface> CreateSubchannel( RefCountedPtr<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override; const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state, void UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override; std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override; void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, void AddTraceEvent(TraceSeverity severity,
@ -464,6 +466,7 @@ void XdsRoutingLb::UpdateStateLocked() {
ConnectivityStateName(connectivity_state)); ConnectivityStateName(connectivity_state));
} }
std::unique_ptr<SubchannelPicker> picker; std::unique_ptr<SubchannelPicker> picker;
absl::Status status;
switch (connectivity_state) { switch (connectivity_state) {
case GRPC_CHANNEL_READY: { case GRPC_CHANNEL_READY: {
RoutePicker::RouteTable route_table; RoutePicker::RouteTable route_table;
@ -493,12 +496,15 @@ void XdsRoutingLb::UpdateStateLocked() {
absl::make_unique<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker")); absl::make_unique<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker"));
break; break;
default: default:
picker = absl::make_unique<TransientFailurePicker>(grpc_error_set_int( grpc_error* error = grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING( GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"TRANSIENT_FAILURE from XdsRoutingLb"), "TRANSIENT_FAILURE from XdsRoutingLb"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE)); GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
status = grpc_error_to_absl_status(error);
picker = absl::make_unique<TransientFailurePicker>(error);
} }
channel_control_helper()->UpdateState(connectivity_state, std::move(picker)); channel_control_helper()->UpdateState(connectivity_state, status,
std::move(picker));
} }
// //
@ -654,13 +660,15 @@ XdsRoutingLb::XdsRoutingChild::Helper::CreateSubchannel(
} }
void XdsRoutingLb::XdsRoutingChild::Helper::UpdateState( void XdsRoutingLb::XdsRoutingChild::Helper::UpdateState(
grpc_connectivity_state state, std::unique_ptr<SubchannelPicker> picker) { grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[xds_routing_lb %p] child %s: received update: state=%s picker=%p", "[xds_routing_lb %p] child %s: received update: state=%s (%s) "
"picker=%p",
xds_routing_child_->xds_routing_policy_.get(), xds_routing_child_->xds_routing_policy_.get(),
xds_routing_child_->name_.c_str(), ConnectivityStateName(state), xds_routing_child_->name_.c_str(), ConnectivityStateName(state),
picker.get()); status.ToString().c_str(), picker.get());
} }
if (xds_routing_child_->xds_routing_policy_->shutting_down_) return; if (xds_routing_child_->xds_routing_policy_->shutting_down_) return;
// Cache the picker in the XdsRoutingChild. // Cache the picker in the XdsRoutingChild.

@ -114,10 +114,11 @@ class ResolvingLoadBalancingPolicy::ResolvingControlHelper
return parent_->channel_control_helper()->CreateSubchannel(args); return parent_->channel_control_helper()->CreateSubchannel(args);
} }
void UpdateState(grpc_connectivity_state state, void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override { std::unique_ptr<SubchannelPicker> picker) override {
if (parent_->resolver_ == nullptr) return; // Shutting down. if (parent_->resolver_ == nullptr) return; // Shutting down.
parent_->channel_control_helper()->UpdateState(state, std::move(picker)); parent_->channel_control_helper()->UpdateState(state, status,
std::move(picker));
} }
void RequestReresolution() override { void RequestReresolution() override {
@ -160,7 +161,7 @@ ResolvingLoadBalancingPolicy::ResolvingLoadBalancingPolicy(
if (GRPC_TRACE_FLAG_ENABLED(*tracer_)) { if (GRPC_TRACE_FLAG_ENABLED(*tracer_)) {
gpr_log(GPR_INFO, "resolving_lb=%p: starting name resolution", this); gpr_log(GPR_INFO, "resolving_lb=%p: starting name resolution", this);
} }
channel_control_helper()->UpdateState(GRPC_CHANNEL_CONNECTING, channel_control_helper()->UpdateState(GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique<QueuePicker>(Ref())); absl::make_unique<QueuePicker>(Ref()));
resolver_->StartLocked(); resolver_->StartLocked();
} }
@ -214,7 +215,7 @@ void ResolvingLoadBalancingPolicy::OnResolverError(grpc_error* error) {
"Resolver transient failure", &error, 1); "Resolver transient failure", &error, 1);
helper_->ResolverTransientFailure(GRPC_ERROR_REF(state_error)); helper_->ResolverTransientFailure(GRPC_ERROR_REF(state_error));
channel_control_helper()->UpdateState( channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(state_error),
absl::make_unique<TransientFailurePicker>(state_error)); absl::make_unique<TransientFailurePicker>(state_error));
} }
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);

@ -26,6 +26,8 @@
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include "absl/strings/str_format.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
@ -325,7 +327,8 @@ class Subchannel::ConnectedSubchannelStateWatcher
} }
private: private:
void OnConnectivityStateChange(grpc_connectivity_state new_state) override { void OnConnectivityStateChange(grpc_connectivity_state new_state,
const absl::Status& status) override {
Subchannel* c = subchannel_; Subchannel* c = subchannel_;
MutexLock lock(&c->mu_); MutexLock lock(&c->mu_);
switch (new_state) { switch (new_state) {
@ -343,7 +346,15 @@ class Subchannel::ConnectedSubchannelStateWatcher
if (c->channelz_node() != nullptr) { if (c->channelz_node() != nullptr) {
c->channelz_node()->SetChildSocket(nullptr); c->channelz_node()->SetChildSocket(nullptr);
} }
c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE); // We need to construct our own status if the underlying state was
// shutdown since the accompanying status will be StatusCode::OK
// otherwise.
c->SetConnectivityStateLocked(
GRPC_CHANNEL_TRANSIENT_FAILURE,
new_state == GRPC_CHANNEL_SHUTDOWN
? absl::Status(absl::StatusCode::kUnavailable,
"Subchannel has disconnected.")
: status);
c->backoff_begun_ = false; c->backoff_begun_ = false;
c->backoff_.Reset(); c->backoff_.Reset();
} }
@ -354,7 +365,7 @@ class Subchannel::ConnectedSubchannelStateWatcher
// a callback for READY, because that was the state we started // a callback for READY, because that was the state we started
// this watch from. And a connected subchannel should never go // this watch from. And a connected subchannel should never go
// from READY to CONNECTING or IDLE. // from READY to CONNECTING or IDLE.
c->SetConnectivityStateLocked(new_state); c->SetConnectivityStateLocked(new_state, status);
} }
} }
} }
@ -368,14 +379,15 @@ class Subchannel::AsyncWatcherNotifierLocked {
public: public:
AsyncWatcherNotifierLocked( AsyncWatcherNotifierLocked(
RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher, RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher,
Subchannel* subchannel, grpc_connectivity_state state) Subchannel* subchannel, grpc_connectivity_state state,
const absl::Status& status)
: watcher_(std::move(watcher)) { : watcher_(std::move(watcher)) {
RefCountedPtr<ConnectedSubchannel> connected_subchannel; RefCountedPtr<ConnectedSubchannel> connected_subchannel;
if (state == GRPC_CHANNEL_READY) { if (state == GRPC_CHANNEL_READY) {
connected_subchannel = subchannel->connected_subchannel_; connected_subchannel = subchannel->connected_subchannel_;
} }
watcher_->PushConnectivityStateChange( watcher_->PushConnectivityStateChange(
{state, std::move(connected_subchannel)}); {state, status, std::move(connected_subchannel)});
ExecCtx::Run( ExecCtx::Run(
DEBUG_LOCATION, DEBUG_LOCATION,
GRPC_CLOSURE_INIT(&closure_, GRPC_CLOSURE_INIT(&closure_,
@ -409,9 +421,10 @@ void Subchannel::ConnectivityStateWatcherList::RemoveWatcherLocked(
} }
void Subchannel::ConnectivityStateWatcherList::NotifyLocked( void Subchannel::ConnectivityStateWatcherList::NotifyLocked(
Subchannel* subchannel, grpc_connectivity_state state) { Subchannel* subchannel, grpc_connectivity_state state,
const absl::Status& status) {
for (const auto& p : watchers_) { for (const auto& p : watchers_) {
new AsyncWatcherNotifierLocked(p.second, subchannel, state); new AsyncWatcherNotifierLocked(p.second, subchannel, state, status);
} }
} }
@ -450,7 +463,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
grpc_connectivity_state initial_state, grpc_connectivity_state initial_state,
RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher) { RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher) {
if (state_ != initial_state) { if (state_ != initial_state) {
new AsyncWatcherNotifierLocked(watcher, subchannel_, state_); new AsyncWatcherNotifierLocked(watcher, subchannel_, state_, status_);
} }
watcher_list_.AddWatcherLocked(std::move(watcher)); watcher_list_.AddWatcherLocked(std::move(watcher));
} }
@ -462,7 +475,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
bool HasWatchers() const { return !watcher_list_.empty(); } bool HasWatchers() const { return !watcher_list_.empty(); }
void NotifyLocked(grpc_connectivity_state state) { void NotifyLocked(grpc_connectivity_state state, const absl::Status& status) {
if (state == GRPC_CHANNEL_READY) { if (state == GRPC_CHANNEL_READY) {
// If we had not already notified for CONNECTING state, do so now. // If we had not already notified for CONNECTING state, do so now.
// (We may have missed this earlier, because if the transition // (We may have missed this earlier, because if the transition
@ -470,13 +483,15 @@ class Subchannel::HealthWatcherMap::HealthWatcher
// subchannel may not have sent us a notification for CONNECTING.) // subchannel may not have sent us a notification for CONNECTING.)
if (state_ != GRPC_CHANNEL_CONNECTING) { if (state_ != GRPC_CHANNEL_CONNECTING) {
state_ = GRPC_CHANNEL_CONNECTING; state_ = GRPC_CHANNEL_CONNECTING;
watcher_list_.NotifyLocked(subchannel_, state_); status_ = status;
watcher_list_.NotifyLocked(subchannel_, state_, status);
} }
// If we've become connected, start health checking. // If we've become connected, start health checking.
StartHealthCheckingLocked(); StartHealthCheckingLocked();
} else { } else {
state_ = state; state_ = state;
watcher_list_.NotifyLocked(subchannel_, state_); status_ = status;
watcher_list_.NotifyLocked(subchannel_, state_, status);
// We're not connected, so stop health checking. // We're not connected, so stop health checking.
health_check_client_.reset(); health_check_client_.reset();
} }
@ -489,11 +504,13 @@ class Subchannel::HealthWatcherMap::HealthWatcher
} }
private: private:
void OnConnectivityStateChange(grpc_connectivity_state new_state) override { void OnConnectivityStateChange(grpc_connectivity_state new_state,
const absl::Status& status) override {
MutexLock lock(&subchannel_->mu_); MutexLock lock(&subchannel_->mu_);
if (new_state != GRPC_CHANNEL_SHUTDOWN && health_check_client_ != nullptr) { if (new_state != GRPC_CHANNEL_SHUTDOWN && health_check_client_ != nullptr) {
state_ = new_state; state_ = new_state;
watcher_list_.NotifyLocked(subchannel_, new_state); status_ = status;
watcher_list_.NotifyLocked(subchannel_, new_state, status);
} }
} }
@ -508,6 +525,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
grpc_core::UniquePtr<char> health_check_service_name_; grpc_core::UniquePtr<char> health_check_service_name_;
OrphanablePtr<HealthCheckClient> health_check_client_; OrphanablePtr<HealthCheckClient> health_check_client_;
grpc_connectivity_state state_; grpc_connectivity_state state_;
absl::Status status_;
ConnectivityStateWatcherList watcher_list_; ConnectivityStateWatcherList watcher_list_;
}; };
@ -547,9 +565,10 @@ void Subchannel::HealthWatcherMap::RemoveWatcherLocked(
if (!it->second->HasWatchers()) map_.erase(it); if (!it->second->HasWatchers()) map_.erase(it);
} }
void Subchannel::HealthWatcherMap::NotifyLocked(grpc_connectivity_state state) { void Subchannel::HealthWatcherMap::NotifyLocked(grpc_connectivity_state state,
const absl::Status& status) {
for (const auto& p : map_) { for (const auto& p : map_) {
p.second->NotifyLocked(state); p.second->NotifyLocked(state, status);
} }
} }
@ -826,7 +845,7 @@ void Subchannel::WatchConnectivityState(
} }
if (health_check_service_name == nullptr) { if (health_check_service_name == nullptr) {
if (state_ != initial_state) { if (state_ != initial_state) {
new AsyncWatcherNotifierLocked(watcher, this, state_); new AsyncWatcherNotifierLocked(watcher, this, state_, status_);
} }
watcher_list_.AddWatcherLocked(std::move(watcher)); watcher_list_.AddWatcherLocked(std::move(watcher));
} else { } else {
@ -928,8 +947,10 @@ const char* SubchannelConnectivityStateChangeString(
} // namespace } // namespace
// Note: Must be called with a state that is different from the current state. // Note: Must be called with a state that is different from the current state.
void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state) { void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state,
const absl::Status& status) {
state_ = state; state_ = state;
status_ = status;
if (channelz_node_ != nullptr) { if (channelz_node_ != nullptr) {
channelz_node_->UpdateConnectivityState(state); channelz_node_->UpdateConnectivityState(state);
channelz_node_->AddTraceEvent( channelz_node_->AddTraceEvent(
@ -938,9 +959,9 @@ void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state) {
SubchannelConnectivityStateChangeString(state))); SubchannelConnectivityStateChangeString(state)));
} }
// Notify non-health watchers. // Notify non-health watchers.
watcher_list_.NotifyLocked(this, state); watcher_list_.NotifyLocked(this, state, status);
// Notify health watchers. // Notify health watchers.
health_watcher_map_.NotifyLocked(state); health_watcher_map_.NotifyLocked(state, status);
} }
void Subchannel::MaybeStartConnectingLocked() { void Subchannel::MaybeStartConnectingLocked() {
@ -1012,7 +1033,7 @@ void Subchannel::ContinueConnectingLocked() {
next_attempt_deadline_ = backoff_.NextAttemptTime(); next_attempt_deadline_ = backoff_.NextAttemptTime();
args.deadline = std::max(next_attempt_deadline_, min_deadline); args.deadline = std::max(next_attempt_deadline_, min_deadline);
args.channel_args = args_; args.channel_args = args_;
SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING); SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING, absl::Status());
connector_->Connect(args, &connecting_result_, &on_connecting_finished_); connector_->Connect(args, &connecting_result_, &on_connecting_finished_);
} }
@ -1031,7 +1052,8 @@ void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) {
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
} else { } else {
gpr_log(GPR_INFO, "Connect failed: %s", grpc_error_string(error)); gpr_log(GPR_INFO, "Connect failed: %s", grpc_error_string(error));
c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE); c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE,
grpc_error_to_absl_status(error));
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
} }
} }
@ -1091,7 +1113,7 @@ bool Subchannel::PublishTransportLocked() {
connected_subchannel_->StartWatch( connected_subchannel_->StartWatch(
pollset_set_, MakeOrphanable<ConnectedSubchannelStateWatcher>(this)); pollset_set_, MakeOrphanable<ConnectedSubchannelStateWatcher>(this));
// Report initial state. // Report initial state.
SetConnectivityStateLocked(GRPC_CHANNEL_READY); SetConnectivityStateLocked(GRPC_CHANNEL_READY, absl::Status());
return true; return true;
} }

@ -182,6 +182,7 @@ class Subchannel {
public: public:
struct ConnectivityStateChange { struct ConnectivityStateChange {
grpc_connectivity_state state; grpc_connectivity_state state;
absl::Status status;
RefCountedPtr<ConnectedSubchannel> connected_subchannel; RefCountedPtr<ConnectedSubchannel> connected_subchannel;
}; };
@ -306,7 +307,8 @@ class Subchannel {
void RemoveWatcherLocked(ConnectivityStateWatcherInterface* watcher); void RemoveWatcherLocked(ConnectivityStateWatcherInterface* watcher);
// Notifies all watchers in the list about a change to state. // Notifies all watchers in the list about a change to state.
void NotifyLocked(Subchannel* subchannel, grpc_connectivity_state state); void NotifyLocked(Subchannel* subchannel, grpc_connectivity_state state,
const absl::Status& status);
void Clear() { watchers_.clear(); } void Clear() { watchers_.clear(); }
@ -339,7 +341,8 @@ class Subchannel {
ConnectivityStateWatcherInterface* watcher); ConnectivityStateWatcherInterface* watcher);
// Notifies the watcher when the subchannel's state changes. // Notifies the watcher when the subchannel's state changes.
void NotifyLocked(grpc_connectivity_state state); void NotifyLocked(grpc_connectivity_state state,
const absl::Status& status);
grpc_connectivity_state CheckConnectivityStateLocked( grpc_connectivity_state CheckConnectivityStateLocked(
Subchannel* subchannel, const char* health_check_service_name); Subchannel* subchannel, const char* health_check_service_name);
@ -357,7 +360,8 @@ class Subchannel {
class AsyncWatcherNotifierLocked; class AsyncWatcherNotifierLocked;
// Sets the subchannel's connectivity state to \a state. // Sets the subchannel's connectivity state to \a state.
void SetConnectivityStateLocked(grpc_connectivity_state state); void SetConnectivityStateLocked(grpc_connectivity_state state,
const absl::Status& status);
// Methods for connection. // Methods for connection.
void MaybeStartConnectingLocked(); void MaybeStartConnectingLocked();
@ -400,6 +404,7 @@ class Subchannel {
// Connectivity state tracking. // Connectivity state tracking.
grpc_connectivity_state state_ = GRPC_CHANNEL_IDLE; grpc_connectivity_state state_ = GRPC_CHANNEL_IDLE;
absl::Status status_;
// The list of watchers without a health check service name. // The list of watchers without a health check service name.
ConnectivityStateWatcherList watcher_list_; ConnectivityStateWatcherList watcher_list_;
// The map of watchers with health check service names. // The map of watchers with health check service names.

@ -73,7 +73,7 @@ grpc_channel* CreateXdsChannel(const XdsBootstrap& bootstrap,
if (!bootstrap.server().channel_creds.empty()) { if (!bootstrap.server().channel_creds.empty()) {
for (size_t i = 0; i < bootstrap.server().channel_creds.size(); ++i) { for (size_t i = 0; i < bootstrap.server().channel_creds.size(); ++i) {
if (bootstrap.server().channel_creds[i].type == "google_default") { if (bootstrap.server().channel_creds[i].type == "google_default") {
creds = grpc_google_default_credentials_create(); creds = grpc_google_default_credentials_create(nullptr);
break; break;
} else if (bootstrap.server().channel_creds[i].type == "fake") { } else if (bootstrap.server().channel_creds[i].type == "fake") {
creds = grpc_fake_transport_security_credentials_create(); creds = grpc_fake_transport_security_credentials_create();

@ -398,13 +398,15 @@ class XdsClient::ChannelState::StateWatcher
parent_(std::move(parent)) {} parent_(std::move(parent)) {}
private: private:
void OnConnectivityStateChange(grpc_connectivity_state new_state) override { void OnConnectivityStateChange(grpc_connectivity_state new_state,
const absl::Status& status) override {
if (!parent_->shutting_down_ && if (!parent_->shutting_down_ &&
new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
// In TRANSIENT_FAILURE. Notify all watchers of error. // In TRANSIENT_FAILURE. Notify all watchers of error.
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[xds_client %p] xds channel in state TRANSIENT_FAILURE", "[xds_client %p] xds channel in state:TRANSIENT_FAILURE "
parent_->xds_client()); "status_message:(%s)",
parent_->xds_client(), status.ToString().c_str());
parent_->xds_client()->NotifyOnError(GRPC_ERROR_CREATE_FROM_STATIC_STRING( parent_->xds_client()->NotifyOnError(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"xds channel in TRANSIENT_FAILURE")); "xds channel in TRANSIENT_FAILURE"));
} }

@ -229,7 +229,8 @@ class ConnectivityWatcher : public AsyncConnectivityStateWatcherInterface {
} }
private: private:
void OnConnectivityStateChange(grpc_connectivity_state new_state) override { void OnConnectivityStateChange(grpc_connectivity_state new_state,
const absl::Status& /* status */) override {
if (new_state != GRPC_CHANNEL_SHUTDOWN) return; if (new_state != GRPC_CHANNEL_SHUTDOWN) return;
{ {
MutexLock lock(&chand_->max_age_timer_mu); MutexLock lock(&chand_->max_age_timer_mu);

@ -18,6 +18,8 @@
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "absl/strings/str_format.h"
#include <grpc/slice_buffer.h> #include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
@ -29,7 +31,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "absl/strings/str_format.h"
#include "src/core/ext/transport/chttp2/transport/context_list.h" #include "src/core/ext/transport/chttp2/transport/context_list.h"
#include "src/core/ext/transport/chttp2/transport/frame_data.h" #include "src/core/ext/transport/chttp2/transport/frame_data.h"
#include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/ext/transport/chttp2/transport/internal.h"
@ -125,6 +126,7 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t);
static void connectivity_state_set(grpc_chttp2_transport* t, static void connectivity_state_set(grpc_chttp2_transport* t,
grpc_connectivity_state state, grpc_connectivity_state state,
const absl::Status& status,
const char* reason); const char* reason);
static void benign_reclaimer(void* t, grpc_error* error); static void benign_reclaimer(void* t, grpc_error* error);
@ -560,7 +562,8 @@ static void close_transport_locked(grpc_chttp2_transport* t,
} }
GPR_ASSERT(error != GRPC_ERROR_NONE); GPR_ASSERT(error != GRPC_ERROR_NONE);
t->closed_with_error = GRPC_ERROR_REF(error); t->closed_with_error = GRPC_ERROR_REF(error);
connectivity_state_set(t, GRPC_CHANNEL_SHUTDOWN, "close_transport"); connectivity_state_set(t, GRPC_CHANNEL_SHUTDOWN, absl::Status(),
"close_transport");
if (t->ping_state.is_delayed_ping_timer_set) { if (t->ping_state.is_delayed_ping_timer_set) {
grpc_timer_cancel(&t->ping_state.delayed_ping_timer); grpc_timer_cancel(&t->ping_state.delayed_ping_timer);
} }
@ -1103,9 +1106,11 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
: static_cast<grpc_millis>(current_keepalive_time_ms * : static_cast<grpc_millis>(current_keepalive_time_ms *
KEEPALIVE_TIME_BACKOFF_MULTIPLIER); KEEPALIVE_TIME_BACKOFF_MULTIPLIER);
} }
absl::Status status = grpc_error_to_absl_status(t->goaway_error);
// lie: use transient failure from the transport to indicate goaway has been // lie: use transient failure from the transport to indicate goaway has been
// received // received.
connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE, "got_goaway"); connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE, status,
"got_goaway");
} }
static void maybe_start_some_streams(grpc_chttp2_transport* t) { static void maybe_start_some_streams(grpc_chttp2_transport* t) {
@ -1140,6 +1145,8 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) {
if (t->next_stream_id >= MAX_CLIENT_STREAM_ID) { if (t->next_stream_id >= MAX_CLIENT_STREAM_ID) {
connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE, connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE,
absl::Status(absl::StatusCode::kUnavailable,
"Transport Stream IDs exhausted"),
"no_more_stream_ids"); "no_more_stream_ids");
} }
@ -2915,10 +2922,11 @@ static void keepalive_watchdog_fired_locked(void* arg, grpc_error* error) {
static void connectivity_state_set(grpc_chttp2_transport* t, static void connectivity_state_set(grpc_chttp2_transport* t,
grpc_connectivity_state state, grpc_connectivity_state state,
const absl::Status& status,
const char* reason) { const char* reason) {
GRPC_CHTTP2_IF_TRACING( GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_INFO, "transport %p set connectivity_state=%d", t, state)); gpr_log(GPR_INFO, "transport %p set connectivity_state=%d", t, state));
t->state_tracker.SetState(state, reason); t->state_tracker.SetState(state, status, reason);
} }
// //

@ -1132,7 +1132,8 @@ void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
void close_transport_locked(inproc_transport* t) { void close_transport_locked(inproc_transport* t) {
INPROC_LOG(GPR_INFO, "close_transport %p %d", t, t->is_closed); INPROC_LOG(GPR_INFO, "close_transport %p %d", t, t->is_closed);
t->state_tracker.SetState(GRPC_CHANNEL_SHUTDOWN, "close transport"); t->state_tracker.SetState(GRPC_CHANNEL_SHUTDOWN, absl::Status(),
"close transport");
if (!t->is_closed) { if (!t->is_closed) {
t->is_closed = true; t->is_closed = true;
/* Also end all streams on this transport */ /* Also end all streams on this transport */

@ -49,6 +49,8 @@ using grpc_core::Json;
/* -- Constants. -- */ /* -- Constants. -- */
#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal." #define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal."
#define GRPC_GOOGLE_CREDENTIAL_CREATION_ERROR \
"Failed to create Google credentials"
/* -- Default credentials. -- */ /* -- Default credentials. -- */
@ -57,7 +59,6 @@ using grpc_core::Json;
* means the detection is done via network test that is unreliable and the * means the detection is done via network test that is unreliable and the
* unreliable result should not be referred by successive calls. */ * unreliable result should not be referred by successive calls. */
static int g_metadata_server_available = 0; static int g_metadata_server_available = 0;
static int g_is_on_gce = 0;
static gpr_mu g_state_mu; static gpr_mu g_state_mu;
/* Protect a metadata_server_detector instance that can be modified by more than /* Protect a metadata_server_detector instance that can be modified by more than
* one gRPC threads */ * one gRPC threads */
@ -89,7 +90,7 @@ grpc_google_default_channel_credentials::create_security_connector(
bool use_alts = bool use_alts =
is_grpclb_load_balancer || is_backend_from_grpclb_load_balancer; is_grpclb_load_balancer || is_backend_from_grpclb_load_balancer;
/* Return failure if ALTS is selected but not running on GCE. */ /* Return failure if ALTS is selected but not running on GCE. */
if (use_alts && !g_is_on_gce) { if (use_alts && alts_creds_ == nullptr) {
gpr_log(GPR_ERROR, "ALTS is selected, but not running on GCE."); gpr_log(GPR_ERROR, "ALTS is selected, but not running on GCE.");
return nullptr; return nullptr;
} }
@ -273,59 +274,78 @@ end:
return error; return error;
} }
grpc_channel_credentials* grpc_google_default_credentials_create() { static void update_tenancy() {
grpc_channel_credentials* result = nullptr; gpr_once_init(&g_once, init_default_credentials);
grpc_core::RefCountedPtr<grpc_call_credentials> call_creds; grpc_core::MutexLock lock(&g_state_mu);
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Failed to create Google credentials");
grpc_error* err;
grpc_core::ExecCtx exec_ctx;
GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ()); /* Try a platform-provided hint for GCE. */
if (!g_metadata_server_available) {
g_metadata_server_available = g_gce_tenancy_checker();
}
/* TODO: Add a platform-provided hint for GAE. */
gpr_once_init(&g_once, init_default_credentials); /* Do a network test for metadata server. */
if (!g_metadata_server_available) {
g_metadata_server_available = is_metadata_server_reachable();
}
}
static bool metadata_server_available() {
grpc_core::MutexLock lock(&g_state_mu);
return static_cast<bool>(g_metadata_server_available);
}
static grpc_core::RefCountedPtr<grpc_call_credentials> make_default_call_creds(
grpc_error** error) {
grpc_core::RefCountedPtr<grpc_call_credentials> call_creds;
grpc_error* err;
/* First, try the environment variable. */ /* First, try the environment variable. */
char* path_from_env = gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR); char* path_from_env = gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR);
if (path_from_env != nullptr) { if (path_from_env != nullptr) {
err = create_default_creds_from_path(path_from_env, &call_creds); err = create_default_creds_from_path(path_from_env, &call_creds);
gpr_free(path_from_env); gpr_free(path_from_env);
if (err == GRPC_ERROR_NONE) goto end; if (err == GRPC_ERROR_NONE) return call_creds;
error = grpc_error_add_child(error, err); *error = grpc_error_add_child(*error, err);
} }
/* Then the well-known file. */ /* Then the well-known file. */
err = create_default_creds_from_path( err = create_default_creds_from_path(
grpc_get_well_known_google_credentials_file_path(), &call_creds); grpc_get_well_known_google_credentials_file_path(), &call_creds);
if (err == GRPC_ERROR_NONE) goto end; if (err == GRPC_ERROR_NONE) return call_creds;
error = grpc_error_add_child(error, err); *error = grpc_error_add_child(*error, err);
gpr_mu_lock(&g_state_mu); update_tenancy();
/* Try a platform-provided hint for GCE. */ if (metadata_server_available()) {
if (!g_metadata_server_available) {
g_is_on_gce = g_gce_tenancy_checker();
g_metadata_server_available = g_is_on_gce;
}
/* TODO: Add a platform-provided hint for GAE. */
/* Do a network test for metadata server. */
if (!g_metadata_server_available) {
g_metadata_server_available = is_metadata_server_reachable();
}
gpr_mu_unlock(&g_state_mu);
if (g_metadata_server_available) {
call_creds = grpc_core::RefCountedPtr<grpc_call_credentials>( call_creds = grpc_core::RefCountedPtr<grpc_call_credentials>(
grpc_google_compute_engine_credentials_create(nullptr)); grpc_google_compute_engine_credentials_create(nullptr));
if (call_creds == nullptr) { if (call_creds == nullptr) {
error = grpc_error_add_child( *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( GRPC_GOOGLE_CREDENTIAL_CREATION_ERROR);
"Failed to get credentials from network")); *error = grpc_error_add_child(
*error, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Failed to get credentials from network"));
} }
} }
end: return call_creds;
}
grpc_channel_credentials* grpc_google_default_credentials_create(
grpc_call_credentials* call_credentials) {
grpc_channel_credentials* result = nullptr;
grpc_core::RefCountedPtr<grpc_call_credentials> call_creds(call_credentials);
grpc_error* error = nullptr;
grpc_core::ExecCtx exec_ctx;
GRPC_API_TRACE("grpc_google_default_credentials_create(%p)", 1,
(call_credentials));
if (call_creds == nullptr) {
call_creds = make_default_call_creds(&error);
}
if (call_creds != nullptr) { if (call_creds != nullptr) {
/* Create google default credentials. */ /* Create google default credentials. */
grpc_channel_credentials* ssl_creds = grpc_channel_credentials* ssl_creds =
@ -338,10 +358,8 @@ end:
grpc_alts_credentials_options_destroy(options); grpc_alts_credentials_options_destroy(options);
auto creds = auto creds =
grpc_core::MakeRefCounted<grpc_google_default_channel_credentials>( grpc_core::MakeRefCounted<grpc_google_default_channel_credentials>(
alts_creds != nullptr ? alts_creds->Ref() : nullptr, grpc_core::RefCountedPtr<grpc_channel_credentials>(alts_creds),
ssl_creds != nullptr ? ssl_creds->Ref() : nullptr); grpc_core::RefCountedPtr<grpc_channel_credentials>(ssl_creds));
if (ssl_creds) ssl_creds->Unref();
if (alts_creds) alts_creds->Unref();
result = grpc_composite_channel_credentials_create( result = grpc_composite_channel_credentials_create(
creds.get(), call_creds.get(), nullptr); creds.get(), call_creds.get(), nullptr);
GPR_ASSERT(result != nullptr); GPR_ASSERT(result != nullptr);

@ -1271,7 +1271,8 @@ class ConnectivityWatcher : public AsyncConnectivityStateWatcherInterface {
} }
private: private:
void OnConnectivityStateChange(grpc_connectivity_state new_state) override { void OnConnectivityStateChange(grpc_connectivity_state new_state,
const absl::Status& /* status */) override {
// Don't do anything until we are being shut down. // Don't do anything until we are being shut down.
if (new_state != GRPC_CHANNEL_SHUTDOWN) return; if (new_state != GRPC_CHANNEL_SHUTDOWN) return;
// Shut down channel. // Shut down channel.

@ -58,9 +58,9 @@ const char* ConnectivityStateName(grpc_connectivity_state state) {
class AsyncConnectivityStateWatcherInterface::Notifier { class AsyncConnectivityStateWatcherInterface::Notifier {
public: public:
Notifier(RefCountedPtr<AsyncConnectivityStateWatcherInterface> watcher, Notifier(RefCountedPtr<AsyncConnectivityStateWatcherInterface> watcher,
grpc_connectivity_state state, grpc_connectivity_state state, const absl::Status& status,
const std::shared_ptr<WorkSerializer>& work_serializer) const std::shared_ptr<WorkSerializer>& work_serializer)
: watcher_(std::move(watcher)), state_(state) { : watcher_(std::move(watcher)), state_(state), status_(status) {
if (work_serializer != nullptr) { if (work_serializer != nullptr) {
work_serializer->Run( work_serializer->Run(
[this]() { SendNotification(this, GRPC_ERROR_NONE); }, [this]() { SendNotification(this, GRPC_ERROR_NONE); },
@ -76,21 +76,24 @@ class AsyncConnectivityStateWatcherInterface::Notifier {
static void SendNotification(void* arg, grpc_error* /*ignored*/) { static void SendNotification(void* arg, grpc_error* /*ignored*/) {
Notifier* self = static_cast<Notifier*>(arg); Notifier* self = static_cast<Notifier*>(arg);
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
gpr_log(GPR_INFO, "watcher %p: delivering async notification for %s", gpr_log(GPR_INFO, "watcher %p: delivering async notification for %s (%s)",
self->watcher_.get(), ConnectivityStateName(self->state_)); self->watcher_.get(), ConnectivityStateName(self->state_),
self->status_.ToString().c_str());
} }
self->watcher_->OnConnectivityStateChange(self->state_); self->watcher_->OnConnectivityStateChange(self->state_, self->status_);
delete self; delete self;
} }
RefCountedPtr<AsyncConnectivityStateWatcherInterface> watcher_; RefCountedPtr<AsyncConnectivityStateWatcherInterface> watcher_;
const grpc_connectivity_state state_; const grpc_connectivity_state state_;
const absl::Status status_;
grpc_closure closure_; grpc_closure closure_;
}; };
void AsyncConnectivityStateWatcherInterface::Notify( void AsyncConnectivityStateWatcherInterface::Notify(
grpc_connectivity_state state) { grpc_connectivity_state state, const absl::Status& status) {
new Notifier(Ref(), state, work_serializer_); // Deletes itself when done. new Notifier(Ref(), state, status,
work_serializer_); // Deletes itself when done.
} }
// //
@ -107,7 +110,7 @@ ConnectivityStateTracker::~ConnectivityStateTracker() {
name_, this, p.first, ConnectivityStateName(current_state), name_, this, p.first, ConnectivityStateName(current_state),
ConnectivityStateName(GRPC_CHANNEL_SHUTDOWN)); ConnectivityStateName(GRPC_CHANNEL_SHUTDOWN));
} }
p.second->Notify(GRPC_CHANNEL_SHUTDOWN); p.second->Notify(GRPC_CHANNEL_SHUTDOWN, absl::Status());
} }
} }
@ -126,7 +129,7 @@ void ConnectivityStateTracker::AddWatcher(
name_, this, watcher.get(), ConnectivityStateName(initial_state), name_, this, watcher.get(), ConnectivityStateName(initial_state),
ConnectivityStateName(current_state)); ConnectivityStateName(current_state));
} }
watcher->Notify(current_state); watcher->Notify(current_state, status_);
} }
// If we're in state SHUTDOWN, don't add the watcher, so that it will // If we're in state SHUTDOWN, don't add the watcher, so that it will
// be orphaned immediately. // be orphaned immediately.
@ -145,15 +148,17 @@ void ConnectivityStateTracker::RemoveWatcher(
} }
void ConnectivityStateTracker::SetState(grpc_connectivity_state state, void ConnectivityStateTracker::SetState(grpc_connectivity_state state,
const absl::Status& status,
const char* reason) { const char* reason) {
grpc_connectivity_state current_state = state_.Load(MemoryOrder::RELAXED); grpc_connectivity_state current_state = state_.Load(MemoryOrder::RELAXED);
if (state == current_state) return; if (state == current_state) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
gpr_log(GPR_INFO, "ConnectivityStateTracker %s[%p]: %s -> %s (%s)", name_, gpr_log(GPR_INFO, "ConnectivityStateTracker %s[%p]: %s -> %s (%s, %s)",
this, ConnectivityStateName(current_state), name_, this, ConnectivityStateName(current_state),
ConnectivityStateName(state), reason); ConnectivityStateName(state), reason, status.ToString().c_str());
} }
state_.Store(state, MemoryOrder::RELAXED); state_.Store(state, MemoryOrder::RELAXED);
status_ = status;
for (const auto& p : watchers_) { for (const auto& p : watchers_) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
@ -161,7 +166,7 @@ void ConnectivityStateTracker::SetState(grpc_connectivity_state state,
name_, this, p.first, ConnectivityStateName(current_state), name_, this, p.first, ConnectivityStateName(current_state),
ConnectivityStateName(state)); ConnectivityStateName(state));
} }
p.second->Notify(state); p.second->Notify(state, status);
} }
// If the new state is SHUTDOWN, orphan all of the watchers. This // If the new state is SHUTDOWN, orphan all of the watchers. This
// avoids the need for the callers to explicitly cancel them. // avoids the need for the callers to explicitly cancel them.

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "absl/status/status.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include "src/core/lib/debug/trace.h" #include "src/core/lib/debug/trace.h"
@ -49,7 +51,8 @@ class ConnectivityStateWatcherInterface
virtual ~ConnectivityStateWatcherInterface() = default; virtual ~ConnectivityStateWatcherInterface() = default;
// Notifies the watcher that the state has changed to new_state. // Notifies the watcher that the state has changed to new_state.
virtual void Notify(grpc_connectivity_state new_state) = 0; virtual void Notify(grpc_connectivity_state new_state,
const absl::Status& status) = 0;
void Orphan() override { Unref(); } void Orphan() override { Unref(); }
}; };
@ -64,7 +67,8 @@ class AsyncConnectivityStateWatcherInterface
// Schedules a closure on the ExecCtx to invoke // Schedules a closure on the ExecCtx to invoke
// OnConnectivityStateChange() asynchronously. // OnConnectivityStateChange() asynchronously.
void Notify(grpc_connectivity_state new_state) override final; void Notify(grpc_connectivity_state new_state,
const absl::Status& status) override final;
protected: protected:
class Notifier; class Notifier;
@ -76,7 +80,8 @@ class AsyncConnectivityStateWatcherInterface
: work_serializer_(std::move(work_serializer)) {} : work_serializer_(std::move(work_serializer)) {}
// Invoked asynchronously when Notify() is called. // Invoked asynchronously when Notify() is called.
virtual void OnConnectivityStateChange(grpc_connectivity_state new_state) = 0; virtual void OnConnectivityStateChange(grpc_connectivity_state new_state,
const absl::Status& status) = 0;
private: private:
std::shared_ptr<WorkSerializer> work_serializer_; std::shared_ptr<WorkSerializer> work_serializer_;
@ -91,8 +96,9 @@ class AsyncConnectivityStateWatcherInterface
class ConnectivityStateTracker { class ConnectivityStateTracker {
public: public:
ConnectivityStateTracker(const char* name, ConnectivityStateTracker(const char* name,
grpc_connectivity_state state = GRPC_CHANNEL_IDLE) grpc_connectivity_state state = GRPC_CHANNEL_IDLE,
: name_(name), state_(state) {} const absl::Status& status = absl::Status())
: name_(name), state_(state), status_(status) {}
~ConnectivityStateTracker(); ~ConnectivityStateTracker();
@ -110,15 +116,21 @@ class ConnectivityStateTracker {
// Sets connectivity state. // Sets connectivity state.
// Not thread safe; access must be serialized with an external lock. // Not thread safe; access must be serialized with an external lock.
void SetState(grpc_connectivity_state state, const char* reason); void SetState(grpc_connectivity_state state, const absl::Status& status,
const char* reason);
// Gets the current state. // Gets the current state.
// Thread safe; no need to use an external lock. // Thread safe; no need to use an external lock.
grpc_connectivity_state state() const; grpc_connectivity_state state() const;
// Get the current status.
// Not thread safe; access must be serialized with an external lock.
absl::Status status() const { return status_; }
private: private:
const char* name_; const char* name_;
Atomic<grpc_connectivity_state> state_; Atomic<grpc_connectivity_state> state_;
absl::Status status_;
// TODO(roth): Once we can use C++-14 heterogeneous lookups, this can // TODO(roth): Once we can use C++-14 heterogeneous lookups, this can
// be a set instead of a map. // be a set instead of a map.
std::map<ConnectivityStateWatcherInterface*, std::map<ConnectivityStateWatcherInterface*,

@ -123,6 +123,19 @@ void grpc_error_get_status(grpc_error* error, grpc_millis deadline,
} }
} }
absl::Status grpc_error_to_absl_status(grpc_error* error) {
grpc_status_code status;
// TODO(yashykt): This should be updated once we decide on how to use the
// absl::Status payload to capture all the contents of grpc_error.
grpc_slice message;
grpc_error_get_status(error, GRPC_MILLIS_INF_FUTURE, &status, &message,
nullptr /* http_error */, nullptr /* error_string */);
return absl::Status(static_cast<absl::StatusCode>(status),
absl::string_view(reinterpret_cast<const char*>(
GRPC_SLICE_START_PTR(message)),
GRPC_SLICE_LENGTH(message)));
}
bool grpc_error_has_clear_grpc_status(grpc_error* error) { bool grpc_error_has_clear_grpc_status(grpc_error* error) {
intptr_t unused; intptr_t unused;
if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &unused)) { if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &unused)) {

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "absl/status/status.h"
#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/transport/http2_errors.h" #include "src/core/lib/transport/http2_errors.h"
@ -37,6 +39,10 @@ void grpc_error_get_status(grpc_error* error, grpc_millis deadline,
grpc_http2_error_code* http_status, grpc_http2_error_code* http_status,
const char** error_string); const char** error_string);
/// Utility Function to convert a grpc_error * \a error to an absl::Status.
/// Does NOT consume a ref to grpc_error.
absl::Status grpc_error_to_absl_status(grpc_error* error);
/// A utility function to check whether there is a clear status code that /// A utility function to check whether there is a clear status code that
/// doesn't need to be guessed in \a error. This means that \a error or some /// doesn't need to be guessed in \a error. This means that \a error or some
/// child has GRPC_ERROR_INT_GRPC_STATUS set, or that it is GRPC_ERROR_NONE or /// child has GRPC_ERROR_INT_GRPC_STATUS set, or that it is GRPC_ERROR_NONE or

@ -97,7 +97,8 @@ std::shared_ptr<CallCredentials> WrapCallCredentials(
std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() { std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() {
grpc::GrpcLibraryCodegen init; // To call grpc_init(). grpc::GrpcLibraryCodegen init; // To call grpc_init().
return WrapChannelCredentials(grpc_google_default_credentials_create()); return WrapChannelCredentials(
grpc_google_default_credentials_create(nullptr));
} }
// Builds SSL Credentials given SSL specific options // Builds SSL Credentials given SSL specific options

@ -131,7 +131,7 @@ PHP_METHOD(ChannelCredentials, invalidateDefaultRootsPem) {
* @return ChannelCredentials The new default channel credentials object * @return ChannelCredentials The new default channel credentials object
*/ */
PHP_METHOD(ChannelCredentials, createDefault) { PHP_METHOD(ChannelCredentials, createDefault) {
grpc_channel_credentials *creds = grpc_google_default_credentials_create(); grpc_channel_credentials *creds = grpc_google_default_credentials_create(NULL);
zval *creds_object = grpc_php_wrap_channel_credentials(creds, NULL, false zval *creds_object = grpc_php_wrap_channel_credentials(creds, NULL, false
TSRMLS_CC); TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object); RETURN_DESTROY_ZVAL(creds_object);

@ -1868,6 +1868,23 @@ def alts_server_credentials():
return ServerCredentials(_cygrpc.server_credentials_alts()) return ServerCredentials(_cygrpc.server_credentials_alts())
def compute_engine_channel_credentials(call_credentials):
"""Creates a compute engine channel credential.
This credential can only be used in a GCP environment as it relies on
a handshaker service. For more info about ALTS, see
https://cloud.google.com/security/encryption-in-transit/application-layer-transport-security
This channel credential is expected to be used as part of a composite
credential in conjunction with a call credentials that authenticates the
VM's default service account. If used with any other sort of call
credential, the connection may suddenly and unexpectedly begin failing RPCs.
"""
return ChannelCredentials(
_cygrpc.channel_credentials_compute_engine(
call_credentials._credentials))
def channel_ready_future(channel): def channel_ready_future(channel):
"""Creates a Future that tracks when a Channel is ready. """Creates a Future that tracks when a Channel is ready.

@ -380,3 +380,22 @@ def server_credentials_alts():
# Options can be destroyed as deep copy was performed. # Options can be destroyed as deep copy was performed.
grpc_alts_credentials_options_destroy(c_options) grpc_alts_credentials_options_destroy(c_options)
return credentials return credentials
cdef class ComputeEngineChannelCredentials(ChannelCredentials):
cdef grpc_channel_credentials* _c_creds
cdef grpc_call_credentials* _call_creds
def __cinit__(self, CallCredentials call_creds):
self._c_creds = NULL
self._call_creds = call_creds.c()
if self._call_creds == NULL:
raise ValueError("Call credentials may not be NULL.")
cdef grpc_channel_credentials *c(self) except *:
self._c_creds = grpc_google_default_credentials_create(self._call_creds)
return self._c_creds
def channel_credentials_compute_engine(call_creds):
return ComputeEngineChannelCredentials(call_creds)

@ -504,7 +504,7 @@ cdef extern from "grpc/grpc_security.h":
void grpc_set_ssl_roots_override_callback( void grpc_set_ssl_roots_override_callback(
grpc_ssl_roots_override_callback cb) nogil grpc_ssl_roots_override_callback cb) nogil
grpc_channel_credentials *grpc_google_default_credentials_create() nogil grpc_channel_credentials *grpc_google_default_credentials_create(grpc_call_credentials* call_credentials) nogil
grpc_channel_credentials *grpc_ssl_credentials_create( grpc_channel_credentials *grpc_ssl_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
verify_peer_options *verify_options, void *reserved) nogil verify_peer_options *verify_options, void *reserved) nogil

@ -476,6 +476,7 @@ CORE_SOURCE_FILES = [
'src/core/tsi/transport_security_grpc.cc', 'src/core/tsi/transport_security_grpc.cc',
'third_party/abseil-cpp/absl/base/dynamic_annotations.cc', 'third_party/abseil-cpp/absl/base/dynamic_annotations.cc',
'third_party/abseil-cpp/absl/base/internal/cycleclock.cc', 'third_party/abseil-cpp/absl/base/internal/cycleclock.cc',
'third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc',
'third_party/abseil-cpp/absl/base/internal/raw_logging.cc', 'third_party/abseil-cpp/absl/base/internal/raw_logging.cc',
'third_party/abseil-cpp/absl/base/internal/spinlock.cc', 'third_party/abseil-cpp/absl/base/internal/spinlock.cc',
'third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc', 'third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc',
@ -484,9 +485,18 @@ CORE_SOURCE_FILES = [
'third_party/abseil-cpp/absl/base/internal/throw_delegate.cc', 'third_party/abseil-cpp/absl/base/internal/throw_delegate.cc',
'third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc', 'third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc',
'third_party/abseil-cpp/absl/base/log_severity.cc', 'third_party/abseil-cpp/absl/base/log_severity.cc',
'third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc',
'third_party/abseil-cpp/absl/debugging/internal/demangle.cc',
'third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc',
'third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc',
'third_party/abseil-cpp/absl/debugging/stacktrace.cc',
'third_party/abseil-cpp/absl/debugging/symbolize.cc',
'third_party/abseil-cpp/absl/numeric/int128.cc', 'third_party/abseil-cpp/absl/numeric/int128.cc',
'third_party/abseil-cpp/absl/status/status.cc',
'third_party/abseil-cpp/absl/status/status_payload_printer.cc',
'third_party/abseil-cpp/absl/strings/ascii.cc', 'third_party/abseil-cpp/absl/strings/ascii.cc',
'third_party/abseil-cpp/absl/strings/charconv.cc', 'third_party/abseil-cpp/absl/strings/charconv.cc',
'third_party/abseil-cpp/absl/strings/cord.cc',
'third_party/abseil-cpp/absl/strings/escaping.cc', 'third_party/abseil-cpp/absl/strings/escaping.cc',
'third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc', 'third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc',
'third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc', 'third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc',

@ -13,7 +13,7 @@ py_library(
) )
py_library( py_library(
name = "client", name = "client_lib",
srcs = ["client.py"], srcs = ["client.py"],
imports = ["../../"], imports = ["../../"],
deps = [ deps = [
@ -25,6 +25,13 @@ py_library(
], ],
) )
py_binary(
name = "client",
srcs = ["client.py"],
python_version = "PY3",
deps = [":client_lib"],
)
py_library( py_library(
name = "methods", name = "methods",
srcs = ["methods.py"], srcs = ["methods.py"],

@ -51,6 +51,10 @@ def parse_interop_client_args():
default=False, default=False,
type=resources.parse_bool, type=resources.parse_bool,
help='replace platform root CAs with ca.pem') help='replace platform root CAs with ca.pem')
parser.add_argument('--custom_credentials_type',
choices=["compute_engine_channel_creds"],
default=None,
help='use google default credentials')
parser.add_argument('--server_host_override', parser.add_argument('--server_host_override',
type=str, type=str,
help='the server host to which to claim to connect') help='the server host to which to claim to connect')
@ -60,6 +64,14 @@ def parse_interop_client_args():
parser.add_argument('--default_service_account', parser.add_argument('--default_service_account',
type=str, type=str,
help='email address of the default service account') help='email address of the default service account')
parser.add_argument(
"--grpc_test_use_grpclb_with_child_policy",
type=str,
help=(
"If non-empty, set a static service config on channels created by "
+ "grpc::CreateTestChannel, that configures the grpclb LB policy " +
"with a child policy being the value of this flag (e.g. round_robin "
+ "or pick_first)."))
return parser.parse_args() return parser.parse_args()
@ -89,8 +101,27 @@ def _create_call_credentials(args):
def get_secure_channel_parameters(args): def get_secure_channel_parameters(args):
call_credentials = _create_call_credentials(args) call_credentials = _create_call_credentials(args)
channel_opts = None channel_opts = ()
if args.use_tls: if args.grpc_test_use_grpclb_with_child_policy:
channel_opts += ((
"grpc.service_config",
'{"loadBalancingConfig": [{"grpclb": {"childPolicy": [{"%s": {}}]}}]}'
% args.grpc_test_use_grpclb_with_child_policy),)
if args.custom_credentials_type is not None:
if args.custom_credentials_type == "compute_engine_channel_creds":
assert call_credentials is None
google_credentials, unused_project_id = google_auth.default(
scopes=[args.oauth_scope])
call_creds = grpc.metadata_call_credentials(
google_auth.transport.grpc.AuthMetadataPlugin(
credentials=google_credentials,
request=google_auth.transport.requests.Request()))
channel_credentials = grpc.compute_engine_channel_credentials(
call_creds)
else:
raise ValueError("Unknown credentials type '{}'".format(
args.custom_credentials_type))
elif args.use_tls:
if args.use_test_ca: if args.use_test_ca:
root_certificates = resources.test_root_certificates() root_certificates = resources.test_root_certificates()
else: else:
@ -102,7 +133,7 @@ def get_secure_channel_parameters(args):
channel_credentials, call_credentials) channel_credentials, call_credentials)
if args.server_host_override: if args.server_host_override:
channel_opts = (( channel_opts += ((
'grpc.ssl_target_name_override', 'grpc.ssl_target_name_override',
args.server_host_override, args.server_host_override,
),) ),)
@ -115,7 +146,7 @@ def get_secure_channel_parameters(args):
def _create_channel(args): def _create_channel(args):
target = '{}:{}'.format(args.server_host, args.server_port) target = '{}:{}'.format(args.server_host, args.server_port)
if args.use_tls or args.use_alts: if args.use_tls or args.use_alts or args.custom_credentials_type is not None:
channel_credentials, options = get_secure_channel_parameters(args) channel_credentials, options = get_secure_channel_parameters(args)
return grpc.secure_channel(target, channel_credentials, options) return grpc.secure_channel(target, channel_credentials, options)
else: else:

@ -70,7 +70,7 @@ py_binary(
deps = [ deps = [
":methods", ":methods",
"//src/python/grpcio/grpc:grpcio", "//src/python/grpcio/grpc:grpcio",
"//src/python/grpcio_tests/tests/interop:client", "//src/python/grpcio_tests/tests/interop:client_lib",
"//src/python/grpcio_tests/tests/interop:resources", "//src/python/grpcio_tests/tests/interop:resources",
], ],
) )

@ -30,7 +30,7 @@ _LOGGER.setLevel(logging.DEBUG)
def _create_channel(args): def _create_channel(args):
target = f'{args.server_host}:{args.server_port}' target = f'{args.server_host}:{args.server_port}'
if args.use_tls or args.use_alts: if args.use_tls or args.use_alts or args.custom_credentials_type is not None:
channel_credentials, options = interop_client_lib.get_secure_channel_parameters( channel_credentials, options = interop_client_lib.get_secure_channel_parameters(
args) args)
return aio.secure_channel(target, channel_credentials, options) return aio.secure_channel(target, channel_credentials, options)

@ -120,12 +120,12 @@ grpc_auth_context_set_peer_identity_property_name_type grpc_auth_context_set_pee
grpc_ssl_session_cache_create_lru_type grpc_ssl_session_cache_create_lru_import; grpc_ssl_session_cache_create_lru_type grpc_ssl_session_cache_create_lru_import;
grpc_ssl_session_cache_destroy_type grpc_ssl_session_cache_destroy_import; grpc_ssl_session_cache_destroy_type grpc_ssl_session_cache_destroy_import;
grpc_ssl_session_cache_create_channel_arg_type grpc_ssl_session_cache_create_channel_arg_import; grpc_ssl_session_cache_create_channel_arg_type grpc_ssl_session_cache_create_channel_arg_import;
grpc_call_credentials_release_type grpc_call_credentials_release_import;
grpc_channel_credentials_release_type grpc_channel_credentials_release_import; grpc_channel_credentials_release_type grpc_channel_credentials_release_import;
grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import; grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import;
grpc_set_ssl_roots_override_callback_type grpc_set_ssl_roots_override_callback_import; grpc_set_ssl_roots_override_callback_type grpc_set_ssl_roots_override_callback_import;
grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import; grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import;
grpc_ssl_credentials_create_ex_type grpc_ssl_credentials_create_ex_import; grpc_ssl_credentials_create_ex_type grpc_ssl_credentials_create_ex_import;
grpc_call_credentials_release_type grpc_call_credentials_release_import;
grpc_composite_channel_credentials_create_type grpc_composite_channel_credentials_create_import; grpc_composite_channel_credentials_create_type grpc_composite_channel_credentials_create_import;
grpc_composite_call_credentials_create_type grpc_composite_call_credentials_create_import; grpc_composite_call_credentials_create_type grpc_composite_call_credentials_create_import;
grpc_google_compute_engine_credentials_create_type grpc_google_compute_engine_credentials_create_import; grpc_google_compute_engine_credentials_create_type grpc_google_compute_engine_credentials_create_import;
@ -394,12 +394,12 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_ssl_session_cache_create_lru_import = (grpc_ssl_session_cache_create_lru_type) GetProcAddress(library, "grpc_ssl_session_cache_create_lru"); grpc_ssl_session_cache_create_lru_import = (grpc_ssl_session_cache_create_lru_type) GetProcAddress(library, "grpc_ssl_session_cache_create_lru");
grpc_ssl_session_cache_destroy_import = (grpc_ssl_session_cache_destroy_type) GetProcAddress(library, "grpc_ssl_session_cache_destroy"); grpc_ssl_session_cache_destroy_import = (grpc_ssl_session_cache_destroy_type) GetProcAddress(library, "grpc_ssl_session_cache_destroy");
grpc_ssl_session_cache_create_channel_arg_import = (grpc_ssl_session_cache_create_channel_arg_type) GetProcAddress(library, "grpc_ssl_session_cache_create_channel_arg"); grpc_ssl_session_cache_create_channel_arg_import = (grpc_ssl_session_cache_create_channel_arg_type) GetProcAddress(library, "grpc_ssl_session_cache_create_channel_arg");
grpc_call_credentials_release_import = (grpc_call_credentials_release_type) GetProcAddress(library, "grpc_call_credentials_release");
grpc_channel_credentials_release_import = (grpc_channel_credentials_release_type) GetProcAddress(library, "grpc_channel_credentials_release"); grpc_channel_credentials_release_import = (grpc_channel_credentials_release_type) GetProcAddress(library, "grpc_channel_credentials_release");
grpc_google_default_credentials_create_import = (grpc_google_default_credentials_create_type) GetProcAddress(library, "grpc_google_default_credentials_create"); grpc_google_default_credentials_create_import = (grpc_google_default_credentials_create_type) GetProcAddress(library, "grpc_google_default_credentials_create");
grpc_set_ssl_roots_override_callback_import = (grpc_set_ssl_roots_override_callback_type) GetProcAddress(library, "grpc_set_ssl_roots_override_callback"); grpc_set_ssl_roots_override_callback_import = (grpc_set_ssl_roots_override_callback_type) GetProcAddress(library, "grpc_set_ssl_roots_override_callback");
grpc_ssl_credentials_create_import = (grpc_ssl_credentials_create_type) GetProcAddress(library, "grpc_ssl_credentials_create"); grpc_ssl_credentials_create_import = (grpc_ssl_credentials_create_type) GetProcAddress(library, "grpc_ssl_credentials_create");
grpc_ssl_credentials_create_ex_import = (grpc_ssl_credentials_create_ex_type) GetProcAddress(library, "grpc_ssl_credentials_create_ex"); grpc_ssl_credentials_create_ex_import = (grpc_ssl_credentials_create_ex_type) GetProcAddress(library, "grpc_ssl_credentials_create_ex");
grpc_call_credentials_release_import = (grpc_call_credentials_release_type) GetProcAddress(library, "grpc_call_credentials_release");
grpc_composite_channel_credentials_create_import = (grpc_composite_channel_credentials_create_type) GetProcAddress(library, "grpc_composite_channel_credentials_create"); grpc_composite_channel_credentials_create_import = (grpc_composite_channel_credentials_create_type) GetProcAddress(library, "grpc_composite_channel_credentials_create");
grpc_composite_call_credentials_create_import = (grpc_composite_call_credentials_create_type) GetProcAddress(library, "grpc_composite_call_credentials_create"); grpc_composite_call_credentials_create_import = (grpc_composite_call_credentials_create_type) GetProcAddress(library, "grpc_composite_call_credentials_create");
grpc_google_compute_engine_credentials_create_import = (grpc_google_compute_engine_credentials_create_type) GetProcAddress(library, "grpc_google_compute_engine_credentials_create"); grpc_google_compute_engine_credentials_create_import = (grpc_google_compute_engine_credentials_create_type) GetProcAddress(library, "grpc_google_compute_engine_credentials_create");

@ -335,10 +335,13 @@ extern grpc_ssl_session_cache_destroy_type grpc_ssl_session_cache_destroy_import
typedef grpc_arg(*grpc_ssl_session_cache_create_channel_arg_type)(grpc_ssl_session_cache* cache); typedef grpc_arg(*grpc_ssl_session_cache_create_channel_arg_type)(grpc_ssl_session_cache* cache);
extern grpc_ssl_session_cache_create_channel_arg_type grpc_ssl_session_cache_create_channel_arg_import; extern grpc_ssl_session_cache_create_channel_arg_type grpc_ssl_session_cache_create_channel_arg_import;
#define grpc_ssl_session_cache_create_channel_arg grpc_ssl_session_cache_create_channel_arg_import #define grpc_ssl_session_cache_create_channel_arg grpc_ssl_session_cache_create_channel_arg_import
typedef void(*grpc_call_credentials_release_type)(grpc_call_credentials* creds);
extern grpc_call_credentials_release_type grpc_call_credentials_release_import;
#define grpc_call_credentials_release grpc_call_credentials_release_import
typedef void(*grpc_channel_credentials_release_type)(grpc_channel_credentials* creds); typedef void(*grpc_channel_credentials_release_type)(grpc_channel_credentials* creds);
extern grpc_channel_credentials_release_type grpc_channel_credentials_release_import; extern grpc_channel_credentials_release_type grpc_channel_credentials_release_import;
#define grpc_channel_credentials_release grpc_channel_credentials_release_import #define grpc_channel_credentials_release grpc_channel_credentials_release_import
typedef grpc_channel_credentials*(*grpc_google_default_credentials_create_type)(void); typedef grpc_channel_credentials*(*grpc_google_default_credentials_create_type)(grpc_call_credentials* call_credentials);
extern grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import; extern grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import;
#define grpc_google_default_credentials_create grpc_google_default_credentials_create_import #define grpc_google_default_credentials_create grpc_google_default_credentials_create_import
typedef void(*grpc_set_ssl_roots_override_callback_type)(grpc_ssl_roots_override_callback cb); typedef void(*grpc_set_ssl_roots_override_callback_type)(grpc_ssl_roots_override_callback cb);
@ -350,9 +353,6 @@ extern grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import;
typedef grpc_channel_credentials*(*grpc_ssl_credentials_create_ex_type)(const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, const grpc_ssl_verify_peer_options* verify_options, void* reserved); typedef grpc_channel_credentials*(*grpc_ssl_credentials_create_ex_type)(const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, const grpc_ssl_verify_peer_options* verify_options, void* reserved);
extern grpc_ssl_credentials_create_ex_type grpc_ssl_credentials_create_ex_import; extern grpc_ssl_credentials_create_ex_type grpc_ssl_credentials_create_ex_import;
#define grpc_ssl_credentials_create_ex grpc_ssl_credentials_create_ex_import #define grpc_ssl_credentials_create_ex grpc_ssl_credentials_create_ex_import
typedef void(*grpc_call_credentials_release_type)(grpc_call_credentials* creds);
extern grpc_call_credentials_release_type grpc_call_credentials_release_import;
#define grpc_call_credentials_release grpc_call_credentials_release_import
typedef grpc_channel_credentials*(*grpc_composite_channel_credentials_create_type)(grpc_channel_credentials* channel_creds, grpc_call_credentials* call_creds, void* reserved); typedef grpc_channel_credentials*(*grpc_composite_channel_credentials_create_type)(grpc_channel_credentials* channel_creds, grpc_call_credentials* call_creds, void* reserved);
extern grpc_composite_channel_credentials_create_type grpc_composite_channel_credentials_create_import; extern grpc_composite_channel_credentials_create_type grpc_composite_channel_credentials_create_import;
#define grpc_composite_channel_credentials_create grpc_composite_channel_credentials_create_import #define grpc_composite_channel_credentials_create grpc_composite_channel_credentials_create_import

@ -41,4 +41,5 @@
# Cloning from a local path sets RepositoryUrl to a path and breaks Source Link. # Cloning from a local path sets RepositoryUrl to a path and breaks Source Link.
# Override RepositoryUrl to a URL to fix Source Link. The value doesn't matter. # Override RepositoryUrl to a URL to fix Source Link. The value doesn't matter.
dotnet build --configuration Debug Grpc.DotNet.sln -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git dotnet build --configuration Debug --output ./output/InteropTestsWebsite testassets/InteropTestsWebsite/InteropTestsWebsite.csproj -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git
dotnet build --configuration Debug --output ./output/InteropTestsClient testassets/InteropTestsClient/InteropTestsClient.csproj -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git

@ -1347,16 +1347,24 @@ static void set_google_default_creds_env_var_with_file_contents(
gpr_free(creds_file_name); gpr_free(creds_file_name);
} }
static bool test_gce_tenancy_checker(void) {
g_test_gce_tenancy_checker_called = true;
return g_test_is_on_gce;
}
static void test_google_default_creds_auth_key(void) { static void test_google_default_creds_auth_key(void) {
grpc_core::ExecCtx exec_ctx; grpc_core::ExecCtx exec_ctx;
grpc_composite_channel_credentials* creds; grpc_composite_channel_credentials* creds;
char* json_key = test_json_key_str(); char* json_key = test_json_key_str();
grpc_flush_cached_google_default_credentials(); grpc_flush_cached_google_default_credentials();
set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
g_test_gce_tenancy_checker_called = false;
g_test_is_on_gce = true;
set_google_default_creds_env_var_with_file_contents( set_google_default_creds_env_var_with_file_contents(
"json_key_google_default_creds", json_key); "json_key_google_default_creds", json_key);
gpr_free(json_key); gpr_free(json_key);
creds = reinterpret_cast<grpc_composite_channel_credentials*>( creds = reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create()); grpc_google_default_credentials_create(nullptr));
auto* default_creds = auto* default_creds =
reinterpret_cast<const grpc_google_default_channel_credentials*>( reinterpret_cast<const grpc_google_default_channel_credentials*>(
creds->inner_creds()); creds->inner_creds());
@ -1368,6 +1376,7 @@ static void test_google_default_creds_auth_key(void) {
strcmp(jwt->key().client_id, strcmp(jwt->key().client_id,
"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") == "777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") ==
0); 0);
GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
creds->Unref(); creds->Unref();
gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
} }
@ -1379,7 +1388,7 @@ static void test_google_default_creds_refresh_token(void) {
set_google_default_creds_env_var_with_file_contents( set_google_default_creds_env_var_with_file_contents(
"refresh_token_google_default_creds", test_refresh_token_str); "refresh_token_google_default_creds", test_refresh_token_str);
creds = reinterpret_cast<grpc_composite_channel_credentials*>( creds = reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create()); grpc_google_default_credentials_create(nullptr));
auto* default_creds = auto* default_creds =
reinterpret_cast<const grpc_google_default_channel_credentials*>( reinterpret_cast<const grpc_google_default_channel_credentials*>(
creds->inner_creds()); creds->inner_creds());
@ -1411,11 +1420,6 @@ static int default_creds_metadata_server_detection_httpcli_get_success_override(
static std::string null_well_known_creds_path_getter(void) { return ""; } static std::string null_well_known_creds_path_getter(void) { return ""; }
static bool test_gce_tenancy_checker(void) {
g_test_gce_tenancy_checker_called = true;
return g_test_is_on_gce;
}
static void test_google_default_creds_gce(void) { static void test_google_default_creds_gce(void) {
grpc_core::ExecCtx exec_ctx; grpc_core::ExecCtx exec_ctx;
expected_md emd[] = { expected_md emd[] = {
@ -1435,7 +1439,7 @@ static void test_google_default_creds_gce(void) {
/* Simulate a successful detection of GCE. */ /* Simulate a successful detection of GCE. */
grpc_composite_channel_credentials* creds = grpc_composite_channel_credentials* creds =
reinterpret_cast<grpc_composite_channel_credentials*>( reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create()); grpc_google_default_credentials_create(nullptr));
/* Verify that the default creds actually embeds a GCE creds. */ /* Verify that the default creds actually embeds a GCE creds. */
GPR_ASSERT(creds != nullptr); GPR_ASSERT(creds != nullptr);
@ -1474,7 +1478,7 @@ static void test_google_default_creds_non_gce(void) {
httpcli_post_should_not_be_called); httpcli_post_should_not_be_called);
grpc_composite_channel_credentials* creds = grpc_composite_channel_credentials* creds =
reinterpret_cast<grpc_composite_channel_credentials*>( reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create()); grpc_google_default_credentials_create(nullptr));
/* Verify that the default creds actually embeds a GCE creds. */ /* Verify that the default creds actually embeds a GCE creds. */
GPR_ASSERT(creds != nullptr); GPR_ASSERT(creds != nullptr);
GPR_ASSERT(creds->call_creds() != nullptr); GPR_ASSERT(creds->call_creds() != nullptr);
@ -1512,16 +1516,105 @@ static void test_no_google_default_creds(void) {
default_creds_gce_detection_httpcli_get_failure_override, default_creds_gce_detection_httpcli_get_failure_override,
httpcli_post_should_not_be_called); httpcli_post_should_not_be_called);
/* Simulate a successful detection of GCE. */ /* Simulate a successful detection of GCE. */
GPR_ASSERT(grpc_google_default_credentials_create() == nullptr); GPR_ASSERT(grpc_google_default_credentials_create(nullptr) == nullptr);
/* Try a second one. GCE detection should occur again. */ /* Try a second one. GCE detection should occur again. */
g_test_gce_tenancy_checker_called = false; g_test_gce_tenancy_checker_called = false;
GPR_ASSERT(grpc_google_default_credentials_create() == nullptr); GPR_ASSERT(grpc_google_default_credentials_create(nullptr) == nullptr);
GPR_ASSERT(g_test_gce_tenancy_checker_called == true); GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
/* Cleanup. */ /* Cleanup. */
grpc_override_well_known_credentials_path_getter(nullptr); grpc_override_well_known_credentials_path_getter(nullptr);
grpc_httpcli_set_override(nullptr, nullptr); grpc_httpcli_set_override(nullptr, nullptr);
} }
static void test_google_default_creds_call_creds_specified(void) {
expected_md emd[] = {
{"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
request_metadata_state* state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
nullptr, nullptr};
grpc_core::ExecCtx exec_ctx;
grpc_flush_cached_google_default_credentials();
grpc_call_credentials* call_creds =
grpc_google_compute_engine_credentials_create(nullptr);
set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
g_test_gce_tenancy_checker_called = false;
g_test_is_on_gce = true;
grpc_httpcli_set_override(
default_creds_metadata_server_detection_httpcli_get_success_override,
httpcli_post_should_not_be_called);
grpc_composite_channel_credentials* channel_creds =
reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create(call_creds));
GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
GPR_ASSERT(channel_creds != nullptr);
GPR_ASSERT(channel_creds->call_creds() != nullptr);
grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
httpcli_post_should_not_be_called);
run_request_metadata_test(channel_creds->mutable_call_creds(), auth_md_ctx,
state);
grpc_core::ExecCtx::Get()->Flush();
channel_creds->Unref();
grpc_httpcli_set_override(nullptr, nullptr);
}
struct fake_call_creds : public grpc_call_credentials {
public:
explicit fake_call_creds() : grpc_call_credentials("fake") {
grpc_slice key = grpc_slice_from_static_string("foo");
grpc_slice value = grpc_slice_from_static_string("oof");
dummy_md_ = grpc_mdelem_from_slices(key, value);
grpc_slice_unref(key);
grpc_slice_unref(value);
}
~fake_call_creds() { GRPC_MDELEM_UNREF(dummy_md_); }
bool get_request_metadata(grpc_polling_entity* pollent,
grpc_auth_metadata_context context,
grpc_credentials_mdelem_array* md_array,
grpc_closure* on_request_metadata,
grpc_error** error) {
grpc_credentials_mdelem_array_add(md_array, dummy_md_);
return true;
}
void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array,
grpc_error* error) {}
private:
grpc_mdelem dummy_md_;
};
static void test_google_default_creds_not_default(void) {
expected_md emd[] = {{"foo", "oof"}};
request_metadata_state* state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
nullptr, nullptr};
grpc_core::ExecCtx exec_ctx;
grpc_flush_cached_google_default_credentials();
grpc_core::RefCountedPtr<grpc_call_credentials> call_creds =
grpc_core::MakeRefCounted<fake_call_creds>();
set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
g_test_gce_tenancy_checker_called = false;
g_test_is_on_gce = true;
grpc_httpcli_set_override(
default_creds_metadata_server_detection_httpcli_get_success_override,
httpcli_post_should_not_be_called);
grpc_composite_channel_credentials* channel_creds =
reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create(call_creds.release()));
GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
GPR_ASSERT(channel_creds != nullptr);
GPR_ASSERT(channel_creds->call_creds() != nullptr);
run_request_metadata_test(channel_creds->mutable_call_creds(), auth_md_ctx,
state);
grpc_core::ExecCtx::Get()->Flush();
channel_creds->Unref();
grpc_httpcli_set_override(nullptr, nullptr);
}
typedef enum { typedef enum {
PLUGIN_INITIAL_STATE, PLUGIN_INITIAL_STATE,
PLUGIN_GET_METADATA_CALLED_STATE, PLUGIN_GET_METADATA_CALLED_STATE,
@ -1825,6 +1918,8 @@ int main(int argc, char** argv) {
test_google_default_creds_gce(); test_google_default_creds_gce();
test_google_default_creds_non_gce(); test_google_default_creds_non_gce();
test_no_google_default_creds(); test_no_google_default_creds();
test_google_default_creds_call_creds_specified();
test_google_default_creds_not_default();
test_metadata_plugin_success(); test_metadata_plugin_success();
test_metadata_plugin_failure(); test_metadata_plugin_failure();
test_get_well_known_google_credentials_file_path(); test_get_well_known_google_credentials_file_path();

@ -30,7 +30,8 @@
class Watcher : public grpc_core::ConnectivityStateWatcherInterface { class Watcher : public grpc_core::ConnectivityStateWatcherInterface {
public: public:
void Notify(grpc_connectivity_state new_state) override { void Notify(grpc_connectivity_state new_state,
const absl::Status& /* status */) override {
GPR_ASSERT(new_state == GRPC_CHANNEL_SHUTDOWN); GPR_ASSERT(new_state == GRPC_CHANNEL_SHUTDOWN);
} }
}; };

@ -164,12 +164,12 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_ssl_session_cache_create_lru); printf("%lx", (unsigned long) grpc_ssl_session_cache_create_lru);
printf("%lx", (unsigned long) grpc_ssl_session_cache_destroy); printf("%lx", (unsigned long) grpc_ssl_session_cache_destroy);
printf("%lx", (unsigned long) grpc_ssl_session_cache_create_channel_arg); printf("%lx", (unsigned long) grpc_ssl_session_cache_create_channel_arg);
printf("%lx", (unsigned long) grpc_call_credentials_release);
printf("%lx", (unsigned long) grpc_channel_credentials_release); printf("%lx", (unsigned long) grpc_channel_credentials_release);
printf("%lx", (unsigned long) grpc_google_default_credentials_create); printf("%lx", (unsigned long) grpc_google_default_credentials_create);
printf("%lx", (unsigned long) grpc_set_ssl_roots_override_callback); printf("%lx", (unsigned long) grpc_set_ssl_roots_override_callback);
printf("%lx", (unsigned long) grpc_ssl_credentials_create); printf("%lx", (unsigned long) grpc_ssl_credentials_create);
printf("%lx", (unsigned long) grpc_ssl_credentials_create_ex); printf("%lx", (unsigned long) grpc_ssl_credentials_create_ex);
printf("%lx", (unsigned long) grpc_call_credentials_release);
printf("%lx", (unsigned long) grpc_composite_channel_credentials_create); printf("%lx", (unsigned long) grpc_composite_channel_credentials_create);
printf("%lx", (unsigned long) grpc_composite_call_credentials_create); printf("%lx", (unsigned long) grpc_composite_call_credentials_create);
printf("%lx", (unsigned long) grpc_google_compute_engine_credentials_create); printf("%lx", (unsigned long) grpc_google_compute_engine_credentials_create);

@ -65,7 +65,6 @@ grpc_status_code PerformCall(grpc_channel* channel, grpc_server* server,
cq_verifier* cqv = cq_verifier_create(cq); cq_verifier* cqv = cq_verifier_create(cq);
grpc_op ops[6]; grpc_op ops[6];
grpc_op* op; grpc_op* op;
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv; grpc_metadata_array trailing_metadata_recv;
grpc_metadata_array request_metadata_recv; grpc_metadata_array request_metadata_recv;
grpc_call_details call_details; grpc_call_details call_details;
@ -78,7 +77,6 @@ grpc_status_code PerformCall(grpc_channel* channel, grpc_server* server,
grpc_slice_from_static_string("/foo"), nullptr, grpc_slice_from_static_string("/foo"), nullptr,
deadline, nullptr); deadline, nullptr);
GPR_ASSERT(c); GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv);
grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv);
grpc_metadata_array_init(&request_metadata_recv); grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details); grpc_call_details_init(&call_details);
@ -111,7 +109,6 @@ grpc_status_code PerformCall(grpc_channel* channel, grpc_server* server,
cq_verify(cqv); cq_verify(cqv);
// cleanup // cleanup
grpc_slice_unref(details); grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details); grpc_call_details_destroy(&call_details);

@ -42,116 +42,164 @@ TEST(ConnectivityStateName, Basic) {
class Watcher : public ConnectivityStateWatcherInterface { class Watcher : public ConnectivityStateWatcherInterface {
public: public:
Watcher(int* count, grpc_connectivity_state* output, Watcher(int* count, grpc_connectivity_state* output, absl::Status* status,
bool* destroyed = nullptr) bool* destroyed = nullptr)
: count_(count), output_(output), destroyed_(destroyed) {} : count_(count),
output_(output),
status_(status),
destroyed_(destroyed) {}
~Watcher() { ~Watcher() {
if (destroyed_ != nullptr) *destroyed_ = true; if (destroyed_ != nullptr) *destroyed_ = true;
} }
void Notify(grpc_connectivity_state new_state) override { void Notify(grpc_connectivity_state new_state,
const absl::Status& status) override {
++*count_; ++*count_;
*output_ = new_state; *output_ = new_state;
*status_ = status;
} }
private: private:
int* count_; int* count_;
grpc_connectivity_state* output_; grpc_connectivity_state* output_;
absl::Status* status_;
bool* destroyed_; bool* destroyed_;
}; };
TEST(StateTracker, SetAndGetState) { TEST(StateTracker, SetAndGetState) {
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING); ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING,
absl::Status());
EXPECT_EQ(tracker.state(), GRPC_CHANNEL_CONNECTING); EXPECT_EQ(tracker.state(), GRPC_CHANNEL_CONNECTING);
tracker.SetState(GRPC_CHANNEL_READY, "whee"); EXPECT_TRUE(tracker.status().ok());
tracker.SetState(GRPC_CHANNEL_READY, absl::Status(), "whee");
EXPECT_EQ(tracker.state(), GRPC_CHANNEL_READY); EXPECT_EQ(tracker.state(), GRPC_CHANNEL_READY);
EXPECT_TRUE(tracker.status().ok());
absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
"status for testing");
tracker.SetState(GRPC_CHANNEL_TRANSIENT_FAILURE, transient_failure_status,
"reason");
EXPECT_EQ(tracker.state(), GRPC_CHANNEL_TRANSIENT_FAILURE);
EXPECT_EQ(tracker.status(), transient_failure_status);
} }
TEST(StateTracker, NotificationUponAddingWatcher) { TEST(StateTracker, NotificationUponAddingWatcher) {
int count = 0; int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
absl::Status status;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING); ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING);
tracker.AddWatcher(GRPC_CHANNEL_IDLE, tracker.AddWatcher(GRPC_CHANNEL_IDLE,
MakeOrphanable<Watcher>(&count, &state)); MakeOrphanable<Watcher>(&count, &state, &status));
EXPECT_EQ(count, 1); EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_CONNECTING); EXPECT_EQ(state, GRPC_CHANNEL_CONNECTING);
EXPECT_TRUE(status.ok());
}
TEST(StateTracker, NotificationUponAddingWatcherWithTransientFailure) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
absl::Status status;
absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
"status for testing");
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_TRANSIENT_FAILURE,
transient_failure_status);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
MakeOrphanable<Watcher>(&count, &state, &status));
EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_TRANSIENT_FAILURE);
EXPECT_EQ(status, transient_failure_status);
} }
TEST(StateTracker, NotificationUponStateChange) { TEST(StateTracker, NotificationUponStateChange) {
int count = 0; int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
absl::Status status;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE); ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
tracker.AddWatcher(GRPC_CHANNEL_IDLE, tracker.AddWatcher(GRPC_CHANNEL_IDLE,
MakeOrphanable<Watcher>(&count, &state)); MakeOrphanable<Watcher>(&count, &state, &status));
EXPECT_EQ(count, 0); EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE); EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
tracker.SetState(GRPC_CHANNEL_CONNECTING, "whee"); EXPECT_TRUE(status.ok());
absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
"status for testing");
tracker.SetState(GRPC_CHANNEL_TRANSIENT_FAILURE, transient_failure_status,
"whee");
EXPECT_EQ(count, 1); EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_CONNECTING); EXPECT_EQ(state, GRPC_CHANNEL_TRANSIENT_FAILURE);
EXPECT_EQ(status, transient_failure_status);
} }
TEST(StateTracker, SubscribeThenUnsubscribe) { TEST(StateTracker, SubscribeThenUnsubscribe) {
int count = 0; int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
absl::Status status;
bool destroyed = false; bool destroyed = false;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE); ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
ConnectivityStateWatcherInterface* watcher = ConnectivityStateWatcherInterface* watcher =
new Watcher(&count, &state, &destroyed); new Watcher(&count, &state, &status, &destroyed);
tracker.AddWatcher(GRPC_CHANNEL_IDLE, tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr<ConnectivityStateWatcherInterface>(watcher)); OrphanablePtr<ConnectivityStateWatcherInterface>(watcher));
// No initial notification, since we started the watch from the // No initial notification, since we started the watch from the
// current state. // current state.
EXPECT_EQ(count, 0); EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE); EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
EXPECT_TRUE(status.ok());
// Cancel watch. This should not generate another notification. // Cancel watch. This should not generate another notification.
tracker.RemoveWatcher(watcher); tracker.RemoveWatcher(watcher);
EXPECT_TRUE(destroyed); EXPECT_TRUE(destroyed);
EXPECT_EQ(count, 0); EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE); EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
EXPECT_TRUE(status.ok());
} }
TEST(StateTracker, OrphanUponShutdown) { TEST(StateTracker, OrphanUponShutdown) {
int count = 0; int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
absl::Status status;
bool destroyed = false; bool destroyed = false;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE); ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
ConnectivityStateWatcherInterface* watcher = ConnectivityStateWatcherInterface* watcher =
new Watcher(&count, &state, &destroyed); new Watcher(&count, &state, &status, &destroyed);
tracker.AddWatcher(GRPC_CHANNEL_IDLE, tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr<ConnectivityStateWatcherInterface>(watcher)); OrphanablePtr<ConnectivityStateWatcherInterface>(watcher));
// No initial notification, since we started the watch from the // No initial notification, since we started the watch from the
// current state. // current state.
EXPECT_EQ(count, 0); EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE); EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
EXPECT_TRUE(status.ok());
// Set state to SHUTDOWN. // Set state to SHUTDOWN.
tracker.SetState(GRPC_CHANNEL_SHUTDOWN, "shutting down"); tracker.SetState(GRPC_CHANNEL_SHUTDOWN, absl::Status(), "shutting down");
EXPECT_TRUE(destroyed); EXPECT_TRUE(destroyed);
EXPECT_EQ(count, 1); EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN); EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
EXPECT_TRUE(status.ok());
} }
TEST(StateTracker, AddWhenAlreadyShutdown) { TEST(StateTracker, AddWhenAlreadyShutdown) {
int count = 0; int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
absl::Status status;
bool destroyed = false; bool destroyed = false;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN); ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN,
absl::Status());
ConnectivityStateWatcherInterface* watcher = ConnectivityStateWatcherInterface* watcher =
new Watcher(&count, &state, &destroyed); new Watcher(&count, &state, &status, &destroyed);
tracker.AddWatcher(GRPC_CHANNEL_IDLE, tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr<ConnectivityStateWatcherInterface>(watcher)); OrphanablePtr<ConnectivityStateWatcherInterface>(watcher));
EXPECT_TRUE(destroyed); EXPECT_TRUE(destroyed);
EXPECT_EQ(count, 1); EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN); EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
EXPECT_TRUE(status.ok());
} }
TEST(StateTracker, NotifyShutdownAtDestruction) { TEST(StateTracker, NotifyShutdownAtDestruction) {
int count = 0; int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
absl::Status status;
{ {
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE); ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
tracker.AddWatcher(GRPC_CHANNEL_IDLE, tracker.AddWatcher(GRPC_CHANNEL_IDLE,
MakeOrphanable<Watcher>(&count, &state)); MakeOrphanable<Watcher>(&count, &state, &status));
// No initial notification, since we started the watch from the // No initial notification, since we started the watch from the
// current state. // current state.
EXPECT_EQ(count, 0); EXPECT_EQ(count, 0);
@ -165,10 +213,11 @@ TEST(StateTracker, NotifyShutdownAtDestruction) {
TEST(StateTracker, DoNotNotifyShutdownAtDestructionIfAlreadyInShutdown) { TEST(StateTracker, DoNotNotifyShutdownAtDestructionIfAlreadyInShutdown) {
int count = 0; int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_SHUTDOWN; grpc_connectivity_state state = GRPC_CHANNEL_SHUTDOWN;
absl::Status status;
{ {
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN); ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN);
tracker.AddWatcher(GRPC_CHANNEL_SHUTDOWN, tracker.AddWatcher(GRPC_CHANNEL_SHUTDOWN,
MakeOrphanable<Watcher>(&count, &state)); MakeOrphanable<Watcher>(&count, &state, &status));
// No initial notification, since we started the watch from the // No initial notification, since we started the watch from the
// current state. // current state.
EXPECT_EQ(count, 0); EXPECT_EQ(count, 0);

@ -142,10 +142,10 @@ class TestPickArgsLb : public ForwardingLoadBalancingPolicy {
return parent_->channel_control_helper()->CreateSubchannel(args); return parent_->channel_control_helper()->CreateSubchannel(args);
} }
void UpdateState(grpc_connectivity_state state, void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override { std::unique_ptr<SubchannelPicker> picker) override {
parent_->channel_control_helper()->UpdateState( parent_->channel_control_helper()->UpdateState(
state, absl::make_unique<Picker>(std::move(picker), cb_)); state, status, absl::make_unique<Picker>(std::move(picker), cb_));
} }
void RequestReresolution() override { void RequestReresolution() override {
@ -252,10 +252,10 @@ class InterceptRecvTrailingMetadataLoadBalancingPolicy
return parent_->channel_control_helper()->CreateSubchannel(args); return parent_->channel_control_helper()->CreateSubchannel(args);
} }
void UpdateState(grpc_connectivity_state state, void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override { std::unique_ptr<SubchannelPicker> picker) override {
parent_->channel_control_helper()->UpdateState( parent_->channel_control_helper()->UpdateState(
state, absl::make_unique<Picker>(std::move(picker), cb_)); state, status, absl::make_unique<Picker>(std::move(picker), cb_));
} }
void RequestReresolution() override { void RequestReresolution() override {

@ -39,4 +39,5 @@ fi
# Cloning from a local path sets RepositoryUrl to a path and breaks Source Link. # Cloning from a local path sets RepositoryUrl to a path and breaks Source Link.
# Override RepositoryUrl to a URL to fix Source Link. The value doesn't matter. # Override RepositoryUrl to a URL to fix Source Link. The value doesn't matter.
dotnet build --configuration Debug Grpc.DotNet.sln -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git dotnet build --configuration Debug --output ./output/InteropTestsWebsite testassets/InteropTestsWebsite/InteropTestsWebsite.csproj -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git
dotnet build --configuration Debug --output ./output/InteropTestsClient testassets/InteropTestsClient/InteropTestsClient.csproj -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git

@ -190,8 +190,8 @@ class CSharpCoreCLRLanguage:
class AspNetCoreLanguage: class AspNetCoreLanguage:
def __init__(self): def __init__(self):
self.client_cwd = '../grpc-dotnet/testassets/InteropTestsClient/bin/Debug/netcoreapp3.0' self.client_cwd = '../grpc-dotnet/output/InteropTestsClient'
self.server_cwd = '../grpc-dotnet/testassets/InteropTestsWebsite/bin/Debug/netcoreapp3.0' self.server_cwd = '../grpc-dotnet/output/InteropTestsWebsite'
self.safename = str(self) self.safename = str(self)
def cloud_to_prod_env(self): def cloud_to_prod_env(self):

Loading…
Cancel
Save