Merge remote-tracking branch 'upstream/master'

pull/24067/head
walkerdu 4 years ago
commit ef13dcb411
  1. 2
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 2
      .github/ISSUE_TEMPLATE/cleanup_request.md
  3. 2
      .github/ISSUE_TEMPLATE/feature_request.md
  4. 2
      .github/ISSUE_TEMPLATE/question.md
  5. 2
      .github/pull_request_template.md
  6. 6
      BUILD
  7. 6
      BUILD.gn
  8. 154
      CMakeLists.txt
  9. 4
      Makefile
  10. 59
      build_autogenerated.yaml
  11. 58
      cmake/modules/Findre2.cmake
  12. 6
      cmake/re2.cmake
  13. 2
      config.m4
  14. 2
      config.w32
  15. 2
      doc/PROTOCOL-HTTP2.md
  16. 25
      doc/server-reflection.md
  17. 8
      gRPC-C++.podspec
  18. 10
      gRPC-Core.podspec
  19. 1
      grpc.def
  20. 6
      grpc.gemspec
  21. 2
      grpc.gyp
  22. 5
      include/grpc/grpc.h
  23. 6
      package.xml
  24. 59
      src/core/ext/xds/certificate_provider_factory.h
  25. 103
      src/core/ext/xds/certificate_provider_registry.cc
  26. 57
      src/core/ext/xds/certificate_provider_registry.h
  27. 50
      src/core/ext/xds/certificate_provider_store.h
  28. 18
      src/core/lib/iomgr/exec_ctx.h
  29. 7
      src/core/lib/security/certificate_provider.h
  30. 321
      src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc
  31. 214
      src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h
  32. 5
      src/core/lib/security/security_connector/ssl_utils.h
  33. 7
      src/core/lib/surface/channel.h
  34. 35
      src/core/lib/surface/init.cc
  35. 4
      src/core/plugin_registry/grpc_plugin_registry.cc
  36. 1
      src/python/grpcio/grpc/_cython/BUILD.bazel
  37. 2
      src/python/grpcio/grpc_core_dependencies.py
  38. 2
      src/ruby/ext/grpc/rb_grpc_imports.generated.c
  39. 3
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  40. 1
      templates/CMakeLists.txt.template
  41. 12
      test/core/client_channel/BUILD
  42. 90
      test/core/client_channel/certificate_provider_registry_test.cc
  43. 1
      test/core/end2end/tests/bad_ping.cc
  44. 1
      test/core/end2end/tests/ping.cc
  45. 3
      test/core/iomgr/BUILD
  46. 10
      test/core/iomgr/stranded_event_test.cc
  47. 13
      test/core/security/BUILD
  48. 968
      test/core/security/grpc_tls_certificate_distributor_test.cc
  49. 3
      test/core/surface/BUILD
  50. 102
      test/core/surface/init_test.cc
  51. 1
      test/core/surface/public_headers_must_be_c89.c
  52. 1
      test/core/transport/chttp2/too_many_pings_test.cc
  53. 19
      test/core/util/port.cc
  54. 106
      test/cpp/end2end/xds_end2end_test.cc
  55. 51
      test/cpp/util/BUILD
  56. 588
      test/cpp/util/channelz_sampler.cc
  57. 176
      test/cpp/util/channelz_sampler_test.cc
  58. 6
      tools/buildgen/extract_metadata_from_bazel_xml.py
  59. 3
      tools/distrib/python/grpcio_tools/grpc_tools/protoc.py
  60. 6
      tools/doxygen/Doxyfile.c++.internal
  61. 6
      tools/doxygen/Doxyfile.core.internal
  62. 2
      tools/internal_ci/macos/grpc_build_artifacts.cfg
  63. 2
      tools/interop_matrix/client_matrix.py
  64. 80
      tools/run_tests/generated/tests.json
  65. 2
      tools/run_tests/helper_scripts/prep_xds.sh
  66. 2
      tools/run_tests/python_utils/start_port_server.py
  67. 29
      tools/run_tests/run_xds_tests.py

@ -2,7 +2,7 @@
name: Report a bug name: Report a bug
about: Create a report to help us improve about: Create a report to help us improve
labels: kind/bug, priority/P2 labels: kind/bug, priority/P2
assignees: donnadionne assignees: markdroth
--- ---

@ -2,7 +2,7 @@
name: Request a cleanup name: Request a cleanup
about: Suggest a cleanup in our repository about: Suggest a cleanup in our repository
labels: kind/internal cleanup, priority/P2 labels: kind/internal cleanup, priority/P2
assignees: donnadionne assignees: markdroth
--- ---

@ -2,7 +2,7 @@
name: Request a feature name: Request a feature
about: Suggest an idea for this project about: Suggest an idea for this project
labels: kind/enhancement, priority/P2 labels: kind/enhancement, priority/P2
assignees: donnadionne assignees: markdroth
--- ---

@ -2,7 +2,7 @@
name: Ask a question name: Ask a question
about: Ask a question about: Ask a question
labels: kind/question, priority/P3 labels: kind/question, priority/P3
assignees: donnadionne assignees: markdroth
--- ---

@ -8,4 +8,4 @@ If you know who should review your pull request, please remove the mentioning be
--> -->
@donnadionne @markdroth

@ -1695,6 +1695,7 @@ grpc_cc_library(
grpc_cc_library( grpc_cc_library(
name = "grpc_secure", name = "grpc_secure",
srcs = [ srcs = [
"src/core/ext/xds/certificate_provider_registry.cc",
"src/core/lib/http/httpcli_security_connector.cc", "src/core/lib/http/httpcli_security_connector.cc",
"src/core/lib/security/context/security_context.cc", "src/core/lib/security/context/security_context.cc",
"src/core/lib/security/credentials/alts/alts_credentials.cc", "src/core/lib/security/credentials/alts/alts_credentials.cc",
@ -1712,6 +1713,7 @@ grpc_cc_library(
"src/core/lib/security/credentials/oauth2/oauth2_credentials.cc", "src/core/lib/security/credentials/oauth2/oauth2_credentials.cc",
"src/core/lib/security/credentials/plugin/plugin_credentials.cc", "src/core/lib/security/credentials/plugin/plugin_credentials.cc",
"src/core/lib/security/credentials/ssl/ssl_credentials.cc", "src/core/lib/security/credentials/ssl/ssl_credentials.cc",
"src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc",
"src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc",
"src/core/lib/security/credentials/tls/tls_credentials.cc", "src/core/lib/security/credentials/tls/tls_credentials.cc",
"src/core/lib/security/security_connector/alts/alts_security_connector.cc", "src/core/lib/security/security_connector/alts/alts_security_connector.cc",
@ -1734,6 +1736,9 @@ grpc_cc_library(
], ],
hdrs = [ hdrs = [
"src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h",
"src/core/ext/xds/certificate_provider_factory.h",
"src/core/ext/xds/certificate_provider_registry.h",
"src/core/ext/xds/certificate_provider_store.h",
"src/core/ext/xds/xds_channel_args.h", "src/core/ext/xds/xds_channel_args.h",
"src/core/lib/security/certificate_provider.h", "src/core/lib/security/certificate_provider.h",
"src/core/lib/security/context/security_context.h", "src/core/lib/security/context/security_context.h",
@ -1750,6 +1755,7 @@ grpc_cc_library(
"src/core/lib/security/credentials/oauth2/oauth2_credentials.h", "src/core/lib/security/credentials/oauth2/oauth2_credentials.h",
"src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/plugin/plugin_credentials.h",
"src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h",
"src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h",
"src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h",
"src/core/lib/security/credentials/tls/tls_credentials.h", "src/core/lib/security/credentials/tls/tls_credentials.h",
"src/core/lib/security/security_connector/alts/alts_security_connector.h", "src/core/lib/security/security_connector/alts/alts_security_connector.h",

@ -542,6 +542,10 @@ config("grpc_config") {
"src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h", "src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h",
"src/core/ext/upb-generated/validate/validate.upb.c", "src/core/ext/upb-generated/validate/validate.upb.c",
"src/core/ext/upb-generated/validate/validate.upb.h", "src/core/ext/upb-generated/validate/validate.upb.h",
"src/core/ext/xds/certificate_provider_factory.h",
"src/core/ext/xds/certificate_provider_registry.cc",
"src/core/ext/xds/certificate_provider_registry.h",
"src/core/ext/xds/certificate_provider_store.h",
"src/core/ext/xds/xds_api.cc", "src/core/ext/xds/xds_api.cc",
"src/core/ext/xds/xds_api.h", "src/core/ext/xds/xds_api.h",
"src/core/ext/xds/xds_bootstrap.cc", "src/core/ext/xds/xds_bootstrap.cc",
@ -837,6 +841,8 @@ config("grpc_config") {
"src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/plugin/plugin_credentials.h",
"src/core/lib/security/credentials/ssl/ssl_credentials.cc", "src/core/lib/security/credentials/ssl/ssl_credentials.cc",
"src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h",
"src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc",
"src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h",
"src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc",
"src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h",
"src/core/lib/security/credentials/tls/tls_credentials.cc", "src/core/lib/security/credentials/tls/tls_credentials.cc",

@ -606,6 +606,7 @@ if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c httpscli_test) add_dependencies(buildtests_c httpscli_test)
endif() endif()
add_dependencies(buildtests_c init_test)
add_dependencies(buildtests_c inproc_callback_test) add_dependencies(buildtests_c inproc_callback_test)
add_dependencies(buildtests_c invalid_call_argument_test) add_dependencies(buildtests_c invalid_call_argument_test)
add_dependencies(buildtests_c json_token_test) add_dependencies(buildtests_c json_token_test)
@ -784,6 +785,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx byte_buffer_test) add_dependencies(buildtests_cxx byte_buffer_test)
add_dependencies(buildtests_cxx byte_stream_test) add_dependencies(buildtests_cxx byte_stream_test)
add_dependencies(buildtests_cxx cancel_ares_query_test) add_dependencies(buildtests_cxx cancel_ares_query_test)
add_dependencies(buildtests_cxx certificate_provider_registry_test)
add_dependencies(buildtests_cxx cfstream_test) add_dependencies(buildtests_cxx cfstream_test)
add_dependencies(buildtests_cxx channel_arguments_test) add_dependencies(buildtests_cxx channel_arguments_test)
add_dependencies(buildtests_cxx channel_filter_test) add_dependencies(buildtests_cxx channel_filter_test)
@ -821,6 +823,7 @@ if(gRPC_BUILD_TESTS)
endif() endif()
add_dependencies(buildtests_cxx global_config_test) add_dependencies(buildtests_cxx global_config_test)
add_dependencies(buildtests_cxx grpc_cli) add_dependencies(buildtests_cxx grpc_cli)
add_dependencies(buildtests_cxx grpc_tls_certificate_distributor_test)
add_dependencies(buildtests_cxx grpc_tls_credentials_options_test) add_dependencies(buildtests_cxx grpc_tls_credentials_options_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx grpc_tool_test) add_dependencies(buildtests_cxx grpc_tool_test)
@ -835,7 +838,6 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx health_service_end2end_test) add_dependencies(buildtests_cxx health_service_end2end_test)
add_dependencies(buildtests_cxx http2_client) add_dependencies(buildtests_cxx http2_client)
add_dependencies(buildtests_cxx hybrid_end2end_test) add_dependencies(buildtests_cxx hybrid_end2end_test)
add_dependencies(buildtests_cxx init_test)
add_dependencies(buildtests_cxx initial_settings_frame_bad_client_test) add_dependencies(buildtests_cxx initial_settings_frame_bad_client_test)
add_dependencies(buildtests_cxx interop_client) add_dependencies(buildtests_cxx interop_client)
add_dependencies(buildtests_cxx interop_server) add_dependencies(buildtests_cxx interop_server)
@ -1595,6 +1597,7 @@ add_library(grpc
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c src/core/ext/upb-generated/udpa/annotations/versioning.upb.c
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
src/core/ext/upb-generated/validate/validate.upb.c src/core/ext/upb-generated/validate/validate.upb.c
src/core/ext/xds/certificate_provider_registry.cc
src/core/ext/xds/xds_api.cc src/core/ext/xds/xds_api.cc
src/core/ext/xds/xds_bootstrap.cc src/core/ext/xds/xds_bootstrap.cc
src/core/ext/xds/xds_client.cc src/core/ext/xds/xds_client.cc
@ -1748,6 +1751,7 @@ add_library(grpc
src/core/lib/security/credentials/oauth2/oauth2_credentials.cc src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
src/core/lib/security/credentials/plugin/plugin_credentials.cc src/core/lib/security/credentials/plugin/plugin_credentials.cc
src/core/lib/security/credentials/ssl/ssl_credentials.cc src/core/lib/security/credentials/ssl/ssl_credentials.cc
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc
src/core/lib/security/credentials/tls/tls_credentials.cc src/core/lib/security/credentials/tls/tls_credentials.cc
src/core/lib/security/security_connector/alts/alts_security_connector.cc src/core/lib/security/security_connector/alts/alts_security_connector.cc
@ -5987,6 +5991,36 @@ endif()
endif() endif()
if(gRPC_BUILD_TESTS) if(gRPC_BUILD_TESTS)
add_executable(init_test
test/core/surface/init_test.cc
)
target_include_directories(init_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
)
target_link_libraries(init_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr
address_sorting
upb
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(inproc_callback_test add_executable(inproc_callback_test
test/core/end2end/inproc_callback_test.cc test/core/end2end/inproc_callback_test.cc
) )
@ -9605,6 +9639,45 @@ target_link_libraries(cancel_ares_query_test
) )
endif()
if(gRPC_BUILD_TESTS)
add_executable(certificate_provider_registry_test
test/core/client_channel/certificate_provider_registry_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(certificate_provider_registry_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(certificate_provider_registry_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr
address_sorting
upb
${_gRPC_GFLAGS_LIBRARIES}
)
endif() endif()
if(gRPC_BUILD_TESTS) if(gRPC_BUILD_TESTS)
@ -11361,6 +11434,45 @@ if(gRPC_INSTALL)
) )
endif() endif()
endif()
if(gRPC_BUILD_TESTS)
add_executable(grpc_tls_certificate_distributor_test
test/core/security/grpc_tls_certificate_distributor_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(grpc_tls_certificate_distributor_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(grpc_tls_certificate_distributor_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr
address_sorting
upb
${_gRPC_GFLAGS_LIBRARIES}
)
endif() endif()
if(gRPC_BUILD_TESTS) if(gRPC_BUILD_TESTS)
@ -11868,45 +11980,6 @@ target_link_libraries(hybrid_end2end_test
) )
endif()
if(gRPC_BUILD_TESTS)
add_executable(init_test
test/core/surface/init_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(init_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(init_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr
address_sorting
upb
${_gRPC_GFLAGS_LIBRARIES}
)
endif() endif()
if(gRPC_BUILD_TESTS) if(gRPC_BUILD_TESTS)
@ -15624,6 +15697,7 @@ install(FILES
) )
install(FILES install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/Findc-ares.cmake ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/Findc-ares.cmake
${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/Findre2.cmake
DESTINATION ${gRPC_INSTALL_CMAKEDIR}/modules DESTINATION ${gRPC_INSTALL_CMAKEDIR}/modules
) )

@ -2002,6 +2002,7 @@ LIBGRPC_SRC = \
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \ src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \ src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
src/core/ext/upb-generated/validate/validate.upb.c \ src/core/ext/upb-generated/validate/validate.upb.c \
src/core/ext/xds/certificate_provider_registry.cc \
src/core/ext/xds/xds_api.cc \ src/core/ext/xds/xds_api.cc \
src/core/ext/xds/xds_bootstrap.cc \ src/core/ext/xds/xds_bootstrap.cc \
src/core/ext/xds/xds_client.cc \ src/core/ext/xds/xds_client.cc \
@ -2155,6 +2156,7 @@ LIBGRPC_SRC = \
src/core/lib/security/credentials/oauth2/oauth2_credentials.cc \ src/core/lib/security/credentials/oauth2/oauth2_credentials.cc \
src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/plugin/plugin_credentials.cc \
src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \
src/core/lib/security/credentials/tls/tls_credentials.cc \ src/core/lib/security/credentials/tls/tls_credentials.cc \
src/core/lib/security/security_connector/alts/alts_security_connector.cc \ src/core/lib/security/security_connector/alts/alts_security_connector.cc \
@ -4586,6 +4588,7 @@ src/core/ext/upb-generated/udpa/annotations/migrate.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/udpa/annotations/status.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/udpa/annotations/status.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/udpa/annotations/versioning.upb.c: $(OPENSSL_DEP)
src/core/ext/xds/certificate_provider_registry.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_api.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_api.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_bootstrap.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_bootstrap.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_client.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_client.cc: $(OPENSSL_DEP)
@ -4616,6 +4619,7 @@ src/core/lib/security/credentials/local/local_credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/oauth2/oauth2_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/oauth2/oauth2_credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/plugin/plugin_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/plugin/plugin_credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/ssl/ssl_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/ssl/ssl_credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/tls/tls_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/tls/tls_credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/security_connector/alts/alts_security_connector.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/alts/alts_security_connector.cc: $(OPENSSL_DEP)

@ -534,6 +534,9 @@ libs:
- src/core/ext/upb-generated/udpa/annotations/versioning.upb.h - src/core/ext/upb-generated/udpa/annotations/versioning.upb.h
- src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h
- src/core/ext/upb-generated/validate/validate.upb.h - src/core/ext/upb-generated/validate/validate.upb.h
- src/core/ext/xds/certificate_provider_factory.h
- src/core/ext/xds/certificate_provider_registry.h
- src/core/ext/xds/certificate_provider_store.h
- src/core/ext/xds/xds_api.h - src/core/ext/xds/xds_api.h
- src/core/ext/xds/xds_bootstrap.h - src/core/ext/xds/xds_bootstrap.h
- src/core/ext/xds/xds_channel_args.h - src/core/ext/xds/xds_channel_args.h
@ -676,6 +679,7 @@ libs:
- src/core/lib/security/credentials/oauth2/oauth2_credentials.h - src/core/lib/security/credentials/oauth2/oauth2_credentials.h
- src/core/lib/security/credentials/plugin/plugin_credentials.h - src/core/lib/security/credentials/plugin/plugin_credentials.h
- src/core/lib/security/credentials/ssl/ssl_credentials.h - src/core/lib/security/credentials/ssl/ssl_credentials.h
- src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h
- src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h - src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h
- src/core/lib/security/credentials/tls/tls_credentials.h - src/core/lib/security/credentials/tls/tls_credentials.h
- src/core/lib/security/security_connector/alts/alts_security_connector.h - src/core/lib/security/security_connector/alts/alts_security_connector.h
@ -939,6 +943,7 @@ libs:
- src/core/ext/upb-generated/udpa/annotations/versioning.upb.c - src/core/ext/upb-generated/udpa/annotations/versioning.upb.c
- src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
- src/core/ext/upb-generated/validate/validate.upb.c - src/core/ext/upb-generated/validate/validate.upb.c
- src/core/ext/xds/certificate_provider_registry.cc
- src/core/ext/xds/xds_api.cc - src/core/ext/xds/xds_api.cc
- src/core/ext/xds/xds_bootstrap.cc - src/core/ext/xds/xds_bootstrap.cc
- src/core/ext/xds/xds_client.cc - src/core/ext/xds/xds_client.cc
@ -1092,6 +1097,7 @@ libs:
- src/core/lib/security/credentials/oauth2/oauth2_credentials.cc - src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
- src/core/lib/security/credentials/plugin/plugin_credentials.cc - src/core/lib/security/credentials/plugin/plugin_credentials.cc
- src/core/lib/security/credentials/ssl/ssl_credentials.cc - src/core/lib/security/credentials/ssl/ssl_credentials.cc
- src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc
- src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc - src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc
- src/core/lib/security/credentials/tls/tls_credentials.cc - src/core/lib/security/credentials/tls/tls_credentials.cc
- src/core/lib/security/security_connector/alts/alts_security_connector.cc - src/core/lib/security/security_connector/alts/alts_security_connector.cc
@ -3573,6 +3579,19 @@ targets:
- linux - linux
- posix - posix
- mac - mac
- name: init_test
build: test
language: c
headers: []
src:
- test/core/surface/init_test.cc
deps:
- grpc_test_util
- grpc
- gpr
- address_sorting
- upb
uses_polling: false
- name: inproc_callback_test - name: inproc_callback_test
build: test build: test
language: c language: c
@ -5234,6 +5253,19 @@ targets:
- gpr - gpr
- address_sorting - address_sorting
- upb - upb
- name: certificate_provider_registry_test
gtest: true
build: test
language: c++
headers: []
src:
- test/core/client_channel/certificate_provider_registry_test.cc
deps:
- grpc_test_util
- grpc
- gpr
- address_sorting
- upb
- name: cfstream_test - name: cfstream_test
gtest: true gtest: true
build: test build: test
@ -5899,6 +5931,19 @@ targets:
deps: deps:
- grpc_plugin_support - grpc_plugin_support
secure: false secure: false
- name: grpc_tls_certificate_distributor_test
gtest: true
build: test
language: c++
headers: []
src:
- test/core/security/grpc_tls_certificate_distributor_test.cc
deps:
- grpc_test_util
- grpc
- gpr
- address_sorting
- upb
- name: grpc_tls_credentials_options_test - name: grpc_tls_credentials_options_test
gtest: true gtest: true
build: test build: test
@ -6155,20 +6200,6 @@ targets:
- gpr - gpr
- address_sorting - address_sorting
- upb - upb
- name: init_test
gtest: true
build: test
language: c++
headers: []
src:
- test/core/surface/init_test.cc
deps:
- grpc_test_util
- grpc
- gpr
- address_sorting
- upb
uses_polling: false
- name: initial_settings_frame_bad_client_test - name: initial_settings_frame_bad_client_test
gtest: true gtest: true
build: test build: test

@ -0,0 +1,58 @@
# Copyright 2017 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
find_package(re2 QUIET CONFIG)
if(re2_FOUND)
message(STATUS "Found RE2 via CMake.")
return()
endif()
find_package(PkgConfig REQUIRED)
# TODO(junyer): Use the IMPORTED_TARGET option whenever CMake 3.6 (or newer)
# becomes the minimum required: that will take care of the add_library() and
# set_property() calls; then we can simply alias PkgConfig::RE2 as re2::re2.
# For now, we can only set INTERFACE_* properties that existed in CMake 3.5.
pkg_check_modules(RE2 QUIET re2)
if(RE2_FOUND)
set(re2_FOUND "${RE2_FOUND}")
add_library(re2::re2 INTERFACE IMPORTED)
if(RE2_INCLUDE_DIRS)
set_property(TARGET re2::re2 PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${RE2_INCLUDE_DIRS}")
endif()
if(RE2_CFLAGS_OTHER)
# Filter out the -std flag, which is handled by CMAKE_CXX_STANDARD.
# TODO(junyer): Use the FILTER option whenever CMake 3.6 (or newer)
# becomes the minimum required: that will allow this to be concise.
foreach(flag IN LISTS RE2_CFLAGS_OTHER)
if("${flag}" MATCHES "^-std=")
list(REMOVE_ITEM RE2_CFLAGS_OTHER "${flag}")
endif()
endforeach()
set_property(TARGET re2::re2 PROPERTY
INTERFACE_COMPILE_OPTIONS "${RE2_CFLAGS_OTHER}")
endif()
if(RE2_LDFLAGS)
set_property(TARGET re2::re2 PROPERTY
INTERFACE_LINK_LIBRARIES "${RE2_LDFLAGS}")
endif()
message(STATUS "Found RE2 via pkg-config.")
return()
endif()
if(re2_FIND_REQUIRED)
message(FATAL_ERROR "Failed to find RE2.")
elseif(NOT re2_FIND_QUIETLY)
message(WARNING "Failed to find RE2.")
endif()

@ -45,13 +45,9 @@ if(gRPC_RE2_PROVIDER STREQUAL "module")
set(gRPC_INSTALL FALSE) set(gRPC_INSTALL FALSE)
endif() endif()
elseif(gRPC_RE2_PROVIDER STREQUAL "package") elseif(gRPC_RE2_PROVIDER STREQUAL "package")
find_package(re2 REQUIRED CONFIG) find_package(re2 REQUIRED)
if(TARGET re2::re2) if(TARGET re2::re2)
set(_gRPC_RE2_LIBRARIES re2::re2) set(_gRPC_RE2_LIBRARIES re2::re2)
else()
set(_gRPC_RE2_LIBRARIES ${RE2_LIBRARIES})
endif() endif()
set(_gRPC_RE2_INCLUDE_DIR ${RE2_INCLUDE_DIRS})
set(_gRPC_FIND_RE2 "if(NOT re2_FOUND)\n find_package(re2)\nendif()") set(_gRPC_FIND_RE2 "if(NOT re2_FOUND)\n find_package(re2)\nendif()")
endif() endif()

@ -223,6 +223,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \ src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \ src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
src/core/ext/upb-generated/validate/validate.upb.c \ src/core/ext/upb-generated/validate/validate.upb.c \
src/core/ext/xds/certificate_provider_registry.cc \
src/core/ext/xds/xds_api.cc \ src/core/ext/xds/xds_api.cc \
src/core/ext/xds/xds_bootstrap.cc \ src/core/ext/xds/xds_bootstrap.cc \
src/core/ext/xds/xds_client.cc \ src/core/ext/xds/xds_client.cc \
@ -417,6 +418,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/security/credentials/oauth2/oauth2_credentials.cc \ src/core/lib/security/credentials/oauth2/oauth2_credentials.cc \
src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/plugin/plugin_credentials.cc \
src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \
src/core/lib/security/credentials/tls/tls_credentials.cc \ src/core/lib/security/credentials/tls/tls_credentials.cc \
src/core/lib/security/security_connector/alts/alts_security_connector.cc \ src/core/lib/security/security_connector/alts/alts_security_connector.cc \

@ -190,6 +190,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\upb-generated\\udpa\\annotations\\versioning.upb.c " + "src\\core\\ext\\upb-generated\\udpa\\annotations\\versioning.upb.c " +
"src\\core\\ext\\upb-generated\\udpa\\data\\orca\\v1\\orca_load_report.upb.c " + "src\\core\\ext\\upb-generated\\udpa\\data\\orca\\v1\\orca_load_report.upb.c " +
"src\\core\\ext\\upb-generated\\validate\\validate.upb.c " + "src\\core\\ext\\upb-generated\\validate\\validate.upb.c " +
"src\\core\\ext\\xds\\certificate_provider_registry.cc " +
"src\\core\\ext\\xds\\xds_api.cc " + "src\\core\\ext\\xds\\xds_api.cc " +
"src\\core\\ext\\xds\\xds_bootstrap.cc " + "src\\core\\ext\\xds\\xds_bootstrap.cc " +
"src\\core\\ext\\xds\\xds_client.cc " + "src\\core\\ext\\xds\\xds_client.cc " +
@ -384,6 +385,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\security\\credentials\\oauth2\\oauth2_credentials.cc " + "src\\core\\lib\\security\\credentials\\oauth2\\oauth2_credentials.cc " +
"src\\core\\lib\\security\\credentials\\plugin\\plugin_credentials.cc " + "src\\core\\lib\\security\\credentials\\plugin\\plugin_credentials.cc " +
"src\\core\\lib\\security\\credentials\\ssl\\ssl_credentials.cc " + "src\\core\\lib\\security\\credentials\\ssl\\ssl_credentials.cc " +
"src\\core\\lib\\security\\credentials\\tls\\grpc_tls_certificate_distributor.cc " +
"src\\core\\lib\\security\\credentials\\tls\\grpc_tls_credentials_options.cc " + "src\\core\\lib\\security\\credentials\\tls\\grpc_tls_credentials_options.cc " +
"src\\core\\lib\\security\\credentials\\tls\\tls_credentials.cc " + "src\\core\\lib\\security\\credentials\\tls\\tls_credentials.cc " +
"src\\core\\lib\\security\\security_connector\\alts\\alts_security_connector.cc " + "src\\core\\lib\\security\\security_connector\\alts\\alts_security_connector.cc " +

@ -215,7 +215,7 @@ The following mapping from RST_STREAM error codes to GRPC error codes is applied
HTTP2 Code|GRPC Code HTTP2 Code|GRPC Code
----------|----------- ----------|-----------
NO_ERROR(0)|INTERNAL - An explicit GRPC status of OK should have been sent but this might be used to aggressively lameduck in some scenarios. NO_ERROR(0)|INTERNAL - An explicit GRPC status of OK should have been sent but this might be used to aggressively [lameduck](https://landing.google.com/sre/sre-book/chapters/load-balancing-datacenter/#identifying-bad-tasks-flow-control-and-lame-ducks-bEs0uy) in some scenarios.
PROTOCOL_ERROR(1)|INTERNAL PROTOCOL_ERROR(1)|INTERNAL
INTERNAL_ERROR(2)|INTERNAL INTERNAL_ERROR(2)|INTERNAL
FLOW_CONTROL_ERROR(3)|INTERNAL FLOW_CONTROL_ERROR(3)|INTERNAL

@ -23,29 +23,8 @@ We want to be able to answer the following queries:
Specifically, what are the names of the methods, are those methods unary or Specifically, what are the names of the methods, are those methods unary or
streaming, and what are the types of the argument and result? streaming, and what are the types of the argument and result?
``` The first proposed version of the protocol is here:
#TODO(dklempner): link to an actual .proto later. https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto
package grpc.reflection.v1alpha;
message ListApisRequest {
}
message ListApisResponse {
repeated google.protobuf.Api apis = 1;
}
message GetMethodRequest {
string method = 1;
}
message GetMethodResponse {
google.protobuf.Method method = 1;
}
service ServerReflection {
rpc ListApis (ListApisRequest) returns (ListApisResponse);
rpc GetMethod (GetMethodRequest) returns (GetMethodResponse);
}
```
Note that a server is under no obligation to return a complete list of all Note that a server is under no obligation to return a complete list of all
methods it supports. For example, a reverse proxy may support server reflection methods it supports. For example, a reverse proxy may support server reflection

@ -367,6 +367,9 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h', 'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h', 'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
'src/core/ext/upb-generated/validate/validate.upb.h', 'src/core/ext/upb-generated/validate/validate.upb.h',
'src/core/ext/xds/certificate_provider_factory.h',
'src/core/ext/xds/certificate_provider_registry.h',
'src/core/ext/xds/certificate_provider_store.h',
'src/core/ext/xds/xds_api.h', 'src/core/ext/xds/xds_api.h',
'src/core/ext/xds/xds_bootstrap.h', 'src/core/ext/xds/xds_bootstrap.h',
'src/core/ext/xds/xds_channel_args.h', 'src/core/ext/xds/xds_channel_args.h',
@ -537,6 +540,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/oauth2/oauth2_credentials.h', 'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/plugin/plugin_credentials.h',
'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h',
'src/core/lib/security/credentials/tls/tls_credentials.h', 'src/core/lib/security/credentials/tls/tls_credentials.h',
'src/core/lib/security/security_connector/alts/alts_security_connector.h', 'src/core/lib/security/security_connector/alts/alts_security_connector.h',
@ -866,6 +870,9 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h', 'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h', 'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
'src/core/ext/upb-generated/validate/validate.upb.h', 'src/core/ext/upb-generated/validate/validate.upb.h',
'src/core/ext/xds/certificate_provider_factory.h',
'src/core/ext/xds/certificate_provider_registry.h',
'src/core/ext/xds/certificate_provider_store.h',
'src/core/ext/xds/xds_api.h', 'src/core/ext/xds/xds_api.h',
'src/core/ext/xds/xds_bootstrap.h', 'src/core/ext/xds/xds_bootstrap.h',
'src/core/ext/xds/xds_channel_args.h', 'src/core/ext/xds/xds_channel_args.h',
@ -1036,6 +1043,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/oauth2/oauth2_credentials.h', 'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/plugin/plugin_credentials.h',
'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h',
'src/core/lib/security/credentials/tls/tls_credentials.h', 'src/core/lib/security/credentials/tls/tls_credentials.h',
'src/core/lib/security/security_connector/alts/alts_security_connector.h', 'src/core/lib/security/security_connector/alts/alts_security_connector.h',

@ -528,6 +528,10 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h', 'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
'src/core/ext/upb-generated/validate/validate.upb.c', 'src/core/ext/upb-generated/validate/validate.upb.c',
'src/core/ext/upb-generated/validate/validate.upb.h', 'src/core/ext/upb-generated/validate/validate.upb.h',
'src/core/ext/xds/certificate_provider_factory.h',
'src/core/ext/xds/certificate_provider_registry.cc',
'src/core/ext/xds/certificate_provider_registry.h',
'src/core/ext/xds/certificate_provider_store.h',
'src/core/ext/xds/xds_api.cc', 'src/core/ext/xds/xds_api.cc',
'src/core/ext/xds/xds_api.h', 'src/core/ext/xds/xds_api.h',
'src/core/ext/xds/xds_bootstrap.cc', 'src/core/ext/xds/xds_bootstrap.cc',
@ -892,6 +896,8 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/plugin/plugin_credentials.h',
'src/core/lib/security/credentials/ssl/ssl_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc',
'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h',
'src/core/lib/security/credentials/tls/tls_credentials.cc', 'src/core/lib/security/credentials/tls/tls_credentials.cc',
@ -1278,6 +1284,9 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h', 'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h', 'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
'src/core/ext/upb-generated/validate/validate.upb.h', 'src/core/ext/upb-generated/validate/validate.upb.h',
'src/core/ext/xds/certificate_provider_factory.h',
'src/core/ext/xds/certificate_provider_registry.h',
'src/core/ext/xds/certificate_provider_store.h',
'src/core/ext/xds/xds_api.h', 'src/core/ext/xds/xds_api.h',
'src/core/ext/xds/xds_bootstrap.h', 'src/core/ext/xds/xds_bootstrap.h',
'src/core/ext/xds/xds_channel_args.h', 'src/core/ext/xds/xds_channel_args.h',
@ -1448,6 +1457,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/oauth2/oauth2_credentials.h', 'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/plugin/plugin_credentials.h',
'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h',
'src/core/lib/security/credentials/tls/tls_credentials.h', 'src/core/lib/security/credentials/tls/tls_credentials.h',
'src/core/lib/security/security_connector/alts/alts_security_connector.h', 'src/core/lib/security/security_connector/alts/alts_security_connector.h',

@ -35,7 +35,6 @@ EXPORTS
grpc_channel_watch_connectivity_state grpc_channel_watch_connectivity_state
grpc_channel_support_connectivity_watcher grpc_channel_support_connectivity_watcher
grpc_channel_create_call grpc_channel_create_call
grpc_channel_ping
grpc_channel_register_call grpc_channel_register_call
grpc_channel_create_registered_call grpc_channel_create_registered_call
grpc_call_arena_alloc grpc_call_arena_alloc

@ -446,6 +446,10 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h ) s.files += %w( src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h )
s.files += %w( src/core/ext/upb-generated/validate/validate.upb.c ) s.files += %w( src/core/ext/upb-generated/validate/validate.upb.c )
s.files += %w( src/core/ext/upb-generated/validate/validate.upb.h ) s.files += %w( src/core/ext/upb-generated/validate/validate.upb.h )
s.files += %w( src/core/ext/xds/certificate_provider_factory.h )
s.files += %w( src/core/ext/xds/certificate_provider_registry.cc )
s.files += %w( src/core/ext/xds/certificate_provider_registry.h )
s.files += %w( src/core/ext/xds/certificate_provider_store.h )
s.files += %w( src/core/ext/xds/xds_api.cc ) s.files += %w( src/core/ext/xds/xds_api.cc )
s.files += %w( src/core/ext/xds/xds_api.h ) s.files += %w( src/core/ext/xds/xds_api.h )
s.files += %w( src/core/ext/xds/xds_bootstrap.cc ) s.files += %w( src/core/ext/xds/xds_bootstrap.cc )
@ -810,6 +814,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h ) s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h )
s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.cc ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.cc )
s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h )
s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc )
s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h )
s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc ) s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc )
s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h ) s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h )
s.files += %w( src/core/lib/security/credentials/tls/tls_credentials.cc ) s.files += %w( src/core/lib/security/credentials/tls/tls_credentials.cc )

@ -628,6 +628,7 @@
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.c', 'src/core/ext/upb-generated/udpa/annotations/versioning.upb.c',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c', 'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
'src/core/ext/upb-generated/validate/validate.upb.c', 'src/core/ext/upb-generated/validate/validate.upb.c',
'src/core/ext/xds/certificate_provider_registry.cc',
'src/core/ext/xds/xds_api.cc', 'src/core/ext/xds/xds_api.cc',
'src/core/ext/xds/xds_bootstrap.cc', 'src/core/ext/xds/xds_bootstrap.cc',
'src/core/ext/xds/xds_client.cc', 'src/core/ext/xds/xds_client.cc',
@ -781,6 +782,7 @@
'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc', 'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc',
'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/plugin/plugin_credentials.cc',
'src/core/lib/security/credentials/ssl/ssl_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc',
'src/core/lib/security/credentials/tls/tls_credentials.cc', 'src/core/lib/security/credentials/tls/tls_credentials.cc',
'src/core/lib/security/security_connector/alts/alts_security_connector.cc', 'src/core/lib/security/security_connector/alts/alts_security_connector.cc',

@ -219,11 +219,6 @@ GRPCAPI grpc_call* grpc_channel_create_call(
grpc_completion_queue* completion_queue, grpc_slice method, grpc_completion_queue* completion_queue, grpc_slice method,
const grpc_slice* host, gpr_timespec deadline, void* reserved); const grpc_slice* host, gpr_timespec deadline, void* reserved);
/** Ping the channels peer (load balanced channels will select one sub-channel
to ping); if the channel is not connected, posts a failed. */
GRPCAPI void grpc_channel_ping(grpc_channel* channel, grpc_completion_queue* cq,
void* tag, void* reserved);
/** Pre-register a method/host pair on a channel. /** Pre-register a method/host pair on a channel.
method and host are not owned and must remain alive while the channel is method and host are not owned and must remain alive while the channel is
alive. */ alive. */

@ -426,6 +426,10 @@
<file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/upb-generated/validate/validate.upb.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/upb-generated/validate/validate.upb.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/upb-generated/validate/validate.upb.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/upb-generated/validate/validate.upb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/certificate_provider_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/certificate_provider_registry.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/certificate_provider_registry.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/certificate_provider_store.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/xds_api.cc" role="src" /> <file baseinstalldir="/" name="src/core/ext/xds/xds_api.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/xds_api.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/xds/xds_api.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/xds_bootstrap.cc" role="src" /> <file baseinstalldir="/" name="src/core/ext/xds/xds_bootstrap.cc" role="src" />
@ -790,6 +794,8 @@
<file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/tls_credentials.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/tls/tls_credentials.cc" role="src" />

@ -0,0 +1,59 @@
//
//
// Copyright 2020 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#ifndef GRPC_CORE_EXT_XDS_CERTIFICATE_PROVIDER_FACTORY_H
#define GRPC_CORE_EXT_XDS_CERTIFICATE_PROVIDER_FACTORY_H
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/json/json.h"
#include "src/core/lib/security/certificate_provider.h"
namespace grpc_core {
// Factories for plugins. Each plugin implementation should create its own
// factory implementation and register an instance with the registry.
class CertificateProviderFactory {
public:
// Interface for configs for CertificateProviders.
class Config {
public:
virtual ~Config() = default;
// Name of the type of the CertificateProvider. Unique to each type of
// config.
virtual const char* name() const = 0;
};
virtual ~CertificateProviderFactory() = default;
// Name of the plugin.
virtual const char* name() const = 0;
virtual std::unique_ptr<Config> CreateCertificateProviderConfig(
const Json& config_json, grpc_error** error) = 0;
// Create a CertificateProvider instance from config.
virtual RefCountedPtr<grpc_tls_certificate_provider>
CreateCertificateProvider(std::unique_ptr<Config> config) = 0;
};
} // namespace grpc_core
#endif // GRPC_CORE_EXT_XDS_CERTIFICATE_PROVIDER_FACTORY_H

@ -0,0 +1,103 @@
//
//
// Copyright 2020 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#include <grpc/support/port_platform.h>
#include "absl/container/inlined_vector.h"
#include "src/core/ext/xds/certificate_provider_registry.h"
namespace grpc_core {
namespace {
class RegistryState {
public:
void RegisterCertificateProviderFactory(
std::unique_ptr<CertificateProviderFactory> factory) {
gpr_log(GPR_DEBUG, "registering certificate provider factory for \"%s\"",
factory->name());
for (size_t i = 0; i < factories_.size(); ++i) {
GPR_ASSERT(strcmp(factories_[i]->name(), factory->name()) != 0);
}
factories_.push_back(std::move(factory));
}
CertificateProviderFactory* LookupCertificateProviderFactory(
absl::string_view name) const {
for (size_t i = 0; i < factories_.size(); ++i) {
if (name == factories_[i]->name()) {
return factories_[i].get();
}
}
return nullptr;
}
private:
// We currently support 3 factories without doing additional
// allocation. This number could be raised if there is a case where
// more factories are needed and the additional allocations are
// hurting performance (which is unlikely, since these allocations
// only occur at gRPC initialization time).
absl::InlinedVector<std::unique_ptr<CertificateProviderFactory>, 3>
factories_;
};
static RegistryState* g_state = nullptr;
} // namespace
//
// CertificateProviderRegistry
//
CertificateProviderFactory*
CertificateProviderRegistry::LookupCertificateProviderFactory(
absl::string_view name) {
GPR_ASSERT(g_state != nullptr);
return g_state->LookupCertificateProviderFactory(name);
}
void CertificateProviderRegistry::InitRegistry() {
if (g_state == nullptr) g_state = new RegistryState();
}
void CertificateProviderRegistry::ShutdownRegistry() {
delete g_state;
g_state = nullptr;
}
void CertificateProviderRegistry::RegisterCertificateProviderFactory(
std::unique_ptr<CertificateProviderFactory> factory) {
InitRegistry();
g_state->RegisterCertificateProviderFactory(std::move(factory));
}
} // namespace grpc_core
//
// Plugin registration
//
void grpc_certificate_provider_registry_init() {
grpc_core::CertificateProviderRegistry::InitRegistry();
}
void grpc_certificate_provider_registry_shutdown() {
grpc_core::CertificateProviderRegistry::ShutdownRegistry();
}

@ -0,0 +1,57 @@
//
//
// Copyright 2020 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#ifndef GRPC_CORE_EXT_XDS_CERTIFICATE_PROVIDER_REGISTRY_H
#define GRPC_CORE_EXT_XDS_CERTIFICATE_PROVIDER_REGISTRY_H
#include <grpc/support/port_platform.h>
#include <string>
#include "src/core/ext/xds/certificate_provider_factory.h"
namespace grpc_core {
// Global registry for all the certificate provider plugins.
class CertificateProviderRegistry {
public:
// Returns the factory for the plugin keyed by name.
static CertificateProviderFactory* LookupCertificateProviderFactory(
absl::string_view name);
// The following methods are used to create and populate the
// CertificateProviderRegistry. NOT THREAD SAFE -- to be used only during
// global gRPC initialization and shutdown.
// Global initialization of the registry.
static void InitRegistry();
// Global shutdown of the registry.
static void ShutdownRegistry();
// Register a provider with the registry. Can only be called after calling
// InitRegistry(). The key of the factory is extracted from factory
// parameter with method CertificateProviderFactory::name. If the same key
// is registered twice, an exception is raised.
static void RegisterCertificateProviderFactory(
std::unique_ptr<CertificateProviderFactory> factory);
};
} // namespace grpc_core
#endif // GRPC_CORE_EXT_XDS_CERTIFICATE_PROVIDER_REGISTRY_H

@ -0,0 +1,50 @@
//
//
// Copyright 2020 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#ifndef GRPC_CORE_EXT_XDS_CERTIFICATE_PROVIDER_STORE_H
#define GRPC_CORE_EXT_XDS_CERTIFICATE_PROVIDER_STORE_H
#include <grpc/support/port_platform.h>
#include <map>
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/security/certificate_provider.h"
namespace grpc_core {
// Map for xDS based grpc_tls_certificate_provider instances.
class CertificateProviderStore {
public:
// If a provider corresponding to the config is found, a raw pointer to the
// grpc_tls_certificate_provider in the map is returned. If no provider is
// found for a key, a new provider is created. The CertificateProviderStore
// maintains a ref to the grpc_tls_certificate_provider for its entire
// lifetime.
RefCountedPtr<grpc_tls_certificate_provider> CreateOrGetCertificateProvider(
absl::string_view key);
private:
// Underlying map for the providers.
std::map<std::string, RefCountedPtr<grpc_tls_certificate_provider>> map_;
};
} // namespace grpc_core
#endif // GRPC_CORE_EXT_XDS_CERTIFICATE_PROVIDER_STORE_H

@ -331,15 +331,9 @@ class ApplicationCallbackExecCtx {
} }
} }
uintptr_t Flags() { return flags_; }
static ApplicationCallbackExecCtx* Get() {
return reinterpret_cast<ApplicationCallbackExecCtx*>(
gpr_tls_get(&callback_exec_ctx_));
}
static void Set(ApplicationCallbackExecCtx* exec_ctx, uintptr_t flags) { static void Set(ApplicationCallbackExecCtx* exec_ctx, uintptr_t flags) {
if (Get() == nullptr) { if (reinterpret_cast<ApplicationCallbackExecCtx*>(
gpr_tls_get(&callback_exec_ctx_)) == nullptr) {
if (!(GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags)) { if (!(GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags)) {
grpc_core::Fork::IncExecCtxCount(); grpc_core::Fork::IncExecCtxCount();
} }
@ -352,7 +346,8 @@ class ApplicationCallbackExecCtx {
functor->internal_success = is_success; functor->internal_success = is_success;
functor->internal_next = nullptr; functor->internal_next = nullptr;
ApplicationCallbackExecCtx* ctx = Get(); auto* ctx = reinterpret_cast<ApplicationCallbackExecCtx*>(
gpr_tls_get(&callback_exec_ctx_));
if (ctx->head_ == nullptr) { if (ctx->head_ == nullptr) {
ctx->head_ = functor; ctx->head_ = functor;
@ -369,7 +364,10 @@ class ApplicationCallbackExecCtx {
/** Global shutdown for ApplicationCallbackExecCtx. Called by init. */ /** Global shutdown for ApplicationCallbackExecCtx. Called by init. */
static void GlobalShutdown(void) { gpr_tls_destroy(&callback_exec_ctx_); } static void GlobalShutdown(void) { gpr_tls_destroy(&callback_exec_ctx_); }
static bool Available() { return Get() != nullptr; } static bool Available() {
return reinterpret_cast<ApplicationCallbackExecCtx*>(
gpr_tls_get(&callback_exec_ctx_)) != nullptr;
}
private: private:
uintptr_t flags_{0u}; uintptr_t flags_{0u};

@ -21,6 +21,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/iomgr/pollset_set.h"
@ -38,7 +39,7 @@ struct grpc_tls_certificate_distributor;
// contexts become valid or changed, a grpc_tls_certificate_provider should // contexts become valid or changed, a grpc_tls_certificate_provider should
// notify its distributor so as to propagate the update to the watchers. // notify its distributor so as to propagate the update to the watchers.
struct grpc_tls_certificate_provider struct grpc_tls_certificate_provider
: public RefCounted<grpc_tls_certificate_provider> { : public grpc_core::RefCounted<grpc_tls_certificate_provider> {
public: public:
grpc_tls_certificate_provider() grpc_tls_certificate_provider()
: interested_parties_(grpc_pollset_set_create()) {} : interested_parties_(grpc_pollset_set_create()) {}
@ -49,8 +50,8 @@ struct grpc_tls_certificate_provider
grpc_pollset_set* interested_parties() const { return interested_parties_; } grpc_pollset_set* interested_parties() const { return interested_parties_; }
virtual RefCountedPtr<grpc_tls_certificate_distributor> distributor() virtual grpc_core::RefCountedPtr<grpc_tls_certificate_distributor>
const = 0; distributor() const = 0;
private: private:
grpc_pollset_set* interested_parties_; grpc_pollset_set* interested_parties_;

@ -0,0 +1,321 @@
//
// Copyright 2020 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <grpc/support/port_platform.h>
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <stdlib.h>
#include <string.h>
void grpc_tls_certificate_distributor::SetKeyMaterials(
const std::string& cert_name, absl::optional<std::string> pem_root_certs,
absl::optional<PemKeyCertPairList> pem_key_cert_pairs) {
GPR_ASSERT(pem_root_certs.has_value() || pem_key_cert_pairs.has_value());
grpc_core::MutexLock lock(&mu_);
auto& cert_info = certificate_info_map_[cert_name];
if (pem_root_certs.has_value()) {
// Successful credential updates will clear any pre-existing error.
cert_info.SetRootError(GRPC_ERROR_NONE);
for (auto* watcher_ptr : cert_info.root_cert_watchers) {
GPR_ASSERT(watcher_ptr != nullptr);
const auto watcher_it = watchers_.find(watcher_ptr);
GPR_ASSERT(watcher_it != watchers_.end());
GPR_ASSERT(watcher_it->second.root_cert_name.has_value());
absl::optional<PemKeyCertPairList> pem_key_cert_pairs_to_report;
if (pem_key_cert_pairs.has_value() &&
watcher_it->second.identity_cert_name == cert_name) {
pem_key_cert_pairs_to_report = pem_key_cert_pairs;
} else if (watcher_it->second.identity_cert_name.has_value()) {
auto& identity_cert_info =
certificate_info_map_[*watcher_it->second.identity_cert_name];
pem_key_cert_pairs_to_report = identity_cert_info.pem_key_cert_pairs;
}
watcher_ptr->OnCertificatesChanged(
pem_root_certs, std::move(pem_key_cert_pairs_to_report));
}
cert_info.pem_root_certs = std::move(*pem_root_certs);
}
if (pem_key_cert_pairs.has_value()) {
// Successful credential updates will clear any pre-existing error.
cert_info.SetIdentityError(GRPC_ERROR_NONE);
for (const auto watcher_ptr : cert_info.identity_cert_watchers) {
GPR_ASSERT(watcher_ptr != nullptr);
const auto watcher_it = watchers_.find(watcher_ptr);
GPR_ASSERT(watcher_it != watchers_.end());
GPR_ASSERT(watcher_it->second.identity_cert_name.has_value());
absl::optional<absl::string_view> pem_root_certs_to_report;
if (pem_root_certs.has_value() &&
watcher_it->second.root_cert_name == cert_name) {
// In this case, We've already sent the credential updates at the time
// when checking pem_root_certs, so we will skip here.
continue;
} else if (watcher_it->second.root_cert_name.has_value()) {
auto& root_cert_info =
certificate_info_map_[*watcher_it->second.root_cert_name];
pem_root_certs_to_report = root_cert_info.pem_root_certs;
}
watcher_ptr->OnCertificatesChanged(pem_root_certs_to_report,
pem_key_cert_pairs);
}
cert_info.pem_key_cert_pairs = std::move(*pem_key_cert_pairs);
}
}
bool grpc_tls_certificate_distributor::HasRootCerts(
const std::string& root_cert_name) {
grpc_core::MutexLock lock(&mu_);
const auto it = certificate_info_map_.find(root_cert_name);
return it != certificate_info_map_.end() &&
!it->second.pem_root_certs.empty();
};
bool grpc_tls_certificate_distributor::HasKeyCertPairs(
const std::string& identity_cert_name) {
grpc_core::MutexLock lock(&mu_);
const auto it = certificate_info_map_.find(identity_cert_name);
return it != certificate_info_map_.end() &&
!it->second.pem_key_cert_pairs.empty();
};
void grpc_tls_certificate_distributor::SetErrorForCert(
const std::string& cert_name, absl::optional<grpc_error*> root_cert_error,
absl::optional<grpc_error*> identity_cert_error) {
GPR_ASSERT(root_cert_error.has_value() || identity_cert_error.has_value());
grpc_core::MutexLock lock(&mu_);
CertificateInfo& cert_info = certificate_info_map_[cert_name];
if (root_cert_error.has_value()) {
for (auto* watcher_ptr : cert_info.root_cert_watchers) {
GPR_ASSERT(watcher_ptr != nullptr);
const auto watcher_it = watchers_.find(watcher_ptr);
GPR_ASSERT(watcher_it != watchers_.end());
// identity_cert_error_to_report is the error of the identity cert this
// watcher is watching, if there is any.
grpc_error* identity_cert_error_to_report = GRPC_ERROR_NONE;
if (identity_cert_error.has_value() &&
watcher_it->second.identity_cert_name == cert_name) {
identity_cert_error_to_report = *identity_cert_error;
} else if (watcher_it->second.identity_cert_name.has_value()) {
auto& identity_cert_info =
certificate_info_map_[*watcher_it->second.identity_cert_name];
identity_cert_error_to_report = identity_cert_info.identity_cert_error;
}
watcher_ptr->OnError(GRPC_ERROR_REF(*root_cert_error),
GRPC_ERROR_REF(identity_cert_error_to_report));
}
cert_info.SetRootError(*root_cert_error);
}
if (identity_cert_error.has_value()) {
for (auto* watcher_ptr : cert_info.identity_cert_watchers) {
GPR_ASSERT(watcher_ptr != nullptr);
const auto watcher_it = watchers_.find(watcher_ptr);
GPR_ASSERT(watcher_it != watchers_.end());
// root_cert_error_to_report is the error of the root cert this watcher is
// watching, if there is any.
grpc_error* root_cert_error_to_report = GRPC_ERROR_NONE;
if (root_cert_error.has_value() &&
watcher_it->second.root_cert_name == cert_name) {
// In this case, We've already sent the error updates at the time when
// checking root_cert_error, so we will skip here.
continue;
} else if (watcher_it->second.root_cert_name.has_value()) {
auto& root_cert_info =
certificate_info_map_[*watcher_it->second.root_cert_name];
root_cert_error_to_report = root_cert_info.root_cert_error;
}
watcher_ptr->OnError(GRPC_ERROR_REF(root_cert_error_to_report),
GRPC_ERROR_REF(*identity_cert_error));
}
cert_info.SetIdentityError(*identity_cert_error);
}
};
void grpc_tls_certificate_distributor::SetError(grpc_error* error) {
GPR_ASSERT(error != GRPC_ERROR_NONE);
grpc_core::MutexLock lock(&mu_);
for (const auto& watcher : watchers_) {
const auto watcher_ptr = watcher.first;
GPR_ASSERT(watcher_ptr != nullptr);
const auto& watcher_info = watcher.second;
watcher_ptr->OnError(
watcher_info.root_cert_name.has_value() ? GRPC_ERROR_REF(error)
: GRPC_ERROR_NONE,
watcher_info.identity_cert_name.has_value() ? GRPC_ERROR_REF(error)
: GRPC_ERROR_NONE);
}
for (auto& cert_info_entry : certificate_info_map_) {
auto& cert_info = cert_info_entry.second;
cert_info.SetRootError(GRPC_ERROR_REF(error));
cert_info.SetIdentityError(GRPC_ERROR_REF(error));
}
GRPC_ERROR_UNREF(error);
};
void grpc_tls_certificate_distributor::WatchTlsCertificates(
std::unique_ptr<TlsCertificatesWatcherInterface> watcher,
absl::optional<std::string> root_cert_name,
absl::optional<std::string> identity_cert_name) {
bool start_watching_root_cert = false;
bool already_watching_identity_for_root_cert = false;
bool start_watching_identity_cert = false;
bool already_watching_root_for_identity_cert = false;
GPR_ASSERT(root_cert_name.has_value() || identity_cert_name.has_value());
TlsCertificatesWatcherInterface* watcher_ptr = watcher.get();
GPR_ASSERT(watcher_ptr != nullptr);
// Update watchers_ and certificate_info_map_.
{
grpc_core::MutexLock lock(&mu_);
const auto watcher_it = watchers_.find(watcher_ptr);
// The caller needs to cancel the watcher first if it wants to re-register
// the watcher.
GPR_ASSERT(watcher_it == watchers_.end());
watchers_[watcher_ptr] = {std::move(watcher), root_cert_name,
identity_cert_name};
absl::optional<absl::string_view> updated_root_certs;
absl::optional<PemKeyCertPairList> updated_identity_pairs;
grpc_error* root_error = GRPC_ERROR_NONE;
grpc_error* identity_error = GRPC_ERROR_NONE;
if (root_cert_name.has_value()) {
CertificateInfo& cert_info = certificate_info_map_[*root_cert_name];
start_watching_root_cert = cert_info.root_cert_watchers.empty();
already_watching_identity_for_root_cert =
!cert_info.identity_cert_watchers.empty();
cert_info.root_cert_watchers.insert(watcher_ptr);
root_error = GRPC_ERROR_REF(cert_info.root_cert_error);
// Empty credentials will be treated as no updates.
if (!cert_info.pem_root_certs.empty()) {
updated_root_certs = cert_info.pem_root_certs;
}
}
if (identity_cert_name.has_value()) {
CertificateInfo& cert_info = certificate_info_map_[*identity_cert_name];
start_watching_identity_cert = cert_info.identity_cert_watchers.empty();
already_watching_root_for_identity_cert =
!cert_info.root_cert_watchers.empty();
cert_info.identity_cert_watchers.insert(watcher_ptr);
identity_error = GRPC_ERROR_REF(cert_info.identity_cert_error);
// Empty credentials will be treated as no updates.
if (!cert_info.pem_key_cert_pairs.empty()) {
updated_identity_pairs = cert_info.pem_key_cert_pairs;
}
}
// Notify this watcher if the certs it is watching already had some
// contents. Note that an *_cert_error in cert_info only indicates error
// occurred while trying to fetch the latest cert, but the updated_*_certs
// should always be valid. So we will send the updates regardless of
// *_cert_error.
if (updated_root_certs.has_value() || updated_identity_pairs.has_value()) {
watcher_ptr->OnCertificatesChanged(updated_root_certs,
std::move(updated_identity_pairs));
}
// Notify this watcher if the certs it is watching already had some errors.
if (root_error != GRPC_ERROR_NONE || identity_error != GRPC_ERROR_NONE) {
watcher_ptr->OnError(GRPC_ERROR_REF(root_error),
GRPC_ERROR_REF(identity_error));
}
GRPC_ERROR_UNREF(root_error);
GRPC_ERROR_UNREF(identity_error);
}
// Invoke watch status callback if needed.
{
grpc_core::MutexLock lock(&callback_mu_);
if (watch_status_callback_ != nullptr) {
if (root_cert_name == identity_cert_name &&
(start_watching_root_cert || start_watching_identity_cert)) {
watch_status_callback_(*root_cert_name, start_watching_root_cert,
start_watching_identity_cert);
} else {
if (start_watching_root_cert) {
watch_status_callback_(*root_cert_name, true,
already_watching_identity_for_root_cert);
}
if (start_watching_identity_cert) {
watch_status_callback_(*identity_cert_name,
already_watching_root_for_identity_cert, true);
}
}
}
}
};
void grpc_tls_certificate_distributor::CancelTlsCertificatesWatch(
TlsCertificatesWatcherInterface* watcher) {
absl::optional<std::string> root_cert_name;
absl::optional<std::string> identity_cert_name;
bool stop_watching_root_cert = false;
bool already_watching_identity_for_root_cert = false;
bool stop_watching_identity_cert = false;
bool already_watching_root_for_identity_cert = false;
// Update watchers_ and certificate_info_map_.
{
grpc_core::MutexLock lock(&mu_);
auto it = watchers_.find(watcher);
if (it == watchers_.end()) return;
WatcherInfo& watcher_info = it->second;
root_cert_name = std::move(watcher_info.root_cert_name);
identity_cert_name = std::move(watcher_info.identity_cert_name);
watchers_.erase(it);
if (root_cert_name.has_value()) {
auto it = certificate_info_map_.find(*root_cert_name);
GPR_ASSERT(it != certificate_info_map_.end());
CertificateInfo& cert_info = it->second;
cert_info.root_cert_watchers.erase(watcher);
stop_watching_root_cert = cert_info.root_cert_watchers.empty();
already_watching_identity_for_root_cert =
!cert_info.identity_cert_watchers.empty();
if (stop_watching_root_cert && !already_watching_identity_for_root_cert) {
certificate_info_map_.erase(it);
}
}
if (identity_cert_name.has_value()) {
auto it = certificate_info_map_.find(*identity_cert_name);
GPR_ASSERT(it != certificate_info_map_.end());
CertificateInfo& cert_info = it->second;
cert_info.identity_cert_watchers.erase(watcher);
stop_watching_identity_cert = cert_info.identity_cert_watchers.empty();
already_watching_root_for_identity_cert =
!cert_info.root_cert_watchers.empty();
if (stop_watching_identity_cert &&
!already_watching_root_for_identity_cert) {
certificate_info_map_.erase(it);
}
}
}
// Invoke watch status callback if needed.
{
grpc_core::MutexLock lock(&callback_mu_);
if (watch_status_callback_ != nullptr) {
if (root_cert_name == identity_cert_name &&
(stop_watching_root_cert || stop_watching_identity_cert)) {
watch_status_callback_(*root_cert_name, !stop_watching_root_cert,
!stop_watching_identity_cert);
} else {
if (stop_watching_root_cert) {
watch_status_callback_(*root_cert_name, false,
already_watching_identity_for_root_cert);
}
if (stop_watching_identity_cert) {
watch_status_callback_(*identity_cert_name,
already_watching_root_for_identity_cert,
false);
}
}
}
}
};

@ -0,0 +1,214 @@
//
// Copyright 2020 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_DISTRIBUTOR_H
#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_DISTRIBUTOR_H
#include <grpc/support/port_platform.h>
#include <grpc/grpc_security.h>
#include "absl/container/inlined_vector.h"
#include "absl/types/optional.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/security/security_connector/ssl_utils.h"
// TLS certificate distributor.
struct grpc_tls_certificate_distributor
: public grpc_core::RefCounted<grpc_tls_certificate_distributor> {
public:
typedef absl::InlinedVector<grpc_core::PemKeyCertPair, 1> PemKeyCertPairList;
// Interface for watching TLS certificates update.
class TlsCertificatesWatcherInterface {
public:
virtual ~TlsCertificatesWatcherInterface() = default;
// Handles the delivery of the updated root and identity certificates.
// An absl::nullopt value indicates no corresponding contents for
// root_certs or key_cert_pairs. Note that we will send updates of the
// latest contents for both root and identity certificates, even when only
// one side of it got updated.
//
// @param root_certs the contents of the reloaded root certs.
// @param key_cert_pairs the contents of the reloaded identity key-cert
// pairs.
virtual void OnCertificatesChanged(
absl::optional<absl::string_view> root_certs,
absl::optional<PemKeyCertPairList> key_cert_pairs) = 0;
// Handles an error that occurs while attempting to fetch certificate data.
// Note that if a watcher sees an error, it simply means the Provider is
// having problems renewing new data. If the watcher has previously received
// several OnCertificatesChanged, all the data received from that function
// is valid.
// In that case, watcher might simply log the error. If the watcher hasn't
// received any OnCertificatesChanged before the error occurs, no valid
// data is available yet, and the watcher should either fail or "waiting"
// for the valid data in a non-blocking way.
//
// @param root_cert_error the error occurred while reloading root
// certificates.
// @param identity_cert_error the error occurred while reloading identity
// certificates.
virtual void OnError(grpc_error* root_cert_error,
grpc_error* identity_cert_error) = 0;
};
// Sets the key materials based on their certificate name. Note that we are
// not doing any copies for pem_root_certs and pem_key_cert_pairs. For
// pem_root_certs, the original string contents need to outlive the
// distributor; for pem_key_cert_pairs, internally it is taking two
// unique_ptr(s) to the credential string, so the ownership is actually
// transferred.
//
// @param cert_name The name of the certificates being updated.
// @param pem_root_certs The content of root certificates.
// @param pem_key_cert_pairs The content of identity key-cert pairs.
void SetKeyMaterials(const std::string& cert_name,
absl::optional<std::string> pem_root_certs,
absl::optional<PemKeyCertPairList> pem_key_cert_pairs);
bool HasRootCerts(const std::string& root_cert_name);
bool HasKeyCertPairs(const std::string& identity_cert_name);
// Propagates the error that the caller (e.g. Producer) encounters to all the
// watchers watching a particular certificate name.
//
// @param cert_name The watching cert name of the watchers that the caller
// wants to notify when encountering error.
// @param root_cert_error The error that the caller encounters when reloading
// root certs.
// @param identity_cert_error The error that the caller encounters when
// reloading identity certs.
void SetErrorForCert(const std::string& cert_name,
absl::optional<grpc_error*> root_cert_error,
absl::optional<grpc_error*> identity_cert_error);
// Propagates the error that the caller (e.g. Producer) encounters to all
// watchers.
//
// @param error The error that the caller encounters.
void SetError(grpc_error* error);
// Sets the TLS certificate watch status callback function. The
// grpc_tls_certificate_distributor will invoke this callback when a new
// certificate name is watched by a newly registered watcher, or when a
// certificate name is no longer watched by any watchers.
// Note that when the callback shows a cert is no longer being watched, the
// distributor will delete the corresponding certificate data from its cache,
// and clear the corresponding error, if there is any. This means that if the
// callback subsequently says the same cert is now being watched again, the
// provider must re-provide the credentials or re-invoke the errors to the
// distributor, to indicate a successful or failed reloading.
// @param callback The callback function being set by the caller, e.g the
// Producer. Note that this callback will be invoked for each certificate
// name.
//
// For the parameters in the callback function:
// string_value The name of the certificates being watched.
// bool_value_1 If the root certificates with the specific name are being
// watched. bool_value_2 If the identity certificates with the specific name
// are being watched.
void SetWatchStatusCallback(
std::function<void(std::string, bool, bool)> callback) {
grpc_core::MutexLock lock(&mu_);
watch_status_callback_ = callback;
};
// Registers a watcher. The caller may keep a raw pointer to the watcher,
// which may be used only for cancellation. (Because the caller does not own
// the watcher, the pointer must not be used for any other purpose.) At least
// one of root_cert_name and identity_cert_name must be specified.
//
// @param watcher The watcher being registered.
// @param root_cert_name The name of the root certificates that will be
// watched. If set to absl::nullopt, the root certificates won't be watched.
// @param identity_cert_name The name of the identity certificates that will
// be watched. If set to absl::nullopt, the identity certificates won't be
// watched.
void WatchTlsCertificates(
std::unique_ptr<TlsCertificatesWatcherInterface> watcher,
absl::optional<std::string> root_cert_name,
absl::optional<std::string> identity_cert_name);
// Cancels a watcher.
//
// @param watcher The watcher being cancelled.
void CancelTlsCertificatesWatch(TlsCertificatesWatcherInterface* watcher);
private:
// Contains the information about each watcher.
struct WatcherInfo {
std::unique_ptr<TlsCertificatesWatcherInterface> watcher;
absl::optional<std::string> root_cert_name;
absl::optional<std::string> identity_cert_name;
};
// CertificateInfo contains the credential contents and some additional
// watcher information.
// Note that having errors doesn't indicate the corresponding credentials are
// invalid. For example, if root_cert_error != nullptr but pem_root_certs has
// value, it simply means an error occurs while trying to fetch the latest
// root certs, while pem_root_certs still contains the valid old data.
struct CertificateInfo {
// The contents of the root certificates.
std::string pem_root_certs;
// The contents of the identity key-certificate pairs.
PemKeyCertPairList pem_key_cert_pairs;
// The root cert reloading error propagated by the caller.
grpc_error* root_cert_error = GRPC_ERROR_NONE;
// The identity cert reloading error propagated by the caller.
grpc_error* identity_cert_error = GRPC_ERROR_NONE;
// The set of watchers watching root certificates.
// This is mainly used for quickly looking up the affected watchers while
// performing a credential reloading.
std::set<TlsCertificatesWatcherInterface*> root_cert_watchers;
// The set of watchers watching identity certificates. This is mainly used
// for quickly looking up the affected watchers while performing a
// credential reloading.
std::set<TlsCertificatesWatcherInterface*> identity_cert_watchers;
~CertificateInfo() {
GRPC_ERROR_UNREF(root_cert_error);
GRPC_ERROR_UNREF(identity_cert_error);
}
void SetRootError(grpc_error* error) {
GRPC_ERROR_UNREF(root_cert_error);
root_cert_error = error;
}
void SetIdentityError(grpc_error* error) {
GRPC_ERROR_UNREF(identity_cert_error);
identity_cert_error = error;
}
};
grpc_core::Mutex mu_;
// We need a dedicated mutex for watch_status_callback_ for allowing
// callers(e.g. Producer) to directly set key materials in the callback
// functions.
grpc_core::Mutex callback_mu_;
// Stores information about each watcher.
std::map<TlsCertificatesWatcherInterface*, WatcherInfo> watchers_;
// The callback to notify the caller, e.g. the Producer, that the watch status
// is changed.
std::function<void(std::string, bool, bool)> watch_status_callback_;
// Stores the names of each certificate, and their corresponding credential
// contents as well as some additional watcher information.
std::map<std::string, CertificateInfo> certificate_info_map_;
};
#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_DISTRIBUTOR_H

@ -174,6 +174,11 @@ class PemKeyCertPair {
return *this; return *this;
} }
bool operator==(const PemKeyCertPair& other) const {
return std::strcmp(this->private_key(), other.private_key()) == 0 &&
std::strcmp(this->cert_chain(), other.cert_chain()) == 0;
}
char* private_key() const { return private_key_.get(); } char* private_key() const { return private_key_.get(); }
char* cert_chain() const { return cert_chain_.get(); } char* cert_chain() const { return cert_chain_.get(); }

@ -161,8 +161,13 @@ inline void grpc_channel_internal_unref(grpc_channel* channel) {
grpc_channel_internal_unref(channel) grpc_channel_internal_unref(channel)
#endif #endif
/** Return the channel's compression options. */ // Return the channel's compression options.
grpc_compression_options grpc_channel_compression_options( grpc_compression_options grpc_channel_compression_options(
const grpc_channel* channel); const grpc_channel* channel);
// Ping the channels peer (load balanced channels will select one sub-channel to
// ping); if the channel is not connected, posts a failed.
void grpc_channel_ping(grpc_channel* channel, grpc_completion_queue* cq,
void* tag, void* reserved);
#endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_H */ #endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_H */

@ -18,8 +18,6 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/lib/surface/init.h"
#include <limits.h> #include <limits.h>
#include <memory.h> #include <memory.h>
@ -28,7 +26,6 @@
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/channel/channelz_registry.h"
#include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/connected_channel.h"
@ -40,7 +37,6 @@
#include "src/core/lib/http/parser.h" #include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/call_combiner.h"
#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/resource_quota.h" #include "src/core/lib/iomgr/resource_quota.h"
@ -51,6 +47,7 @@
#include "src/core/lib/surface/call.h" #include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/channel_init.h" #include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/surface/completion_queue.h" #include "src/core/lib/surface/completion_queue.h"
#include "src/core/lib/surface/init.h"
#include "src/core/lib/surface/lame_client.h" #include "src/core/lib/surface/lame_client.h"
#include "src/core/lib/surface/server.h" #include "src/core/lib/surface/server.h"
#include "src/core/lib/transport/bdp_estimator.h" #include "src/core/lib/transport/bdp_estimator.h"
@ -214,29 +211,15 @@ void grpc_shutdown_internal(void* /*ignored*/) {
void grpc_shutdown(void) { void grpc_shutdown(void) {
GRPC_API_TRACE("grpc_shutdown(void)", 0, ()); GRPC_API_TRACE("grpc_shutdown(void)", 0, ());
grpc_core::MutexLock lock(&g_init_mu); grpc_core::MutexLock lock(&g_init_mu);
if (--g_initializations == 0) { if (--g_initializations == 0) {
grpc_core::ApplicationCallbackExecCtx* acec = g_initializations++;
grpc_core::ApplicationCallbackExecCtx::Get(); g_shutting_down = true;
if (!grpc_iomgr_is_any_background_poller_thread() && // spawn a detached thread to do the actual clean up in case we are
(acec == nullptr || // currently in an executor thread.
(acec->Flags() & GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD) == grpc_core::Thread cleanup_thread(
0)) { "grpc_shutdown", grpc_shutdown_internal, nullptr, nullptr,
// just run clean-up when this is called on non-executor thread. grpc_core::Thread::Options().set_joinable(false).set_tracked(false));
gpr_log(GPR_DEBUG, "grpc_shutdown starts clean-up now"); cleanup_thread.Start();
g_shutting_down = true;
grpc_shutdown_internal_locked();
} else {
// spawn a detached thread to do the actual clean up in case we are
// currently in an executor thread.
gpr_log(GPR_DEBUG, "grpc_shutdown spawns clean-up thread");
g_initializations++;
g_shutting_down = true;
grpc_core::Thread cleanup_thread(
"grpc_shutdown", grpc_shutdown_internal, nullptr, nullptr,
grpc_core::Thread::Options().set_joinable(false).set_tracked(false));
cleanup_thread.Start();
}
} }
} }

@ -62,6 +62,8 @@ void grpc_workaround_cronet_compression_filter_init(void);
void grpc_workaround_cronet_compression_filter_shutdown(void); void grpc_workaround_cronet_compression_filter_shutdown(void);
#ifndef GRPC_NO_XDS #ifndef GRPC_NO_XDS
void grpc_certificate_provider_registry_init(void);
void grpc_certificate_provider_registry_shutdown(void);
void grpc_lb_policy_cds_init(void); void grpc_lb_policy_cds_init(void);
void grpc_lb_policy_cds_shutdown(void); void grpc_lb_policy_cds_shutdown(void);
void grpc_lb_policy_eds_init(void); void grpc_lb_policy_eds_init(void);
@ -116,6 +118,8 @@ void grpc_register_built_in_plugins(void) {
grpc_register_plugin(grpc_workaround_cronet_compression_filter_init, grpc_register_plugin(grpc_workaround_cronet_compression_filter_init,
grpc_workaround_cronet_compression_filter_shutdown); grpc_workaround_cronet_compression_filter_shutdown);
#ifndef GRPC_NO_XDS #ifndef GRPC_NO_XDS
grpc_register_plugin(grpc_certificate_provider_registry_init,
grpc_certificate_provider_registry_shutdown);
grpc_register_plugin(grpc_lb_policy_cds_init, grpc_register_plugin(grpc_lb_policy_cds_init,
grpc_lb_policy_cds_shutdown); grpc_lb_policy_cds_shutdown);
grpc_register_plugin(grpc_lb_policy_eds_init, grpc_register_plugin(grpc_lb_policy_eds_init,

@ -15,6 +15,7 @@ pyx_library(
"**/*.pxi", "**/*.pxi",
"cygrpc.pxd", "cygrpc.pxd",
"cygrpc.pyx", "cygrpc.pyx",
"**/__init__.py",
]), ]),
data = [":copy_roots_pem"], data = [":copy_roots_pem"],
deps = [ deps = [

@ -199,6 +199,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.c', 'src/core/ext/upb-generated/udpa/annotations/versioning.upb.c',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c', 'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
'src/core/ext/upb-generated/validate/validate.upb.c', 'src/core/ext/upb-generated/validate/validate.upb.c',
'src/core/ext/xds/certificate_provider_registry.cc',
'src/core/ext/xds/xds_api.cc', 'src/core/ext/xds/xds_api.cc',
'src/core/ext/xds/xds_bootstrap.cc', 'src/core/ext/xds/xds_bootstrap.cc',
'src/core/ext/xds/xds_client.cc', 'src/core/ext/xds/xds_client.cc',
@ -393,6 +394,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc', 'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc',
'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/plugin/plugin_credentials.cc',
'src/core/lib/security/credentials/ssl/ssl_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc',
'src/core/lib/security/credentials/tls/tls_credentials.cc', 'src/core/lib/security/credentials/tls/tls_credentials.cc',
'src/core/lib/security/security_connector/alts/alts_security_connector.cc', 'src/core/lib/security/security_connector/alts/alts_security_connector.cc',

@ -58,7 +58,6 @@ grpc_channel_num_external_connectivity_watchers_type grpc_channel_num_external_c
grpc_channel_watch_connectivity_state_type grpc_channel_watch_connectivity_state_import; grpc_channel_watch_connectivity_state_type grpc_channel_watch_connectivity_state_import;
grpc_channel_support_connectivity_watcher_type grpc_channel_support_connectivity_watcher_import; grpc_channel_support_connectivity_watcher_type grpc_channel_support_connectivity_watcher_import;
grpc_channel_create_call_type grpc_channel_create_call_import; grpc_channel_create_call_type grpc_channel_create_call_import;
grpc_channel_ping_type grpc_channel_ping_import;
grpc_channel_register_call_type grpc_channel_register_call_import; grpc_channel_register_call_type grpc_channel_register_call_import;
grpc_channel_create_registered_call_type grpc_channel_create_registered_call_import; grpc_channel_create_registered_call_type grpc_channel_create_registered_call_import;
grpc_call_arena_alloc_type grpc_call_arena_alloc_import; grpc_call_arena_alloc_type grpc_call_arena_alloc_import;
@ -332,7 +331,6 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_channel_watch_connectivity_state_import = (grpc_channel_watch_connectivity_state_type) GetProcAddress(library, "grpc_channel_watch_connectivity_state"); grpc_channel_watch_connectivity_state_import = (grpc_channel_watch_connectivity_state_type) GetProcAddress(library, "grpc_channel_watch_connectivity_state");
grpc_channel_support_connectivity_watcher_import = (grpc_channel_support_connectivity_watcher_type) GetProcAddress(library, "grpc_channel_support_connectivity_watcher"); grpc_channel_support_connectivity_watcher_import = (grpc_channel_support_connectivity_watcher_type) GetProcAddress(library, "grpc_channel_support_connectivity_watcher");
grpc_channel_create_call_import = (grpc_channel_create_call_type) GetProcAddress(library, "grpc_channel_create_call"); grpc_channel_create_call_import = (grpc_channel_create_call_type) GetProcAddress(library, "grpc_channel_create_call");
grpc_channel_ping_import = (grpc_channel_ping_type) GetProcAddress(library, "grpc_channel_ping");
grpc_channel_register_call_import = (grpc_channel_register_call_type) GetProcAddress(library, "grpc_channel_register_call"); grpc_channel_register_call_import = (grpc_channel_register_call_type) GetProcAddress(library, "grpc_channel_register_call");
grpc_channel_create_registered_call_import = (grpc_channel_create_registered_call_type) GetProcAddress(library, "grpc_channel_create_registered_call"); grpc_channel_create_registered_call_import = (grpc_channel_create_registered_call_type) GetProcAddress(library, "grpc_channel_create_registered_call");
grpc_call_arena_alloc_import = (grpc_call_arena_alloc_type) GetProcAddress(library, "grpc_call_arena_alloc"); grpc_call_arena_alloc_import = (grpc_call_arena_alloc_type) GetProcAddress(library, "grpc_call_arena_alloc");

@ -149,9 +149,6 @@ extern grpc_channel_support_connectivity_watcher_type grpc_channel_support_conne
typedef grpc_call*(*grpc_channel_create_call_type)(grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask, grpc_completion_queue* completion_queue, grpc_slice method, const grpc_slice* host, gpr_timespec deadline, void* reserved); typedef grpc_call*(*grpc_channel_create_call_type)(grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask, grpc_completion_queue* completion_queue, grpc_slice method, const grpc_slice* host, gpr_timespec deadline, void* reserved);
extern grpc_channel_create_call_type grpc_channel_create_call_import; extern grpc_channel_create_call_type grpc_channel_create_call_import;
#define grpc_channel_create_call grpc_channel_create_call_import #define grpc_channel_create_call grpc_channel_create_call_import
typedef void(*grpc_channel_ping_type)(grpc_channel* channel, grpc_completion_queue* cq, void* tag, void* reserved);
extern grpc_channel_ping_type grpc_channel_ping_import;
#define grpc_channel_ping grpc_channel_ping_import
typedef void*(*grpc_channel_register_call_type)(grpc_channel* channel, const char* method, const char* host, void* reserved); typedef void*(*grpc_channel_register_call_type)(grpc_channel* channel, const char* method, const char* host, void* reserved);
extern grpc_channel_register_call_type grpc_channel_register_call_import; extern grpc_channel_register_call_type grpc_channel_register_call_import;
#define grpc_channel_register_call grpc_channel_register_call_import #define grpc_channel_register_call grpc_channel_register_call_import

@ -706,6 +706,7 @@
) )
install(FILES install(FILES
<%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/cmake/modules/Findc-ares.cmake <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/cmake/modules/Findc-ares.cmake
<%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/cmake/modules/Findre2.cmake
DESTINATION <%text>${gRPC_INSTALL_CMAKEDIR}</%text>/modules DESTINATION <%text>${gRPC_INSTALL_CMAKEDIR}</%text>/modules
) )

@ -18,6 +18,18 @@ grpc_package(name = "test/core/client_channel")
licenses(["notice"]) licenses(["notice"])
grpc_cc_test(
name = "certificate_provider_registry_test",
srcs = ["certificate_provider_registry_test.cc"],
external_deps = ["gtest"],
language = "C++",
deps = [
"//:gpr",
"//:grpc",
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test( grpc_cc_test(
name = "retry_throttle_test", name = "retry_throttle_test",
srcs = ["retry_throttle_test.cc"], srcs = ["retry_throttle_test.cc"],

@ -0,0 +1,90 @@
//
//
// Copyright 2020 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#include <grpc/support/port_platform.h>
#include <gmock/gmock.h>
#include "src/core/ext/xds/certificate_provider_registry.h"
#include "test/core/util/test_config.h"
namespace grpc_core {
namespace testing {
namespace {
class FakeCertificateProviderFactory1 : public CertificateProviderFactory {
public:
const char* name() const override { return "fake1"; }
std::unique_ptr<Config> CreateCertificateProviderConfig(
const Json& config_json, grpc_error** error) override {
return nullptr;
}
RefCountedPtr<grpc_tls_certificate_provider> CreateCertificateProvider(
std::unique_ptr<Config> config) override {
return nullptr;
}
};
class FakeCertificateProviderFactory2 : public CertificateProviderFactory {
public:
const char* name() const override { return "fake2"; }
std::unique_ptr<Config> CreateCertificateProviderConfig(
const Json& config_json, grpc_error** error) override {
return nullptr;
}
RefCountedPtr<grpc_tls_certificate_provider> CreateCertificateProvider(
std::unique_ptr<Config> config) override {
return nullptr;
}
};
TEST(CertificateProviderRegistryTest, Basic) {
CertificateProviderRegistry::InitRegistry();
auto* fake_factory_1 = new FakeCertificateProviderFactory1;
auto* fake_factory_2 = new FakeCertificateProviderFactory2;
CertificateProviderRegistry::RegisterCertificateProviderFactory(
std::unique_ptr<CertificateProviderFactory>(fake_factory_1));
CertificateProviderRegistry::RegisterCertificateProviderFactory(
std::unique_ptr<CertificateProviderFactory>(fake_factory_2));
EXPECT_EQ(
CertificateProviderRegistry::LookupCertificateProviderFactory("fake1"),
fake_factory_1);
EXPECT_EQ(
CertificateProviderRegistry::LookupCertificateProviderFactory("fake2"),
fake_factory_2);
EXPECT_EQ(
CertificateProviderRegistry::LookupCertificateProviderFactory("fake3"),
nullptr);
CertificateProviderRegistry::ShutdownRegistry();
}
} // namespace
} // namespace testing
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc::testing::TestEnvironment env(argc, argv);
auto result = RUN_ALL_TESTS();
return result;
}

@ -26,6 +26,7 @@
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gpr/useful.h"
#include "src/core/lib/surface/channel.h"
#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/cq_verifier.h"
#define MAX_PING_STRIKES 2 #define MAX_PING_STRIKES 2

@ -23,6 +23,7 @@
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gpr/useful.h"
#include "src/core/lib/surface/channel.h"
#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/cq_verifier.h"
#define PING_NUM 5 #define PING_NUM 5

@ -377,8 +377,7 @@ grpc_cc_test(
language = "C++", language = "C++",
tags = [ tags = [
# TODO(apolcyn): This test is failing on Windows at entry, enable once passing. # TODO(apolcyn): This test is failing on Windows at entry, enable once passing.
# See e.g. https://source.cloud.google.com/results/invocations/03e2c2bc-1742-48b4-a33d-b4cdaee5c8f9/targets # See e.g. https://source.cloud.google.com/results/invocations/6716596a-c9e1-4780-85ed-890d8758d582/targets
# E0717 23:43:56.391000000 5488 src/core/lib/surface/server.cc:1630] assertion failed: server->listeners_destroyed == server->listeners.size()
"no_windows", "no_windows",
], ],
deps = [ deps = [

@ -224,8 +224,14 @@ class TestServer {
} }
~TestServer() { ~TestServer() {
grpc_server_shutdown_and_notify(server_, cq_, nullptr);
thread_.join(); thread_.join();
void* shutdown_and_notify_tag = this;
grpc_server_shutdown_and_notify(server_, cq_, shutdown_and_notify_tag);
grpc_event event = grpc_completion_queue_next(
cq_, gpr_inf_future(GPR_CLOCK_REALTIME), nullptr);
GPR_ASSERT(event.type == GRPC_OP_COMPLETE);
GPR_ASSERT(event.tag == shutdown_and_notify_tag);
GPR_ASSERT(event.success);
grpc_server_destroy(server_); grpc_server_destroy(server_);
grpc_completion_queue_shutdown(cq_); grpc_completion_queue_shutdown(cq_);
while (grpc_completion_queue_next(cq_, gpr_inf_future(GPR_CLOCK_REALTIME), while (grpc_completion_queue_next(cq_, gpr_inf_future(GPR_CLOCK_REALTIME),
@ -243,7 +249,7 @@ class TestServer {
grpc_call_details_init(&call_details); grpc_call_details_init(&call_details);
grpc_metadata_array request_metadata_recv; grpc_metadata_array request_metadata_recv;
grpc_metadata_array_init(&request_metadata_recv); grpc_metadata_array_init(&request_metadata_recv);
void* tag = this; void* tag = &call_details;
grpc_call* call; grpc_call* call;
grpc_call_error error = grpc_server_request_call( grpc_call_error error = grpc_server_request_call(
server_, &call, &call_details, &request_metadata_recv, cq_, cq_, tag); server_, &call, &call_details, &request_metadata_recv, cq_, cq_, tag);

@ -313,3 +313,16 @@ grpc_cc_test(
"//test/core/util:grpc_test_util", "//test/core/util:grpc_test_util",
], ],
) )
grpc_cc_test(
name = "grpc_tls_certificate_distributor_test",
srcs = ["grpc_tls_certificate_distributor_test.cc"],
external_deps = ["gtest"],
language = "C++",
deps = [
"//:gpr",
"//:grpc",
"//:grpc_secure",
"//test/core/util:grpc_test_util",
],
)

@ -0,0 +1,968 @@
//
// Copyright 2020 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h"
#include <gmock/gmock.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <gtest/gtest.h>
#include <deque>
#include <list>
#include <string>
#include <thread>
#include "src/core/lib/slice/slice_internal.h"
#include "test/core/util/test_config.h"
namespace testing {
constexpr const char* kCertName1 = "cert_1_name";
constexpr const char* kCertName2 = "cert_2_name";
constexpr const char* kRootCert1Name = "root_cert_1_name";
constexpr const char* kRootCert1Contents = "root_cert_1_contents";
constexpr const char* kRootCert2Name = "root_cert_2_name";
constexpr const char* kRootCert2Contents = "root_cert_2_contents";
constexpr const char* kIdentityCert1Name = "identity_cert_1_name";
constexpr const char* kIdentityCert1PrivateKey = "identity_private_key_1";
constexpr const char* kIdentityCert1Contents = "identity_cert_1_contents";
constexpr const char* kIdentityCert2Name = "identity_cert_2_name";
constexpr const char* kIdentityCert2PrivateKey = "identity_private_key_2";
constexpr const char* kIdentityCert2Contents = "identity_cert_2_contents";
constexpr const char* kErrorMessage = "error_message";
constexpr const char* kRootErrorMessage = "root_error_message";
constexpr const char* kIdentityErrorMessage = "identity_error_message";
class GrpcTlsCertificateDistributorTest : public ::testing::Test {
protected:
// Forward declaration.
class TlsCertificatesTestWatcher;
static grpc_tls_certificate_distributor::PemKeyCertPairList MakeCertKeyPairs(
const char* private_key, const char* certs) {
if (strcmp(private_key, "") == 0 && strcmp(certs, "") == 0) {
return {};
}
grpc_ssl_pem_key_cert_pair* ssl_pair =
static_cast<grpc_ssl_pem_key_cert_pair*>(
gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair)));
ssl_pair->private_key = gpr_strdup(private_key);
ssl_pair->cert_chain = gpr_strdup(certs);
grpc_tls_certificate_distributor::PemKeyCertPairList pem_key_cert_pairs;
pem_key_cert_pairs.emplace_back(ssl_pair);
return pem_key_cert_pairs;
}
// CredentialInfo contains the parameters when calling OnCertificatesChanged
// of a watcher. When OnCertificatesChanged is invoked, we will push a
// CredentialInfo to the cert_update_queue of state_, and check in each test
// if the status updates are correct.
struct CredentialInfo {
std::string root_certs;
grpc_tls_certificate_distributor::PemKeyCertPairList key_cert_pairs;
CredentialInfo(
std::string root,
grpc_tls_certificate_distributor::PemKeyCertPairList key_cert)
: root_certs(std::move(root)), key_cert_pairs(std::move(key_cert)) {}
bool operator==(const CredentialInfo& other) const {
return root_certs == other.root_certs &&
key_cert_pairs == other.key_cert_pairs;
}
};
// ErrorInfo contains the parameters when calling OnError of a watcher. When
// OnError is invoked, we will push a ErrorInfo to the error_queue of state_,
// and check in each test if the status updates are correct.
struct ErrorInfo {
std::string root_cert_str;
std::string identity_cert_str;
ErrorInfo(std::string root, std::string identity)
: root_cert_str(std::move(root)),
identity_cert_str(std::move(identity)) {}
bool operator==(const ErrorInfo& other) const {
return root_cert_str == other.root_cert_str &&
identity_cert_str == other.identity_cert_str;
}
};
struct WatcherState {
TlsCertificatesTestWatcher* watcher = nullptr;
std::deque<CredentialInfo> cert_update_queue;
std::deque<ErrorInfo> error_queue;
std::deque<CredentialInfo> GetCredentialQueue() {
// We move the data member value so the data member will be re-initiated
// with size 0, and ready for the next check.
return std::move(cert_update_queue);
}
std::deque<ErrorInfo> GetErrorQueue() {
// We move the data member value so the data member will be re-initiated
// with size 0, and ready for the next check.
return std::move(error_queue);
}
};
class TlsCertificatesTestWatcher : public grpc_tls_certificate_distributor::
TlsCertificatesWatcherInterface {
public:
// ctor sets state->watcher to this.
explicit TlsCertificatesTestWatcher(WatcherState* state) : state_(state) {
state_->watcher = this;
}
// dtor sets state->watcher to nullptr.
~TlsCertificatesTestWatcher() { state_->watcher = nullptr; }
void OnCertificatesChanged(
absl::optional<absl::string_view> root_certs,
absl::optional<grpc_tls_certificate_distributor::PemKeyCertPairList>
key_cert_pairs) override {
std::string updated_root;
if (root_certs.has_value()) {
updated_root = std::string(*root_certs);
}
grpc_tls_certificate_distributor::PemKeyCertPairList updated_identity;
if (key_cert_pairs.has_value()) {
updated_identity = std::move(*key_cert_pairs);
}
state_->cert_update_queue.emplace_back(std::move(updated_root),
std::move(updated_identity));
}
void OnError(grpc_error* root_cert_error,
grpc_error* identity_cert_error) override {
GPR_ASSERT(root_cert_error != GRPC_ERROR_NONE ||
identity_cert_error != GRPC_ERROR_NONE);
std::string root_error_str;
std::string identity_error_str;
if (root_cert_error != GRPC_ERROR_NONE) {
grpc_slice root_error_slice;
GPR_ASSERT(grpc_error_get_str(
root_cert_error, GRPC_ERROR_STR_DESCRIPTION, &root_error_slice));
root_error_str =
std::string(grpc_core::StringViewFromSlice(root_error_slice));
}
if (identity_cert_error != GRPC_ERROR_NONE) {
grpc_slice identity_error_slice;
GPR_ASSERT(grpc_error_get_str(identity_cert_error,
GRPC_ERROR_STR_DESCRIPTION,
&identity_error_slice));
identity_error_str =
std::string(grpc_core::StringViewFromSlice(identity_error_slice));
}
state_->error_queue.emplace_back(std::move(root_error_str),
std::move(identity_error_str));
GRPC_ERROR_UNREF(root_cert_error);
GRPC_ERROR_UNREF(identity_cert_error);
}
private:
WatcherState* state_;
};
// CallbackStatus contains the parameters when calling watch_status_callback_
// of the distributor. When a particular callback is invoked, we will push a
// CallbackStatus to a callback_queue_, and check in each test if the status
// updates are correct.
struct CallbackStatus {
std::string cert_name;
bool root_being_watched;
bool identity_being_watched;
CallbackStatus(std::string name, bool root_watched, bool identity_watched)
: cert_name(std::move(name)),
root_being_watched(root_watched),
identity_being_watched(identity_watched) {}
bool operator==(const CallbackStatus& other) const {
return cert_name == other.cert_name &&
root_being_watched == other.root_being_watched &&
identity_being_watched == other.identity_being_watched;
}
};
void SetUp() override {
distributor_.SetWatchStatusCallback([this](std::string cert_name,
bool root_being_watched,
bool identity_being_watched) {
callback_queue_.emplace_back(std::move(cert_name), root_being_watched,
identity_being_watched);
});
}
WatcherState* MakeWatcher(absl::optional<std::string> root_cert_name,
absl::optional<std::string> identity_cert_name) {
grpc_core::MutexLock lock(&mu_);
watchers_.emplace_back();
// TlsCertificatesTestWatcher ctor takes a pointer to the WatcherState.
// It sets WatcherState::watcher to point to itself.
// The TlsCertificatesTestWatcher dtor will set WatcherState::watcher back
// to nullptr to indicate that it's been destroyed.
auto watcher =
absl::make_unique<TlsCertificatesTestWatcher>(&watchers_.back());
distributor_.WatchTlsCertificates(std::move(watcher),
std::move(root_cert_name),
std::move(identity_cert_name));
return &watchers_.back();
}
void CancelWatch(WatcherState* state) {
grpc_core::MutexLock lock(&mu_);
distributor_.CancelTlsCertificatesWatch(state->watcher);
EXPECT_EQ(state->watcher, nullptr);
}
std::deque<CallbackStatus> GetCallbackQueue() {
// We move the data member value so the data member will be re-initiated
// with size 0, and ready for the next check.
return std::move(callback_queue_);
}
grpc_tls_certificate_distributor distributor_;
// Use a std::list<> here to avoid the address invalidation caused by internal
// reallocation of std::vector<>.
std::list<WatcherState> watchers_;
std::deque<CallbackStatus> callback_queue_;
// This is to make watchers_ and callback_queue_ thread-safe.
grpc_core::Mutex mu_;
};
TEST_F(GrpcTlsCertificateDistributorTest, BasicCredentialBehaviors) {
EXPECT_FALSE(distributor_.HasRootCerts(kRootCert1Name));
EXPECT_FALSE(distributor_.HasKeyCertPairs(kIdentityCert1Name));
// After setting the certificates to the corresponding cert names, the
// distributor should possess the corresponding certs.
distributor_.SetKeyMaterials(kRootCert1Name, kRootCert1Contents,
absl::nullopt);
EXPECT_TRUE(distributor_.HasRootCerts(kRootCert1Name));
distributor_.SetKeyMaterials(
kIdentityCert1Name, absl::nullopt,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
EXPECT_TRUE(distributor_.HasKeyCertPairs(kIdentityCert1Name));
// Querying a non-existing cert name should return false.
EXPECT_FALSE(distributor_.HasRootCerts(kRootCert2Name));
EXPECT_FALSE(distributor_.HasKeyCertPairs(kIdentityCert2Name));
}
TEST_F(GrpcTlsCertificateDistributorTest, UpdateCredentialsOnAnySide) {
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName1);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, true, true)));
// SetKeyMaterials should trigger watcher's OnCertificatesChanged method.
distributor_.SetKeyMaterials(
kCertName1, kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
EXPECT_THAT(
watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents))));
// Set root certs should trigger watcher's OnCertificatesChanged again.
distributor_.SetKeyMaterials(kCertName1, kRootCert2Contents, absl::nullopt);
EXPECT_THAT(
watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert2Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents))));
// Set identity certs should trigger watcher's OnCertificatesChanged again.
distributor_.SetKeyMaterials(
kCertName1, absl::nullopt,
MakeCertKeyPairs(kIdentityCert2PrivateKey, kIdentityCert2Contents));
EXPECT_THAT(
watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert2Contents,
MakeCertKeyPairs(kIdentityCert2PrivateKey, kIdentityCert2Contents))));
CancelWatch(watcher_state_1);
}
TEST_F(GrpcTlsCertificateDistributorTest, SameIdentityNameDiffRootName) {
// Register watcher 1.
WatcherState* watcher_state_1 =
MakeWatcher(kRootCert1Name, kIdentityCert1Name);
EXPECT_THAT(
GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kRootCert1Name, true, false),
CallbackStatus(kIdentityCert1Name, false, true)));
// Register watcher 2.
WatcherState* watcher_state_2 =
MakeWatcher(kRootCert2Name, kIdentityCert1Name);
EXPECT_THAT(GetCallbackQueue(), testing::ElementsAre(CallbackStatus(
kRootCert2Name, true, false)));
// Push credential updates to kRootCert1Name and check if the status works as
// expected.
distributor_.SetKeyMaterials(kRootCert1Name, kRootCert1Contents,
absl::nullopt);
// Check the updates are delivered to watcher 1.
EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(kRootCert1Contents, {})));
// Push credential updates to kRootCert2Name.
distributor_.SetKeyMaterials(kRootCert2Name, kRootCert2Contents,
absl::nullopt);
// Check the updates are delivered to watcher 2.
EXPECT_THAT(watcher_state_2->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(kRootCert2Contents, {})));
// Push credential updates to kIdentityCert1Name and check if the status works
// as expected.
distributor_.SetKeyMaterials(
kIdentityCert1Name, absl::nullopt,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
// Check the updates are delivered to watcher 1 and watcher 2.
EXPECT_THAT(
watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents))));
EXPECT_THAT(
watcher_state_2->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert2Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents))));
// Cancel watcher 1.
CancelWatch(watcher_state_1);
EXPECT_THAT(GetCallbackQueue(), testing::ElementsAre(CallbackStatus(
kRootCert1Name, false, false)));
// Cancel watcher 2.
CancelWatch(watcher_state_2);
EXPECT_THAT(
GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kRootCert2Name, false, false),
CallbackStatus(kIdentityCert1Name, false, false)));
}
TEST_F(GrpcTlsCertificateDistributorTest, SameRootNameDiffIdentityName) {
// Register watcher 1.
WatcherState* watcher_state_1 =
MakeWatcher(kRootCert1Name, kIdentityCert1Name);
EXPECT_THAT(
GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kRootCert1Name, true, false),
CallbackStatus(kIdentityCert1Name, false, true)));
// Register watcher 2.
WatcherState* watcher_state_2 =
MakeWatcher(kRootCert1Name, kIdentityCert2Name);
EXPECT_THAT(GetCallbackQueue(), testing::ElementsAre(CallbackStatus(
kIdentityCert2Name, false, true)));
// Push credential updates to kRootCert1Name and check if the status works as
// expected.
distributor_.SetKeyMaterials(kRootCert1Name, kRootCert1Contents,
absl::nullopt);
// Check the updates are delivered to watcher 1.
EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(kRootCert1Contents, {})));
// Check the updates are delivered to watcher 2.
EXPECT_THAT(watcher_state_2->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(kRootCert1Contents, {})));
// Push credential updates to SetKeyMaterials.
distributor_.SetKeyMaterials(
kIdentityCert1Name, absl::nullopt,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
// Check the updates are delivered to watcher 1.
EXPECT_THAT(
watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents))));
// Push credential updates to kIdentityCert2Name.
distributor_.SetKeyMaterials(
kIdentityCert2Name, absl::nullopt,
MakeCertKeyPairs(kIdentityCert2PrivateKey, kIdentityCert2Contents));
// Check the updates are delivered to watcher 2.
EXPECT_THAT(
watcher_state_2->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert2PrivateKey, kIdentityCert2Contents))));
// Cancel watcher 1.
CancelWatch(watcher_state_1);
EXPECT_THAT(GetCallbackQueue(), testing::ElementsAre(CallbackStatus(
kIdentityCert1Name, false, false)));
// Cancel watcher 2.
CancelWatch(watcher_state_2);
EXPECT_THAT(
GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kRootCert1Name, false, false),
CallbackStatus(kIdentityCert2Name, false, false)));
}
TEST_F(GrpcTlsCertificateDistributorTest,
AddAndCancelFirstWatcherForSameRootAndIdentityCertName) {
// Register watcher 1 watching kCertName1 for both root and identity certs.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName1);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, true, true)));
// Push credential updates to kCertName1 and check if the status works as
// expected.
distributor_.SetKeyMaterials(
kCertName1, kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
// Check the updates are delivered to watcher 1.
EXPECT_THAT(
watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents))));
// Cancel watcher 1.
CancelWatch(watcher_state_1);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, false, false)));
}
TEST_F(GrpcTlsCertificateDistributorTest,
AddAndCancelFirstWatcherForIdentityCertNameWithRootBeingWatched) {
// Register watcher 1 watching kCertName1 for root certs.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, absl::nullopt);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, true, false)));
// Register watcher 2 watching kCertName1 for identity certs.
WatcherState* watcher_state_2 = MakeWatcher(absl::nullopt, kCertName1);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, true, true)));
// Push credential updates to kCertName1 and check if the status works as
// expected.
distributor_.SetKeyMaterials(
kCertName1, kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
// Check the updates are delivered to watcher 1.
EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(kRootCert1Contents, {})));
// Check the updates are delivered to watcher 2.
EXPECT_THAT(watcher_state_2->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
"", MakeCertKeyPairs(kIdentityCert1PrivateKey,
kIdentityCert1Contents))));
// Push root cert updates to kCertName1.
distributor_.SetKeyMaterials(kCertName1, kRootCert2Contents, absl::nullopt);
// Check the updates are delivered to watcher 1.
EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(kRootCert2Contents, {})));
// Check the updates are not delivered to watcher 2.
EXPECT_THAT(watcher_state_2->GetCredentialQueue(), testing::ElementsAre());
// Push identity cert updates to kCertName1.
distributor_.SetKeyMaterials(
kCertName1, absl::nullopt,
MakeCertKeyPairs(kIdentityCert2PrivateKey, kIdentityCert2Contents));
// Check the updates are not delivered to watcher 1.
EXPECT_THAT(watcher_state_1->GetCredentialQueue(), testing::ElementsAre());
// Check the updates are delivered to watcher 2.
EXPECT_THAT(watcher_state_2->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
"", MakeCertKeyPairs(kIdentityCert2PrivateKey,
kIdentityCert2Contents))));
watcher_state_2->cert_update_queue.clear();
// Cancel watcher 2.
CancelWatch(watcher_state_2);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, true, false)));
// Cancel watcher 1.
CancelWatch(watcher_state_1);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, false, false)));
}
TEST_F(GrpcTlsCertificateDistributorTest,
AddAndCancelFirstWatcherForRootCertNameWithIdentityBeingWatched) {
// Register watcher 1 watching kCertName1 for identity certs.
WatcherState* watcher_state_1 = MakeWatcher(absl::nullopt, kCertName1);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, false, true)));
// Register watcher 2 watching kCertName1 for root certs.
WatcherState* watcher_state_2 = MakeWatcher(kCertName1, absl::nullopt);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, true, true)));
// Push credential updates to kCertName1 and check if the status works as
// expected.
distributor_.SetKeyMaterials(
kCertName1, kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
// Check the updates are delivered to watcher 1.
EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
"", MakeCertKeyPairs(kIdentityCert1PrivateKey,
kIdentityCert1Contents))));
// Check the updates are delivered to watcher 2.
EXPECT_THAT(watcher_state_2->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(kRootCert1Contents, {})));
// Push root cert updates to kCertName1.
distributor_.SetKeyMaterials(kCertName1, kRootCert2Contents, absl::nullopt);
// Check the updates are delivered to watcher 2.
EXPECT_THAT(watcher_state_2->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(kRootCert2Contents, {})));
// Check the updates are not delivered to watcher 1.
EXPECT_THAT(watcher_state_1->GetCredentialQueue(), testing::ElementsAre());
// Push identity cert updates to kCertName1.
distributor_.SetKeyMaterials(
kCertName1, absl::nullopt,
MakeCertKeyPairs(kIdentityCert2PrivateKey, kIdentityCert2Contents));
// Check the updates are not delivered to watcher 2.
EXPECT_THAT(watcher_state_2->GetCredentialQueue(), testing::ElementsAre());
// Check the updates are delivered to watcher 1.
EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
"", MakeCertKeyPairs(kIdentityCert2PrivateKey,
kIdentityCert2Contents))));
// Cancel watcher 2.
CancelWatch(watcher_state_2);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, false, true)));
// Cancel watcher 1.
CancelWatch(watcher_state_1);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, false, false)));
}
TEST_F(GrpcTlsCertificateDistributorTest,
RemoveAllWatchersForCertNameAndAddAgain) {
// Register watcher 1 and watcher 2 watching kCertName1 for root and identity
// certs.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName1);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, true, true)));
WatcherState* watcher_state_2 = MakeWatcher(kCertName1, kCertName1);
EXPECT_THAT(GetCallbackQueue(), testing::ElementsAre());
// Push credential updates to kCertName1.
distributor_.SetKeyMaterials(
kCertName1, kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
// Cancel watcher 2.
CancelWatch(watcher_state_2);
EXPECT_THAT(GetCallbackQueue(), testing::ElementsAre());
// Cancel watcher 1.
CancelWatch(watcher_state_1);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, false, false)));
// Register watcher 3 watching kCertName for root and identity certs.
WatcherState* watcher_state_3 = MakeWatcher(kCertName1, kCertName1);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, true, true)));
// Push credential updates to kCertName1.
distributor_.SetKeyMaterials(
kCertName1, kRootCert2Contents,
MakeCertKeyPairs(kIdentityCert2PrivateKey, kIdentityCert2Contents));
// Check the updates are delivered to watcher 3.
EXPECT_THAT(
watcher_state_3->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert2Contents,
MakeCertKeyPairs(kIdentityCert2PrivateKey, kIdentityCert2Contents))));
// Cancel watcher 3.
CancelWatch(watcher_state_3);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, false, false)));
}
TEST_F(GrpcTlsCertificateDistributorTest, ResetCallbackToNull) {
// Register watcher 1 watching kCertName1 for root and identity certs.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName1);
EXPECT_THAT(GetCallbackQueue(),
testing::ElementsAre(CallbackStatus(kCertName1, true, true)));
// Reset callback to nullptr.
distributor_.SetWatchStatusCallback(nullptr);
// Cancel watcher 1 shouldn't trigger any callback.
CancelWatch(watcher_state_1);
EXPECT_THAT(GetCallbackQueue(), testing::ElementsAre());
}
TEST_F(GrpcTlsCertificateDistributorTest, SetKeyMaterialsInCallback) {
distributor_.SetWatchStatusCallback([this](std::string cert_name,
bool root_being_watched,
bool identity_being_watched) {
distributor_.SetKeyMaterials(
cert_name, kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
});
auto verify_function = [this](std::string cert_name) {
WatcherState* watcher_state_1 = MakeWatcher(cert_name, cert_name);
// Check the updates are delivered to watcher 1.
EXPECT_THAT(
watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert1Contents, MakeCertKeyPairs(kIdentityCert1PrivateKey,
kIdentityCert1Contents))));
CancelWatch(watcher_state_1);
};
// Start 1000 threads that will register a watcher to a new cert name, verify
// the key materials being set, and then cancel the watcher, to make sure the
// lock mechanism in the distributor is safe.
std::vector<std::thread> threads;
threads.reserve(1000);
for (int i = 0; i < 1000; ++i) {
threads.emplace_back(verify_function, std::to_string(i));
}
for (auto& th : threads) {
th.join();
}
}
TEST_F(GrpcTlsCertificateDistributorTest, WatchACertInfoWithValidCredentials) {
// Push credential updates to kCertName1.
distributor_.SetKeyMaterials(
kCertName1, kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
// Push root credential updates to kCertName2.
distributor_.SetKeyMaterials(kRootCert2Name, kRootCert2Contents,
absl::nullopt);
// Push identity credential updates to kCertName2.
distributor_.SetKeyMaterials(
kIdentityCert2Name, absl::nullopt,
MakeCertKeyPairs(kIdentityCert2PrivateKey, kIdentityCert2Contents));
// Register watcher 1.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName1);
// watcher 1 should receive the credentials right away.
EXPECT_THAT(
watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents))));
CancelWatch(watcher_state_1);
// Register watcher 2.
WatcherState* watcher_state_2 = MakeWatcher(kRootCert2Name, absl::nullopt);
// watcher 2 should receive the root credentials right away.
EXPECT_THAT(watcher_state_2->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(kRootCert2Contents, {})));
// Register watcher 3.
WatcherState* watcher_state_3 =
MakeWatcher(absl::nullopt, kIdentityCert2Name);
// watcher 3 should received the identity credentials right away.
EXPECT_THAT(watcher_state_3->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
"", MakeCertKeyPairs(kIdentityCert2PrivateKey,
kIdentityCert2Contents))));
CancelWatch(watcher_state_2);
CancelWatch(watcher_state_3);
}
TEST_F(GrpcTlsCertificateDistributorTest,
SetErrorForCertForBothRootAndIdentity) {
// Register watcher 1.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName1);
// Calling SetErrorForCert on both cert names should only call one OnError
// on watcher 1.
distributor_.SetErrorForCert(
kCertName1, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(
ErrorInfo(kRootErrorMessage, kIdentityErrorMessage)));
// Calling SetErrorForCert on root cert name should call OnError
// on watcher 1 again.
distributor_.SetErrorForCert(
kCertName1, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kErrorMessage),
absl::nullopt);
EXPECT_THAT(
watcher_state_1->GetErrorQueue(),
testing::ElementsAre(ErrorInfo(kErrorMessage, kIdentityErrorMessage)));
// Calling SetErrorForCert on identity cert name should call OnError
// on watcher 1 again.
distributor_.SetErrorForCert(
kCertName1, absl::nullopt,
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kErrorMessage));
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(ErrorInfo(kErrorMessage, kErrorMessage)));
distributor_.CancelTlsCertificatesWatch(watcher_state_1->watcher);
EXPECT_EQ(watcher_state_1->watcher, nullptr);
}
TEST_F(GrpcTlsCertificateDistributorTest, SetErrorForCertForRootOrIdentity) {
// Register watcher 1.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, absl::nullopt);
// Calling SetErrorForCert on root name should only call one OnError
// on watcher 1.
distributor_.SetErrorForCert(
kCertName1, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
absl::nullopt);
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(ErrorInfo(kRootErrorMessage, "")));
// Calling SetErrorForCert on identity name should do nothing.
distributor_.SetErrorForCert(
kCertName1, absl::nullopt,
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
EXPECT_THAT(watcher_state_1->GetErrorQueue(), testing::ElementsAre());
// Calling SetErrorForCert on both names should still get one OnError call.
distributor_.SetErrorForCert(
kCertName1, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(ErrorInfo(kRootErrorMessage, "")));
CancelWatch(watcher_state_1);
// Register watcher 2.
WatcherState* watcher_state_2 = MakeWatcher(absl::nullopt, kCertName1);
// Calling SetErrorForCert on identity name should only call one OnError
// on watcher 2.
distributor_.SetErrorForCert(
kCertName1, absl::nullopt,
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
EXPECT_THAT(watcher_state_2->GetErrorQueue(),
testing::ElementsAre(ErrorInfo("", kIdentityErrorMessage)));
// Calling SetErrorForCert on root name should do nothing.
distributor_.SetErrorForCert(
kCertName1, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
absl::nullopt);
EXPECT_THAT(watcher_state_2->GetErrorQueue(), testing::ElementsAre());
// Calling SetErrorForCert on both names should still get one OnError call.
distributor_.SetErrorForCert(
kCertName1, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
EXPECT_THAT(watcher_state_2->GetErrorQueue(),
testing::ElementsAre(ErrorInfo("", kIdentityErrorMessage)));
CancelWatch(watcher_state_2);
}
TEST_F(GrpcTlsCertificateDistributorTest,
SetErrorForIdentityNameWithPreexistingErrorForRootName) {
// SetErrorForCert for kCertName1.
distributor_.SetErrorForCert(
kCertName1, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
// Register watcher 1 for kCertName1 as root and kCertName2 as identity.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName2);
// Should trigger OnError call right away since kCertName1 has error.
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(ErrorInfo(kRootErrorMessage, "")));
// Calling SetErrorForCert on kCertName2 should trigger OnError with both
// errors, because kCertName1 also has error.
distributor_.SetErrorForCert(
kCertName2, absl::nullopt,
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(
ErrorInfo(kRootErrorMessage, kIdentityErrorMessage)));
CancelWatch(watcher_state_1);
}
TEST_F(GrpcTlsCertificateDistributorTest,
SetErrorForCertForRootNameWithSameNameForIdentityErrored) {
// SetErrorForCert for kCertName1.
distributor_.SetErrorForCert(
kCertName1, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
// Register watcher 1 for kCertName2 as root and kCertName1 as identity.
WatcherState* watcher_state_1 = MakeWatcher(kCertName2, kCertName1);
// Should trigger OnError call right away since kCertName2 has error.
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(ErrorInfo("", kIdentityErrorMessage)));
// Calling SetErrorForCert on kCertName2 should trigger OnError with both
// errors, because kCertName1 also has error.
distributor_.SetErrorForCert(
kCertName2, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
absl::nullopt);
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(
ErrorInfo(kRootErrorMessage, kIdentityErrorMessage)));
CancelWatch(watcher_state_1);
}
TEST_F(GrpcTlsCertificateDistributorTest,
SetErrorForIdentityNameWithoutErrorForRootName) {
// Register watcher 1 for kCertName1 as root and kCertName2 as identity.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName2);
// Should not trigger OnError.
EXPECT_THAT(watcher_state_1->GetErrorQueue(), testing::ElementsAre());
// Calling SetErrorForCert on kCertName2 should trigger OnError.
distributor_.SetErrorForCert(
kCertName2, absl::nullopt,
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(ErrorInfo("", kIdentityErrorMessage)));
CancelWatch(watcher_state_1);
// Register watcher 2 for kCertName2 as identity and a non-existing name
// kRootCert1Name as root.
WatcherState* watcher_state_2 = MakeWatcher(kRootCert1Name, kCertName2);
// Should not trigger OnError.
EXPECT_THAT(watcher_state_2->GetErrorQueue(), testing::ElementsAre());
// Calling SetErrorForCert on kCertName2 should trigger OnError.
distributor_.SetErrorForCert(
kCertName2, absl::nullopt,
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
EXPECT_THAT(watcher_state_2->error_queue,
testing::ElementsAre(ErrorInfo("", kIdentityErrorMessage)));
CancelWatch(watcher_state_2);
}
TEST_F(GrpcTlsCertificateDistributorTest,
SetErrorForRootNameWithPreexistingErrorForIdentityName) {
WatcherState* watcher_state_1 = MakeWatcher(kCertName2, kCertName1);
// Should not trigger OnError.
EXPECT_THAT(watcher_state_1->GetErrorQueue(), testing::ElementsAre());
// Calling SetErrorForCert on kCertName2 should trigger OnError.
distributor_.SetErrorForCert(
kCertName2, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
absl::nullopt);
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(ErrorInfo(kRootErrorMessage, "")));
CancelWatch(watcher_state_1);
// Register watcher 2 for kCertName2 as root and a non-existing name
// kIdentityCert1Name as identity.
WatcherState* watcher_state_2 = MakeWatcher(kCertName2, kIdentityCert1Name);
// Should not trigger OnError.
EXPECT_THAT(watcher_state_2->GetErrorQueue(), testing::ElementsAre());
// Calling SetErrorForCert on kCertName2 should trigger OnError.
distributor_.SetErrorForCert(
kCertName2, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
absl::nullopt);
EXPECT_THAT(watcher_state_2->GetErrorQueue(),
testing::ElementsAre(ErrorInfo(kRootErrorMessage, "")));
CancelWatch(watcher_state_2);
}
TEST_F(GrpcTlsCertificateDistributorTest,
CancelTheLastWatcherOnAnErroredCertInfo) {
// Register watcher 1.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName1);
// Calling SetErrorForCert on both cert names should only call one OnError
// on watcher 1.
distributor_.SetErrorForCert(
kCertName1, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(
ErrorInfo(kRootErrorMessage, kIdentityErrorMessage)));
// When watcher 1 is removed, the cert info entry should be removed.
CancelWatch(watcher_state_1);
// Register watcher 2 on the same cert name.
WatcherState* watcher_state_2 = MakeWatcher(kCertName1, kCertName1);
// Should not trigger OnError call on watcher 2 right away.
EXPECT_THAT(watcher_state_2->GetErrorQueue(), testing::ElementsAre());
CancelWatch(watcher_state_2);
}
TEST_F(GrpcTlsCertificateDistributorTest,
WatchErroredCertInfoWithValidCredentialData) {
// Push credential updates to kCertName1.
distributor_.SetKeyMaterials(
kCertName1, kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
// Calling SetErrorForCert on both cert names.
distributor_.SetErrorForCert(
kCertName1, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
// Register watcher 1.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName1);
// watcher 1 should receive both the old credentials and the error right away.
EXPECT_THAT(
watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents))));
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(
ErrorInfo(kRootErrorMessage, kIdentityErrorMessage)));
CancelWatch(watcher_state_1);
}
TEST_F(GrpcTlsCertificateDistributorTest,
SetErrorForCertThenSuccessfulCredentialUpdates) {
// Calling SetErrorForCert on both cert names.
distributor_.SetErrorForCert(
kCertName1, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
// Push credential updates to kCertName1.
distributor_.SetKeyMaterials(
kCertName1, kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents));
// Register watcher 1.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName1);
// watcher 1 should only receive credential updates without any error, because
// the previous error is wiped out by a successful update.
EXPECT_THAT(
watcher_state_1->GetCredentialQueue(),
testing::ElementsAre(CredentialInfo(
kRootCert1Contents,
MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1Contents))));
EXPECT_THAT(watcher_state_1->GetErrorQueue(), testing::ElementsAre());
CancelWatch(watcher_state_1);
}
TEST_F(GrpcTlsCertificateDistributorTest, WatchCertInfoThenInvokeSetError) {
// Register watcher 1.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, kCertName1);
// Register watcher 2.
WatcherState* watcher_state_2 = MakeWatcher(kRootCert1Name, absl::nullopt);
// Register watcher 3.
WatcherState* watcher_state_3 =
MakeWatcher(absl::nullopt, kIdentityCert1Name);
distributor_.SetError(GRPC_ERROR_CREATE_FROM_STATIC_STRING(kErrorMessage));
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(ErrorInfo(kErrorMessage, kErrorMessage)));
EXPECT_THAT(watcher_state_2->GetErrorQueue(),
testing::ElementsAre(ErrorInfo(kErrorMessage, "")));
EXPECT_THAT(watcher_state_3->GetErrorQueue(),
testing::ElementsAre(ErrorInfo("", kErrorMessage)));
CancelWatch(watcher_state_1);
CancelWatch(watcher_state_2);
CancelWatch(watcher_state_3);
}
TEST_F(GrpcTlsCertificateDistributorTest, WatchErroredCertInfoBySetError) {
// Register watcher 1 watching kCertName1 as root.
WatcherState* watcher_state_1 = MakeWatcher(kCertName1, absl::nullopt);
// Register watcher 2 watching kCertName2 as identity.
WatcherState* watcher_state_2 = MakeWatcher(absl::nullopt, kCertName2);
// Call SetError and then cancel all watchers.
distributor_.SetError(GRPC_ERROR_CREATE_FROM_STATIC_STRING(kErrorMessage));
CancelWatch(watcher_state_1);
CancelWatch(watcher_state_2);
// Register watcher 3 watching kCertName1 as root and kCertName2 as identity
// should not get the error updates.
WatcherState* watcher_state_3 = MakeWatcher(kCertName1, kCertName2);
EXPECT_THAT(watcher_state_3->GetErrorQueue(), testing::ElementsAre());
CancelWatch(watcher_state_3);
// Register watcher 4 watching kCertName2 as root and kCertName1 as identity
// should not get the error updates.
WatcherState* watcher_state_4 = MakeWatcher(kCertName2, kCertName1);
EXPECT_THAT(watcher_state_4->GetErrorQueue(), testing::ElementsAre());
CancelWatch(watcher_state_4);
}
TEST_F(GrpcTlsCertificateDistributorTest, SetErrorForCertInCallback) {
distributor_.SetWatchStatusCallback([this](std::string cert_name,
bool root_being_watched,
bool identity_being_watched) {
this->distributor_.SetErrorForCert(
cert_name, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage),
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage));
});
auto verify_function = [this](std::string cert_name) {
WatcherState* watcher_state_1 = MakeWatcher(cert_name, cert_name);
// Check the errors are delivered to watcher 1.
EXPECT_THAT(watcher_state_1->GetErrorQueue(),
testing::ElementsAre(
ErrorInfo(kRootErrorMessage, kIdentityErrorMessage)));
CancelWatch(watcher_state_1);
};
// Start 1000 threads that will register a watcher to a new cert name, verify
// the key materials being set, and then cancel the watcher, to make sure the
// lock mechanism in the distributor is safe.
std::vector<std::thread> threads;
threads.reserve(1000);
for (int i = 0; i < 1000; ++i) {
threads.emplace_back(verify_function, std::to_string(i));
}
for (auto& th : threads) {
th.join();
}
}
} // namespace testing
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv);
grpc_init();
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return ret;
}

@ -79,9 +79,6 @@ grpc_cc_test(
grpc_cc_test( grpc_cc_test(
name = "init_test", name = "init_test",
srcs = ["init_test.cc"], srcs = ["init_test.cc"],
external_deps = [
"gtest",
],
language = "C++", language = "C++",
uses_polling = False, uses_polling = False,
deps = [ deps = [

@ -16,22 +16,14 @@
* *
*/ */
#include "src/core/lib/surface/init.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include <gtest/gtest.h>
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/surface/init.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
static int g_plugin_state; static int g_flag;
static void plugin_init(void) { g_plugin_state = 1; }
static void plugin_destroy(void) { g_plugin_state = 2; }
static bool plugin_is_intialized(void) { return g_plugin_state == 1; }
static bool plugin_is_destroyed(void) { return g_plugin_state == 2; }
static void test(int rounds) { static void test(int rounds) {
int i; int i;
@ -41,13 +33,7 @@ static void test(int rounds) {
for (i = 0; i < rounds; i++) { for (i = 0; i < rounds; i++) {
grpc_shutdown(); grpc_shutdown();
} }
EXPECT_FALSE(grpc_is_initialized()); grpc_maybe_wait_for_async_shutdown();
}
TEST(Init, test) {
test(1);
test(2);
test(3);
} }
static void test_blocking(int rounds) { static void test_blocking(int rounds) {
@ -58,87 +44,55 @@ static void test_blocking(int rounds) {
for (i = 0; i < rounds; i++) { for (i = 0; i < rounds; i++) {
grpc_shutdown_blocking(); grpc_shutdown_blocking();
} }
EXPECT_FALSE(grpc_is_initialized());
}
TEST(Init, blocking) {
test_blocking(1);
test_blocking(2);
test_blocking(3);
}
TEST(Init, shutdown_with_thread) {
grpc_init();
{
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx(
GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD);
grpc_shutdown();
}
grpc_maybe_wait_for_async_shutdown();
EXPECT_FALSE(grpc_is_initialized());
} }
TEST(Init, mixed) { static void test_mixed(void) {
grpc_init(); grpc_init();
grpc_init(); grpc_init();
grpc_shutdown(); grpc_shutdown();
grpc_init(); grpc_init();
grpc_shutdown(); grpc_shutdown();
grpc_shutdown(); grpc_shutdown();
EXPECT_FALSE(grpc_is_initialized());
}
TEST(Init, mixed_with_thread) {
grpc_init();
{
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx(
GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD);
grpc_init();
grpc_shutdown();
grpc_init();
grpc_shutdown();
grpc_shutdown();
}
grpc_maybe_wait_for_async_shutdown(); grpc_maybe_wait_for_async_shutdown();
EXPECT_FALSE(grpc_is_initialized());
} }
TEST(Init, plugin) { static void plugin_init(void) { g_flag = 1; }
static void plugin_destroy(void) { g_flag = 2; }
static void test_plugin() {
grpc_register_plugin(plugin_init, plugin_destroy);
grpc_init(); grpc_init();
EXPECT_TRUE(plugin_is_intialized()); GPR_ASSERT(g_flag == 1);
grpc_shutdown_blocking(); grpc_shutdown_blocking();
EXPECT_TRUE(plugin_is_destroyed()); GPR_ASSERT(g_flag == 2);
EXPECT_FALSE(grpc_is_initialized());
} }
TEST(Init, repeatedly) { static void test_repeatedly() {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 1000; i++) {
grpc_init(); grpc_init();
{ grpc_shutdown();
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx(
GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD);
grpc_shutdown();
}
} }
grpc_maybe_wait_for_async_shutdown(); grpc_maybe_wait_for_async_shutdown();
EXPECT_FALSE(grpc_is_initialized());
} }
TEST(Init, repeatedly_blocking) { static void test_repeatedly_blocking() {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 1000; i++) {
grpc_init(); grpc_init();
{ grpc_shutdown_blocking();
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx(
GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD);
grpc_shutdown_blocking();
}
} }
EXPECT_FALSE(grpc_is_initialized());
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv); grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv); test(1);
grpc_register_plugin(plugin_init, plugin_destroy); test(2);
return RUN_ALL_TESTS(); test(3);
test_blocking(1);
test_blocking(2);
test_blocking(3);
test_mixed();
test_plugin();
test_repeatedly();
test_repeatedly_blocking();
return 0;
} }

@ -104,7 +104,6 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_channel_watch_connectivity_state); printf("%lx", (unsigned long) grpc_channel_watch_connectivity_state);
printf("%lx", (unsigned long) grpc_channel_support_connectivity_watcher); printf("%lx", (unsigned long) grpc_channel_support_connectivity_watcher);
printf("%lx", (unsigned long) grpc_channel_create_call); printf("%lx", (unsigned long) grpc_channel_create_call);
printf("%lx", (unsigned long) grpc_channel_ping);
printf("%lx", (unsigned long) grpc_channel_register_call); printf("%lx", (unsigned long) grpc_channel_register_call);
printf("%lx", (unsigned long) grpc_channel_create_registered_call); printf("%lx", (unsigned long) grpc_channel_create_registered_call);
printf("%lx", (unsigned long) grpc_call_arena_alloc); printf("%lx", (unsigned long) grpc_call_arena_alloc);

@ -49,6 +49,7 @@
#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/security_connector/alts/alts_security_connector.h" #include "src/core/lib/security/security_connector/alts/alts_security_connector.h"
#include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/surface/channel.h"
#include "test/core/util/memory_counters.h" #include "test/core/util/memory_counters.h"
#include "test/core/util/port.h" #include "test/core/util/port.h"

@ -38,8 +38,14 @@
static int* chosen_ports = nullptr; static int* chosen_ports = nullptr;
static size_t num_chosen_ports = 0; static size_t num_chosen_ports = 0;
static grpc_core::Mutex* g_default_port_picker_mu;
static gpr_once g_default_port_picker_init = GPR_ONCE_INIT;
static int free_chosen_port(int port) { static void init_default_port_picker() {
g_default_port_picker_mu = new grpc_core::Mutex();
}
static int free_chosen_port_locked(int port) {
size_t i; size_t i;
int found = 0; int found = 0;
size_t found_at = 0; size_t found_at = 0;
@ -61,6 +67,7 @@ static int free_chosen_port(int port) {
} }
static void free_chosen_ports(void) { static void free_chosen_ports(void) {
grpc_core::MutexLock lock(g_default_port_picker_mu);
size_t i; size_t i;
grpc_init(); grpc_init();
for (i = 0; i < num_chosen_ports; i++) { for (i = 0; i < num_chosen_ports; i++) {
@ -70,7 +77,7 @@ static void free_chosen_ports(void) {
gpr_free(chosen_ports); gpr_free(chosen_ports);
} }
static void chose_port(int port) { static void chose_port_locked(int port) {
if (chosen_ports == nullptr) { if (chosen_ports == nullptr) {
atexit(free_chosen_ports); atexit(free_chosen_ports);
} }
@ -81,9 +88,11 @@ static void chose_port(int port) {
} }
static int grpc_pick_unused_port_impl(void) { static int grpc_pick_unused_port_impl(void) {
gpr_once_init(&g_default_port_picker_init, init_default_port_picker);
grpc_core::MutexLock lock(g_default_port_picker_mu);
int port = grpc_pick_port_using_server(); int port = grpc_pick_port_using_server();
if (port != 0) { if (port != 0) {
chose_port(port); chose_port_locked(port);
} }
return port; return port;
@ -103,7 +112,9 @@ static int grpc_pick_unused_port_or_die_impl(void) {
} }
static void grpc_recycle_unused_port_impl(int port) { static void grpc_recycle_unused_port_impl(int port) {
GPR_ASSERT(free_chosen_port(port)); gpr_once_init(&g_default_port_picker_init, init_default_port_picker);
grpc_core::MutexLock lock(g_default_port_picker_mu);
GPR_ASSERT(free_chosen_port_locked(port));
} }
static grpc_pick_port_functions g_pick_port_functions = { static grpc_pick_port_functions g_pick_port_functions = {

@ -1531,7 +1531,8 @@ class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
std::tuple<int, int, int> WaitForAllBackends( std::tuple<int, int, int> WaitForAllBackends(
size_t start_index = 0, size_t stop_index = 0, bool reset_counters = true, size_t start_index = 0, size_t stop_index = 0, bool reset_counters = true,
const RpcOptions& rpc_options = RpcOptions()) { const RpcOptions& rpc_options = RpcOptions(),
bool allow_failures = false) {
int num_ok = 0; int num_ok = 0;
int num_failure = 0; int num_failure = 0;
int num_drops = 0; int num_drops = 0;
@ -1545,7 +1546,7 @@ class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
"Performed %d warm up requests against the backends. " "Performed %d warm up requests against the backends. "
"%d succeeded, %d failed, %d dropped.", "%d succeeded, %d failed, %d dropped.",
num_total, num_ok, num_failure, num_drops); num_total, num_ok, num_failure, num_drops);
EXPECT_EQ(num_failure, 0); if (!allow_failures) EXPECT_EQ(num_failure, 0);
return std::make_tuple(num_ok, num_failure, num_drops); return std::make_tuple(num_ok, num_failure, num_drops);
} }
@ -1662,8 +1663,10 @@ class XdsEnd2endTest : public ::testing::TestWithParam<TestType> {
for (const auto& metadata : rpc_options.metadata) { for (const auto& metadata : rpc_options.metadata) {
context.AddMetadata(metadata.first, metadata.second); context.AddMetadata(metadata.first, metadata.second);
} }
context.set_deadline( if (rpc_options.timeout_ms != 0) {
grpc_timeout_milliseconds_to_deadline(rpc_options.timeout_ms)); context.set_deadline(
grpc_timeout_milliseconds_to_deadline(rpc_options.timeout_ms));
}
if (rpc_options.wait_for_ready) context.set_wait_for_ready(true); if (rpc_options.wait_for_ready) context.set_wait_for_ready(true);
request.set_message(kRequestMessage_); request.set_message(kRequestMessage_);
if (rpc_options.server_fail) { if (rpc_options.server_fail) {
@ -3593,6 +3596,101 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateClusters) {
(1 + kErrorToleranceSmallLoad)))); (1 + kErrorToleranceSmallLoad))));
} }
TEST_P(LdsRdsTest, XdsRoutingClusterUpdateClusters) {
const char* kNewCluster1Name = "new_cluster_1";
const size_t kNumEchoRpcs = 5;
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
// Populate new EDS resources.
AdsServiceImpl::EdsResourceArgs args({
{"locality0", GetBackendPorts(0, 1)},
});
AdsServiceImpl::EdsResourceArgs args1({
{"locality0", GetBackendPorts(1, 2)},
});
balancers_[0]->ads_service()->SetEdsResource(
AdsServiceImpl::BuildEdsResource(args));
balancers_[0]->ads_service()->SetEdsResource(
AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
// Populate new CDS resources.
Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
new_cluster1.set_name(kNewCluster1Name);
balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
// Send Route Configuration.
RouteConfiguration new_route_config =
balancers_[0]->ads_service()->default_route_config();
SetRouteConfiguration(0, new_route_config);
WaitForAllBackends(0, 1);
CheckRpcSendOk(kNumEchoRpcs);
// Make sure RPCs all go to the correct backend.
EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
// Change Route Configurations: new default cluster.
auto* default_route =
new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
default_route->mutable_route()->set_cluster(kNewCluster1Name);
SetRouteConfiguration(0, new_route_config);
WaitForAllBackends(1, 2);
CheckRpcSendOk(kNumEchoRpcs);
// Make sure RPCs all go to the correct backend.
EXPECT_EQ(kNumEchoRpcs, backends_[1]->backend_service()->request_count());
}
TEST_P(LdsRdsTest, XdsRoutingClusterUpdateClustersWithPickingDelays) {
const char* kNewCluster1Name = "new_cluster_1";
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
// Populate new EDS resources.
AdsServiceImpl::EdsResourceArgs args({
{"locality0", GetBackendPorts(0, 1)},
});
AdsServiceImpl::EdsResourceArgs args1({
{"locality0", GetBackendPorts(1, 2)},
});
balancers_[0]->ads_service()->SetEdsResource(
AdsServiceImpl::BuildEdsResource(args));
balancers_[0]->ads_service()->SetEdsResource(
AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
// Populate new CDS resources.
Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
new_cluster1.set_name(kNewCluster1Name);
balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
// Bring down the current backend: 0, this will delay route picking time,
// resulting in un-committed RPCs.
ShutdownBackend(0);
// Send a RouteConfiguration with a default route that points to
// backend 0.
RouteConfiguration new_route_config =
balancers_[0]->ads_service()->default_route_config();
SetRouteConfiguration(0, new_route_config);
// Send exactly one RPC with no deadline and with wait_for_ready=true.
// This RPC will not complete until after backend 0 is started.
std::thread sending_rpc([this]() {
CheckRpcSendOk(1, RpcOptions().set_wait_for_ready(true).set_timeout_ms(0));
});
// Send a non-wait_for_ready RPC which should fail, this will tell us
// that the client has received the update and attempted to connect.
const Status status = SendRpc(RpcOptions().set_timeout_ms(0));
EXPECT_FALSE(status.ok());
// Send a update RouteConfiguration to use backend 1.
auto* default_route =
new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
default_route->mutable_route()->set_cluster(kNewCluster1Name);
SetRouteConfiguration(0, new_route_config);
// Wait for RPCs to go to the new backend: 1, this ensures that the client has
// processed the update.
WaitForAllBackends(1, 2, false, RpcOptions(), true);
// Bring up the previous backend: 0, this will allow the delayed RPC to
// finally call on_call_committed upon completion.
StartBackend(0);
sending_rpc.join();
// Make sure RPCs go to the correct backend:
// Before moving routing to XdsConfigSelector, 2 to backend 1;
// TODO(donnadionne): After moving routing to XdsConfigSelector, 1 for each
// backend.
EXPECT_EQ(0, backends_[0]->backend_service()->request_count());
EXPECT_EQ(2, backends_[1]->backend_service()->request_count());
}
TEST_P(LdsRdsTest, XdsRoutingHeadersMatching) { TEST_P(LdsRdsTest, XdsRoutingHeadersMatching) {
const char* kNewCluster1Name = "new_cluster_1"; const char* kNewCluster1Name = "new_cluster_1";
const size_t kNumEcho1Rpcs = 100; const size_t kNumEcho1Rpcs = 100;

@ -310,3 +310,54 @@ grpc_cc_binary(
"//src/proto/grpc/reflection/v1alpha:reflection_proto", "//src/proto/grpc/reflection/v1alpha:reflection_proto",
], ],
) )
grpc_cc_binary(
name = "channelz_sampler",
srcs = ["channelz_sampler.cc"],
external_deps = [
"gflags",
],
language = "c++",
tags = [
"no_windows", # unistd.h
],
deps = [
"//:gpr",
"//:grpc++",
"//:grpcpp_channelz",
"//src/proto/grpc/channelz:channelz_proto",
"//test/cpp/util:test_config",
"//test/cpp/util:test_util",
],
)
grpc_cc_test(
name = "channelz_sampler_test",
srcs = [
"channelz_sampler_test.cc",
],
data = [
":channelz_sampler",
],
external_deps = [
"gflags",
"gtest",
],
tags = [
"no_mac", # cmake does not build channelz_sampler in Basic Tests C/C++ MacOS test
"no_test_android", # android_cc_test doesn't work with data dependency.
"no_test_ios",
"no_windows", # unistd.h
],
deps = [
"//:gpr",
"//:grpc",
"//:grpc++",
"//:grpcpp_channelz",
"//src/proto/grpc/channelz:channelz_proto",
"//src/proto/grpc/testing:test_proto",
"//test/core/util:grpc_test_util",
"//test/core/util:grpc_test_util_base",
"//test/cpp/util:test_util",
],
)

@ -0,0 +1,588 @@
/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <unistd.h>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <memory>
#include <ostream>
#include <queue>
#include <string>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "gflags/gflags.h"
#include "google/protobuf/text_format.h"
#include "grpc/grpc.h"
#include "grpc/support/port_platform.h"
#include "grpcpp/channel.h"
#include "grpcpp/client_context.h"
#include "grpcpp/create_channel.h"
#include "grpcpp/ext/channelz_service_plugin.h"
#include "grpcpp/grpcpp.h"
#include "grpcpp/security/credentials.h"
#include "grpcpp/security/server_credentials.h"
#include "grpcpp/server.h"
#include "grpcpp/server_builder.h"
#include "grpcpp/server_context.h"
#include "src/core/lib/json/json.h"
#include "src/cpp/server/channelz/channelz_service.h"
#include "src/proto/grpc/channelz/channelz.pb.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/test_config.h"
#include "test/cpp/util/test_credentials_provider.h"
DEFINE_string(server_address, "", "channelz server address");
DEFINE_string(custom_credentials_type, "", "custom credentials type");
DEFINE_int64(sampling_times, 1, "number of sampling");
DEFINE_int64(sampling_interval_seconds, 0, "sampling interval in seconds");
DEFINE_string(output_json, "", "output filename in json format");
namespace {
using grpc::ClientContext;
using grpc::Status;
using grpc::StatusCode;
using grpc::channelz::v1::GetChannelRequest;
using grpc::channelz::v1::GetChannelResponse;
using grpc::channelz::v1::GetServerRequest;
using grpc::channelz::v1::GetServerResponse;
using grpc::channelz::v1::GetServerSocketsRequest;
using grpc::channelz::v1::GetServerSocketsResponse;
using grpc::channelz::v1::GetServersRequest;
using grpc::channelz::v1::GetServersResponse;
using grpc::channelz::v1::GetSocketRequest;
using grpc::channelz::v1::GetSocketResponse;
using grpc::channelz::v1::GetSubchannelRequest;
using grpc::channelz::v1::GetSubchannelResponse;
using grpc::channelz::v1::GetTopChannelsRequest;
using grpc::channelz::v1::GetTopChannelsResponse;
} // namespace
class ChannelzSampler final {
public:
// Get server_id of a server
int64_t GetServerID(const grpc::channelz::v1::Server& server) {
return server.ref().server_id();
}
// Get channel_id of a channel
inline int64_t GetChannelID(const grpc::channelz::v1::Channel& channel) {
return channel.ref().channel_id();
}
// Get subchannel_id of a subchannel
inline int64_t GetSubchannelID(
const grpc::channelz::v1::Subchannel& subchannel) {
return subchannel.ref().subchannel_id();
}
// Get socket_id of a socket
inline int64_t GetSocketID(const grpc::channelz::v1::Socket& socket) {
return socket.ref().socket_id();
}
// Get name of a server
inline std::string GetServerName(const grpc::channelz::v1::Server& server) {
return server.ref().name();
}
// Get name of a channel
inline std::string GetChannelName(
const grpc::channelz::v1::Channel& channel) {
return channel.ref().name();
}
// Get name of a subchannel
inline std::string GetSubchannelName(
const grpc::channelz::v1::Subchannel& subchannel) {
return subchannel.ref().name();
}
// Get name of a socket
inline std::string GetSocketName(const grpc::channelz::v1::Socket& socket) {
return socket.ref().name();
}
// Get a channel based on channel_id
grpc::channelz::v1::Channel GetChannelRPC(int64_t channel_id) {
GetChannelRequest get_channel_request;
get_channel_request.set_channel_id(channel_id);
GetChannelResponse get_channel_response;
ClientContext get_channel_context;
get_channel_context.set_deadline(
grpc_timeout_seconds_to_deadline(rpc_timeout_seconds_));
Status status = channelz_stub_->GetChannel(
&get_channel_context, get_channel_request, &get_channel_response);
if (!status.ok()) {
gpr_log(GPR_ERROR, "GetChannelRPC failed: %s",
get_channel_context.debug_error_string().c_str());
GPR_ASSERT(0);
}
return get_channel_response.channel();
}
// Get a subchannel based on subchannel_id
grpc::channelz::v1::Subchannel GetSubchannelRPC(int64_t subchannel_id) {
GetSubchannelRequest get_subchannel_request;
get_subchannel_request.set_subchannel_id(subchannel_id);
GetSubchannelResponse get_subchannel_response;
ClientContext get_subchannel_context;
get_subchannel_context.set_deadline(
grpc_timeout_seconds_to_deadline(rpc_timeout_seconds_));
Status status = channelz_stub_->GetSubchannel(&get_subchannel_context,
get_subchannel_request,
&get_subchannel_response);
if (!status.ok()) {
gpr_log(GPR_ERROR, "GetSubchannelRPC failed: %s",
get_subchannel_context.debug_error_string().c_str());
GPR_ASSERT(0);
}
return get_subchannel_response.subchannel();
}
// get a socket based on socket_id
grpc::channelz::v1::Socket GetSocketRPC(int64_t socket_id) {
GetSocketRequest get_socket_request;
get_socket_request.set_socket_id(socket_id);
GetSocketResponse get_socket_response;
ClientContext get_socket_context;
get_socket_context.set_deadline(
grpc_timeout_seconds_to_deadline(rpc_timeout_seconds_));
Status status = channelz_stub_->GetSocket(
&get_socket_context, get_socket_request, &get_socket_response);
if (!status.ok()) {
gpr_log(GPR_ERROR, "GetSocketRPC failed: %s",
get_socket_context.debug_error_string().c_str());
GPR_ASSERT(0);
}
return get_socket_response.socket();
}
// get the descedent channels/subchannels/sockets of a channel
// push descedent channels/subchannels to queue for layer traverse
// store descedent channels/subchannels/sockets for dumping data
void GetChannelDescedence(
const grpc::channelz::v1::Channel& channel,
std::queue<grpc::channelz::v1::Channel>& channel_queue,
std::queue<grpc::channelz::v1::Subchannel>& subchannel_queue) {
std::cout << " Channel ID" << GetChannelID(channel) << "_"
<< GetChannelName(channel) << " descendence - ";
if (channel.channel_ref_size() > 0 || channel.subchannel_ref_size() > 0) {
if (channel.channel_ref_size() > 0) {
std::cout << "channel: ";
for (const auto& _channelref : channel.channel_ref()) {
int64_t ch_id = _channelref.channel_id();
std::cout << "ID" << ch_id << "_" << _channelref.name() << " ";
grpc::channelz::v1::Channel ch = GetChannelRPC(ch_id);
channel_queue.push(ch);
if (CheckID(ch_id)) {
all_channels_.push_back(ch);
StoreChannelInJson(ch);
}
}
if (channel.subchannel_ref_size() > 0) {
std::cout << ", ";
}
}
if (channel.subchannel_ref_size() > 0) {
std::cout << "subchannel: ";
for (const auto& _subchannelref : channel.subchannel_ref()) {
int64_t subch_id = _subchannelref.subchannel_id();
std::cout << "ID" << subch_id << "_" << _subchannelref.name() << " ";
grpc::channelz::v1::Subchannel subch = GetSubchannelRPC(subch_id);
subchannel_queue.push(subch);
if (CheckID(subch_id)) {
all_subchannels_.push_back(subch);
StoreSubchannelInJson(subch);
}
}
}
} else if (channel.socket_ref_size() > 0) {
std::cout << "socket: ";
for (const auto& _socketref : channel.socket_ref()) {
int64_t so_id = _socketref.socket_id();
std::cout << "ID" << so_id << "_" << _socketref.name() << " ";
grpc::channelz::v1::Socket so = GetSocketRPC(so_id);
if (CheckID(so_id)) {
all_sockets_.push_back(so);
StoreSocketInJson(so);
}
}
}
std::cout << std::endl;
}
// get the descedent channels/subchannels/sockets of a subchannel
// push descedent channels/subchannels to queue for layer traverse
// store descedent channels/subchannels/sockets for dumping data
void GetSubchannelDescedence(
grpc::channelz::v1::Subchannel& subchannel,
std::queue<grpc::channelz::v1::Channel>& channel_queue,
std::queue<grpc::channelz::v1::Subchannel>& subchannel_queue) {
std::cout << " Subchannel ID" << GetSubchannelID(subchannel) << "_"
<< GetSubchannelName(subchannel) << " descendence - ";
if (subchannel.channel_ref_size() > 0 ||
subchannel.subchannel_ref_size() > 0) {
if (subchannel.channel_ref_size() > 0) {
std::cout << "channel: ";
for (const auto& _channelref : subchannel.channel_ref()) {
int64_t ch_id = _channelref.channel_id();
std::cout << "ID" << ch_id << "_" << _channelref.name() << " ";
grpc::channelz::v1::Channel ch = GetChannelRPC(ch_id);
channel_queue.push(ch);
if (CheckID(ch_id)) {
all_channels_.push_back(ch);
StoreChannelInJson(ch);
}
}
if (subchannel.subchannel_ref_size() > 0) {
std::cout << ", ";
}
}
if (subchannel.subchannel_ref_size() > 0) {
std::cout << "subchannel: ";
for (const auto& _subchannelref : subchannel.subchannel_ref()) {
int64_t subch_id = _subchannelref.subchannel_id();
std::cout << "ID" << subch_id << "_" << _subchannelref.name() << " ";
grpc::channelz::v1::Subchannel subch = GetSubchannelRPC(subch_id);
subchannel_queue.push(subch);
if (CheckID(subch_id)) {
all_subchannels_.push_back(subch);
StoreSubchannelInJson(subch);
}
}
}
} else if (subchannel.socket_ref_size() > 0) {
std::cout << "socket: ";
for (const auto& _socketref : subchannel.socket_ref()) {
int64_t so_id = _socketref.socket_id();
std::cout << "ID" << so_id << "_" << _socketref.name() << " ";
grpc::channelz::v1::Socket so = GetSocketRPC(so_id);
if (CheckID(so_id)) {
all_sockets_.push_back(so);
StoreSocketInJson(so);
}
}
}
std::cout << std::endl;
}
// Set up the channelz sampler client
// Initialize json as an array
void Setup(const std::string& custom_credentials_type,
const std::string& server_address) {
json_ = grpc_core::Json::Array();
rpc_timeout_seconds_ = 20;
grpc::ChannelArguments channel_args;
std::shared_ptr<grpc::ChannelCredentials> channel_creds =
grpc::testing::GetCredentialsProvider()->GetChannelCredentials(
custom_credentials_type, &channel_args);
if (!channel_creds) {
gpr_log(GPR_ERROR,
"Wrong user credential type: %s. Allowed credential types: "
"INSECURE_CREDENTIALS, ssl, alts, google_default_credentials.",
custom_credentials_type.c_str());
GPR_ASSERT(0);
}
std::shared_ptr<grpc::Channel> channel =
CreateChannel(server_address, channel_creds);
channelz_stub_ = grpc::channelz::v1::Channelz::NewStub(channel);
}
// Get all servers, keep querying until getting all
// Store servers for dumping data
// Need to check id repeating for servers
void GetServersRPC() {
int64_t server_start_id = 0;
while (true) {
GetServersRequest get_servers_request;
GetServersResponse get_servers_response;
ClientContext get_servers_context;
get_servers_context.set_deadline(
grpc_timeout_seconds_to_deadline(rpc_timeout_seconds_));
get_servers_request.set_start_server_id(server_start_id);
Status status = channelz_stub_->GetServers(
&get_servers_context, get_servers_request, &get_servers_response);
if (!status.ok()) {
if (status.error_code() == StatusCode::UNIMPLEMENTED) {
gpr_log(GPR_ERROR,
"Error status UNIMPLEMENTED. Please check and make sure "
"channelz has been registered on the server being queried.");
} else {
gpr_log(GPR_ERROR,
"GetServers RPC with GetServersRequest.server_start_id=%d, "
"failed: %s",
int(server_start_id),
get_servers_context.debug_error_string().c_str());
}
GPR_ASSERT(0);
}
for (const auto& _server : get_servers_response.server()) {
all_servers_.push_back(_server);
StoreServerInJson(_server);
}
if (!get_servers_response.end()) {
server_start_id = GetServerID(all_servers_.back()) + 1;
} else {
break;
}
}
std::cout << "Number of servers = " << all_servers_.size() << std::endl;
}
// Get sockets that belongs to servers
// Store sockets for dumping data
void GetSocketsOfServers() {
for (const auto& _server : all_servers_) {
std::cout << "Server ID" << GetServerID(_server) << "_"
<< GetServerName(_server) << " listen_socket - ";
for (const auto& _socket : _server.listen_socket()) {
int64_t so_id = _socket.socket_id();
std::cout << "ID" << so_id << "_" << _socket.name() << " ";
if (CheckID(so_id)) {
grpc::channelz::v1::Socket so = GetSocketRPC(so_id);
all_sockets_.push_back(so);
StoreSocketInJson(so);
}
}
std::cout << std::endl;
}
}
// Get all top channels, keep querying until getting all
// Store channels for dumping data
// No need to check id repeating for top channels
void GetTopChannelsRPC() {
int64_t channel_start_id = 0;
while (true) {
GetTopChannelsRequest get_top_channels_request;
GetTopChannelsResponse get_top_channels_response;
ClientContext get_top_channels_context;
get_top_channels_context.set_deadline(
grpc_timeout_seconds_to_deadline(rpc_timeout_seconds_));
get_top_channels_request.set_start_channel_id(channel_start_id);
Status status = channelz_stub_->GetTopChannels(
&get_top_channels_context, get_top_channels_request,
&get_top_channels_response);
if (!status.ok()) {
gpr_log(GPR_ERROR,
"GetTopChannels RPC with "
"GetTopChannelsRequest.channel_start_id=%d failed: %s",
int(channel_start_id),
get_top_channels_context.debug_error_string().c_str());
GPR_ASSERT(0);
}
for (const auto& _topchannel : get_top_channels_response.channel()) {
top_channels_.push_back(_topchannel);
all_channels_.push_back(_topchannel);
StoreChannelInJson(_topchannel);
}
if (!get_top_channels_response.end()) {
channel_start_id = GetChannelID(top_channels_.back()) + 1;
} else {
break;
}
}
std::cout << std::endl
<< "Number of top channels = " << top_channels_.size()
<< std::endl;
}
// layer traverse for each top channel
void TraverseTopChannels() {
for (const auto& _topchannel : top_channels_) {
int tree_depth = 0;
std::queue<grpc::channelz::v1::Channel> channel_queue;
std::queue<grpc::channelz::v1::Subchannel> subchannel_queue;
std::cout << "Tree depth = " << tree_depth << std::endl;
GetChannelDescedence(_topchannel, channel_queue, subchannel_queue);
while (!channel_queue.empty() || !subchannel_queue.empty()) {
++tree_depth;
std::cout << "Tree depth = " << tree_depth << std::endl;
int ch_q_size = channel_queue.size();
int subch_q_size = subchannel_queue.size();
for (int i = 0; i < ch_q_size; ++i) {
grpc::channelz::v1::Channel ch = channel_queue.front();
channel_queue.pop();
GetChannelDescedence(ch, channel_queue, subchannel_queue);
}
for (int i = 0; i < subch_q_size; ++i) {
grpc::channelz::v1::Subchannel subch = subchannel_queue.front();
subchannel_queue.pop();
GetSubchannelDescedence(subch, channel_queue, subchannel_queue);
}
}
std::cout << std::endl;
}
}
// dump data of all entities to stdout
void DumpStdout() {
std::string data_str;
for (const auto& _channel : all_channels_) {
std::cout << "channel ID" << GetChannelID(_channel) << "_"
<< GetChannelName(_channel) << " data:" << std::endl;
// TODO(mohanli): TextFormat::PrintToString records time as seconds and
// nanos. Need a more human readable way.
::google::protobuf::TextFormat::PrintToString(_channel.data(), &data_str);
printf("%s\n", data_str.c_str());
}
for (const auto& _subchannel : all_subchannels_) {
std::cout << "subchannel ID" << GetSubchannelID(_subchannel) << "_"
<< GetSubchannelName(_subchannel) << " data:" << std::endl;
::google::protobuf::TextFormat::PrintToString(_subchannel.data(),
&data_str);
printf("%s\n", data_str.c_str());
}
for (const auto& _server : all_servers_) {
std::cout << "server ID" << GetServerID(_server) << "_"
<< GetServerName(_server) << " data:" << std::endl;
::google::protobuf::TextFormat::PrintToString(_server.data(), &data_str);
printf("%s\n", data_str.c_str());
}
for (const auto& _socket : all_sockets_) {
std::cout << "socket ID" << GetSocketID(_socket) << "_"
<< GetSocketName(_socket) << " data:" << std::endl;
::google::protobuf::TextFormat::PrintToString(_socket.data(), &data_str);
printf("%s\n", data_str.c_str());
}
}
// Store a channel in Json
void StoreChannelInJson(const grpc::channelz::v1::Channel& channel) {
std::string id = grpc::to_string(GetChannelID(channel));
std::string type = "Channel";
std::string description;
::google::protobuf::TextFormat::PrintToString(channel.data(), &description);
grpc_core::Json description_json = grpc_core::Json(description);
StoreEntityInJson(id, type, description_json);
}
// Store a subchannel in Json
void StoreSubchannelInJson(const grpc::channelz::v1::Subchannel& subchannel) {
std::string id = grpc::to_string(GetSubchannelID(subchannel));
std::string type = "Subchannel";
std::string description;
::google::protobuf::TextFormat::PrintToString(subchannel.data(),
&description);
grpc_core::Json description_json = grpc_core::Json(description);
StoreEntityInJson(id, type, description_json);
}
// Store a server in Json
void StoreServerInJson(const grpc::channelz::v1::Server& server) {
std::string id = grpc::to_string(GetServerID(server));
std::string type = "Server";
std::string description;
::google::protobuf::TextFormat::PrintToString(server.data(), &description);
grpc_core::Json description_json = grpc_core::Json(description);
StoreEntityInJson(id, type, description_json);
}
// Store a socket in Json
void StoreSocketInJson(const grpc::channelz::v1::Socket& socket) {
std::string id = grpc::to_string(GetSocketID(socket));
std::string type = "Socket";
std::string description;
::google::protobuf::TextFormat::PrintToString(socket.data(), &description);
grpc_core::Json description_json = grpc_core::Json(description);
StoreEntityInJson(id, type, description_json);
}
// Store an entity in Json
void StoreEntityInJson(std::string& id, std::string& type,
const grpc_core::Json& description) {
std::string start, finish;
gpr_timespec ago = gpr_time_sub(
now_,
gpr_time_from_seconds(FLAGS_sampling_interval_seconds, GPR_TIMESPAN));
std::stringstream ss;
const time_t time_now = now_.tv_sec;
ss << std::put_time(std::localtime(&time_now), "%F %T");
finish = ss.str(); // example: "2019-02-01 12:12:18"
ss.str("");
const time_t time_ago = ago.tv_sec;
ss << std::put_time(std::localtime(&time_ago), "%F %T");
start = ss.str();
grpc_core::Json obj =
grpc_core::Json::Object{{"Task", absl::StrFormat("%s_ID%s", type, id)},
{"Start", start},
{"Finish", finish},
{"ID", id},
{"Type", type},
{"Description", description}};
json_.mutable_array()->push_back(obj);
}
// Dump data in json
std::string DumpJson() { return json_.Dump(); }
// Check if one entity has been recorded
bool CheckID(int64_t id) {
if (id_set_.count(id) == 0) {
id_set_.insert(id);
return true;
} else {
return false;
}
}
// Record current time
void RecordNow() { now_ = gpr_now(GPR_CLOCK_REALTIME); }
private:
std::unique_ptr<grpc::channelz::v1::Channelz::Stub> channelz_stub_;
std::vector<grpc::channelz::v1::Channel> top_channels_;
std::vector<grpc::channelz::v1::Server> all_servers_;
std::vector<grpc::channelz::v1::Channel> all_channels_;
std::vector<grpc::channelz::v1::Subchannel> all_subchannels_;
std::vector<grpc::channelz::v1::Socket> all_sockets_;
std::unordered_set<int64_t> id_set_;
grpc_core::Json json_;
int64_t rpc_timeout_seconds_;
gpr_timespec now_;
};
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
grpc::testing::InitTest(&argc, &argv, true);
std::ofstream output_file(FLAGS_output_json);
for (int i = 0; i < FLAGS_sampling_times; ++i) {
ChannelzSampler channelz_sampler;
channelz_sampler.Setup(FLAGS_custom_credentials_type, FLAGS_server_address);
std::cout << "Wait for sampling interval "
<< FLAGS_sampling_interval_seconds << "s..." << std::endl;
const gpr_timespec kDelay = gpr_time_add(
gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_seconds(FLAGS_sampling_interval_seconds, GPR_TIMESPAN));
gpr_sleep_until(kDelay);
std::cout << "##### " << i << "th sampling #####" << std::endl;
channelz_sampler.RecordNow();
channelz_sampler.GetServersRPC();
channelz_sampler.GetSocketsOfServers();
channelz_sampler.GetTopChannelsRPC();
channelz_sampler.TraverseTopChannels();
channelz_sampler.DumpStdout();
if (!FLAGS_output_json.empty()) {
output_file << channelz_sampler.DumpJson() << "\n" << std::flush;
}
}
output_file.close();
return 0;
}

@ -0,0 +1,176 @@
/*
*
* Copyright 2016 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include "grpc/grpc.h"
#include "grpc/support/alloc.h"
#include "grpc/support/port_platform.h"
#include "grpcpp/channel.h"
#include "grpcpp/client_context.h"
#include "grpcpp/create_channel.h"
#include "grpcpp/ext/channelz_service_plugin.h"
#include "grpcpp/grpcpp.h"
#include "grpcpp/security/credentials.h"
#include "grpcpp/security/server_credentials.h"
#include "grpcpp/server.h"
#include "grpcpp/server_builder.h"
#include "grpcpp/server_context.h"
#include "gtest/gtest.h"
#include "src/core/lib/gpr/env.h"
#include "src/cpp/server/channelz/channelz_service.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/subprocess.h"
#include "test/cpp/util/test_credentials_provider.h"
static std::string g_root;
namespace {
using grpc::ClientContext;
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
} // namespace
// Test variables
std::string server_address("0.0.0.0:10000");
std::string custom_credentials_type("INSECURE_CREDENTIALS");
std::string sampling_times = "2";
std::string sampling_interval_seconds = "3";
std::string output_json("output.json");
// Creata an echo server
class EchoServerImpl final : public grpc::testing::TestService::Service {
Status EmptyCall(::grpc::ServerContext* context,
const grpc::testing::Empty* request,
grpc::testing::Empty* response) {
return Status::OK;
}
};
// Run client in a thread
void RunClient(const std::string& client_id, gpr_event* done_ev) {
grpc::ChannelArguments channel_args;
std::shared_ptr<grpc::ChannelCredentials> channel_creds =
grpc::testing::GetCredentialsProvider()->GetChannelCredentials(
custom_credentials_type, &channel_args);
std::unique_ptr<grpc::testing::TestService::Stub> stub =
grpc::testing::TestService::NewStub(
grpc::CreateChannel(server_address, channel_creds));
gpr_log(GPR_INFO, "Client %s is echoing!", client_id.c_str());
while (true) {
if (gpr_event_wait(done_ev, grpc_timeout_seconds_to_deadline(1)) !=
nullptr) {
return;
}
grpc::testing::Empty request;
grpc::testing::Empty response;
ClientContext context;
Status status = stub->EmptyCall(&context, request, &response);
if (!status.ok()) {
gpr_log(GPR_ERROR, "Client echo failed.");
GPR_ASSERT(0);
}
}
}
// Create the channelz to test the connection to the server
bool WaitForConnection(int wait_server_seconds) {
grpc::ChannelArguments channel_args;
std::shared_ptr<grpc::ChannelCredentials> channel_creds =
grpc::testing::GetCredentialsProvider()->GetChannelCredentials(
custom_credentials_type, &channel_args);
auto channel = grpc::CreateChannel(server_address, channel_creds);
return channel->WaitForConnected(
grpc_timeout_seconds_to_deadline(wait_server_seconds));
}
// Test the channelz sampler
TEST(ChannelzSamplerTest, SimpleTest) {
// start server
::grpc::channelz::experimental::InitChannelzService();
EchoServerImpl service;
grpc::ServerBuilder builder;
auto server_creds =
grpc::testing::GetCredentialsProvider()->GetServerCredentials(
custom_credentials_type);
builder.AddListeningPort(server_address, server_creds);
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
gpr_log(GPR_INFO, "Server listening on %s", server_address.c_str());
const int kWaitForServerSeconds = 10;
ASSERT_TRUE(WaitForConnection(kWaitForServerSeconds));
// client threads
gpr_event done_ev1, done_ev2;
gpr_event_init(&done_ev1);
gpr_event_init(&done_ev2);
std::thread client_thread_1(RunClient, "1", &done_ev1);
std::thread client_thread_2(RunClient, "2", &done_ev2);
// Run the channelz sampler
grpc::SubProcess* test_driver = new grpc::SubProcess(
{g_root + "/channelz_sampler", "--server_address=" + server_address,
"--custom_credentials_type=" + custom_credentials_type,
"--sampling_times=" + sampling_times,
"--sampling_interval_seconds=" + sampling_interval_seconds,
"--output_json=" + output_json});
int status = test_driver->Join();
if (WIFEXITED(status)) {
if (WEXITSTATUS(status)) {
gpr_log(GPR_ERROR,
"Channelz sampler test test-runner exited with code %d",
WEXITSTATUS(status));
GPR_ASSERT(0); // log the line number of the assertion failure
}
} else if (WIFSIGNALED(status)) {
gpr_log(GPR_ERROR, "Channelz sampler test test-runner ended from signal %d",
WTERMSIG(status));
GPR_ASSERT(0);
} else {
gpr_log(GPR_ERROR,
"Channelz sampler test test-runner ended with unknown status %d",
status);
GPR_ASSERT(0);
}
delete test_driver;
gpr_event_set(&done_ev1, (void*)1);
gpr_event_set(&done_ev2, (void*)1);
client_thread_1.join();
client_thread_2.join();
}
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv);
std::string me = argv[0];
auto lslash = me.rfind('/');
if (lslash != std::string::npos) {
g_root = me.substr(0, lslash);
} else {
g_root = ".";
}
int ret = RUN_ALL_TESTS();
return ret;
}

@ -468,6 +468,12 @@ def _filter_cc_tests(tests):
lambda test: not test.startswith( lambda test: not test.startswith(
'test/core/tsi:ssl_session_cache_test'), tests)) 'test/core/tsi:ssl_session_cache_test'), tests))
# the binary of this test does not get built with cmake
tests = list(
filter(
lambda test: not test.startswith(
'test/cpp/util:channelz_sampler_test'), tests))
return tests return tests

@ -38,7 +38,8 @@ def main(command_arguments):
return _protoc_compiler.run_main(command_arguments) return _protoc_compiler.run_main(command_arguments)
if sys.version_info[0] > 2: # NOTE(rbellevi): importlib.abc is not supported on 3.4.
if sys.version_info >= (3, 5, 0):
import contextlib import contextlib
import importlib import importlib
import importlib.machinery import importlib.machinery

@ -1393,6 +1393,10 @@ src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \ src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \
src/core/ext/upb-generated/validate/validate.upb.c \ src/core/ext/upb-generated/validate/validate.upb.c \
src/core/ext/upb-generated/validate/validate.upb.h \ src/core/ext/upb-generated/validate/validate.upb.h \
src/core/ext/xds/certificate_provider_factory.h \
src/core/ext/xds/certificate_provider_registry.cc \
src/core/ext/xds/certificate_provider_registry.h \
src/core/ext/xds/certificate_provider_store.h \
src/core/ext/xds/xds_api.cc \ src/core/ext/xds/xds_api.cc \
src/core/ext/xds/xds_api.h \ src/core/ext/xds/xds_api.h \
src/core/ext/xds/xds_bootstrap.cc \ src/core/ext/xds/xds_bootstrap.cc \
@ -1757,6 +1761,8 @@ src/core/lib/security/credentials/plugin/plugin_credentials.cc \
src/core/lib/security/credentials/plugin/plugin_credentials.h \ src/core/lib/security/credentials/plugin/plugin_credentials.h \
src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \
src/core/lib/security/credentials/ssl/ssl_credentials.h \ src/core/lib/security/credentials/ssl/ssl_credentials.h \
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h \
src/core/lib/security/credentials/tls/tls_credentials.cc \ src/core/lib/security/credentials/tls/tls_credentials.cc \

@ -1217,6 +1217,10 @@ src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \ src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \
src/core/ext/upb-generated/validate/validate.upb.c \ src/core/ext/upb-generated/validate/validate.upb.c \
src/core/ext/upb-generated/validate/validate.upb.h \ src/core/ext/upb-generated/validate/validate.upb.h \
src/core/ext/xds/certificate_provider_factory.h \
src/core/ext/xds/certificate_provider_registry.cc \
src/core/ext/xds/certificate_provider_registry.h \
src/core/ext/xds/certificate_provider_store.h \
src/core/ext/xds/xds_api.cc \ src/core/ext/xds/xds_api.cc \
src/core/ext/xds/xds_api.h \ src/core/ext/xds/xds_api.h \
src/core/ext/xds/xds_bootstrap.cc \ src/core/ext/xds/xds_bootstrap.cc \
@ -1586,6 +1590,8 @@ src/core/lib/security/credentials/plugin/plugin_credentials.cc \
src/core/lib/security/credentials/plugin/plugin_credentials.h \ src/core/lib/security/credentials/plugin/plugin_credentials.h \
src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \
src/core/lib/security/credentials/ssl/ssl_credentials.h \ src/core/lib/security/credentials/ssl/ssl_credentials.h \
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h \
src/core/lib/security/credentials/tls/tls_credentials.cc \ src/core/lib/security/credentials/tls/tls_credentials.cc \

@ -17,7 +17,7 @@
# Location of the continuous shell script in repository. # Location of the continuous shell script in repository.
build_file: "grpc/tools/internal_ci/macos/grpc_build_artifacts.sh" build_file: "grpc/tools/internal_ci/macos/grpc_build_artifacts.sh"
gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0eeee2db331.json" gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0eeee2db331.json"
timeout_mins: 120 timeout_mins: 150
action { action {
define_artifacts { define_artifacts {
regex: "**/*sponge_log.*" regex: "**/*sponge_log.*"

@ -222,7 +222,7 @@ LANG_RELEASE_MATRIX = {
('v1.28.1', ReleaseInfo()), ('v1.28.1', ReleaseInfo()),
('v1.29.0', ReleaseInfo()), ('v1.29.0', ReleaseInfo()),
('v1.30.2', ReleaseInfo()), ('v1.30.2', ReleaseInfo()),
('v1.31.0', ReleaseInfo()), ('v1.31.1', ReleaseInfo()),
]), ]),
'python': 'python':
OrderedDict([ OrderedDict([

@ -1607,6 +1607,30 @@
], ],
"uses_polling": true "uses_polling": true
}, },
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "init_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{ {
"args": [], "args": [],
"benchmark": false, "benchmark": false,
@ -3857,6 +3881,30 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "certificate_provider_registry_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{ {
"args": [], "args": [],
"benchmark": false, "benchmark": false,
@ -4470,7 +4518,7 @@
"flaky": false, "flaky": false,
"gtest": true, "gtest": true,
"language": "c++", "language": "c++",
"name": "grpc_tls_credentials_options_test", "name": "grpc_tls_certificate_distributor_test",
"platforms": [ "platforms": [
"linux", "linux",
"mac", "mac",
@ -4485,7 +4533,8 @@
"ci_platforms": [ "ci_platforms": [
"linux", "linux",
"mac", "mac",
"posix" "posix",
"windows"
], ],
"cpu_cost": 1.0, "cpu_cost": 1.0,
"exclude_configs": [], "exclude_configs": [],
@ -4493,11 +4542,12 @@
"flaky": false, "flaky": false,
"gtest": true, "gtest": true,
"language": "c++", "language": "c++",
"name": "grpc_tool_test", "name": "grpc_tls_credentials_options_test",
"platforms": [ "platforms": [
"linux", "linux",
"mac", "mac",
"posix" "posix",
"windows"
], ],
"uses_polling": true "uses_polling": true
}, },
@ -4507,8 +4557,7 @@
"ci_platforms": [ "ci_platforms": [
"linux", "linux",
"mac", "mac",
"posix", "posix"
"windows"
], ],
"cpu_cost": 1.0, "cpu_cost": 1.0,
"exclude_configs": [], "exclude_configs": [],
@ -4516,12 +4565,11 @@
"flaky": false, "flaky": false,
"gtest": true, "gtest": true,
"language": "c++", "language": "c++",
"name": "grpclb_api_test", "name": "grpc_tool_test",
"platforms": [ "platforms": [
"linux", "linux",
"mac", "mac",
"posix", "posix"
"windows"
], ],
"uses_polling": true "uses_polling": true
}, },
@ -4540,7 +4588,7 @@
"flaky": false, "flaky": false,
"gtest": true, "gtest": true,
"language": "c++", "language": "c++",
"name": "h2_ssl_session_reuse_test", "name": "grpclb_api_test",
"platforms": [ "platforms": [
"linux", "linux",
"mac", "mac",
@ -4564,7 +4612,7 @@
"flaky": false, "flaky": false,
"gtest": true, "gtest": true,
"language": "c++", "language": "c++",
"name": "head_of_line_blocking_bad_client_test", "name": "h2_ssl_session_reuse_test",
"platforms": [ "platforms": [
"linux", "linux",
"mac", "mac",
@ -4588,7 +4636,7 @@
"flaky": false, "flaky": false,
"gtest": true, "gtest": true,
"language": "c++", "language": "c++",
"name": "headers_bad_client_test", "name": "head_of_line_blocking_bad_client_test",
"platforms": [ "platforms": [
"linux", "linux",
"mac", "mac",
@ -4612,7 +4660,7 @@
"flaky": false, "flaky": false,
"gtest": true, "gtest": true,
"language": "c++", "language": "c++",
"name": "health_service_end2end_test", "name": "headers_bad_client_test",
"platforms": [ "platforms": [
"linux", "linux",
"mac", "mac",
@ -4636,7 +4684,7 @@
"flaky": false, "flaky": false,
"gtest": true, "gtest": true,
"language": "c++", "language": "c++",
"name": "hybrid_end2end_test", "name": "health_service_end2end_test",
"platforms": [ "platforms": [
"linux", "linux",
"mac", "mac",
@ -4660,14 +4708,14 @@
"flaky": false, "flaky": false,
"gtest": true, "gtest": true,
"language": "c++", "language": "c++",
"name": "init_test", "name": "hybrid_end2end_test",
"platforms": [ "platforms": [
"linux", "linux",
"mac", "mac",
"posix", "posix",
"windows" "windows"
], ],
"uses_polling": false "uses_polling": true
}, },
{ {
"args": [], "args": [],

@ -20,7 +20,7 @@ cd "$(dirname "$0")/../../.."
sudo apt-get install -y python3-pip sudo apt-get install -y python3-pip
sudo python3 -m pip install --upgrade pip sudo python3 -m pip install --upgrade pip
sudo python3 -m pip install grpcio grpcio-tools google-api-python-client google-auth-httplib2 oauth2client sudo python3 -m pip install grpcio==1.31.0 grpcio-tools==1.31.0 google-api-python-client google-auth-httplib2 oauth2client
# Prepare generated Python code. # Prepare generated Python code.
TOOLS_DIR=tools/run_tests TOOLS_DIR=tools/run_tests

@ -25,7 +25,7 @@ import sys
import tempfile import tempfile
import time import time
# must be synchronized with test/core/utils/port_server_client.h # must be synchronized with test/core/util/port_server_client.h
_PORT_SERVER_PORT = 32766 _PORT_SERVER_PORT = 32766

@ -683,13 +683,6 @@ def prepare_services_for_urlmap_tests(gcp, original_backend_service,
Returns: Returns:
Returns original and alternate backend names as lists of strings. Returns original and alternate backend names as lists of strings.
''' '''
# The config validation for proxyless doesn't allow setting
# default_route_action or route_rules. Disable validate
# validate_for_proxyless for this test. This can be removed when validation
# accepts default_route_action.
logger.info('disabling validate_for_proxyless in target proxy')
set_validate_for_proxyless(gcp, False)
logger.info('waiting for original backends to become healthy') logger.info('waiting for original backends to become healthy')
wait_for_healthy_backends(gcp, original_backend_service, instance_group) wait_for_healthy_backends(gcp, original_backend_service, instance_group)
@ -784,7 +777,6 @@ def test_traffic_splitting(gcp, original_backend_service, instance_group,
finally: finally:
patch_url_map_backend_service(gcp, original_backend_service) patch_url_map_backend_service(gcp, original_backend_service)
patch_backend_instances(gcp, alternate_backend_service, []) patch_backend_instances(gcp, alternate_backend_service, [])
set_validate_for_proxyless(gcp, True)
def test_path_matching(gcp, original_backend_service, instance_group, def test_path_matching(gcp, original_backend_service, instance_group,
@ -892,7 +884,6 @@ def test_path_matching(gcp, original_backend_service, instance_group,
finally: finally:
patch_url_map_backend_service(gcp, original_backend_service) patch_url_map_backend_service(gcp, original_backend_service)
patch_backend_instances(gcp, alternate_backend_service, []) patch_backend_instances(gcp, alternate_backend_service, [])
set_validate_for_proxyless(gcp, True)
def test_header_matching(gcp, original_backend_service, instance_group, def test_header_matching(gcp, original_backend_service, instance_group,
@ -963,7 +954,6 @@ def test_header_matching(gcp, original_backend_service, instance_group,
finally: finally:
patch_url_map_backend_service(gcp, original_backend_service) patch_url_map_backend_service(gcp, original_backend_service)
patch_backend_instances(gcp, alternate_backend_service, []) patch_backend_instances(gcp, alternate_backend_service, [])
set_validate_for_proxyless(gcp, True)
def get_serving_status(instance, service_port): def get_serving_status(instance, service_port):
@ -1194,27 +1184,12 @@ def patch_url_map_host_rule_with_port(gcp, name, backend_service, host_name):
wait_for_global_operation(gcp, result['name']) wait_for_global_operation(gcp, result['name'])
def set_validate_for_proxyless(gcp, validate_for_proxyless): def create_target_proxy(gcp, name):
if not gcp.alpha_compute:
logger.debug(
'Not setting validateForProxy because alpha is not enabled')
return
# This function deletes global_forwarding_rule and target_proxy, then
# recreate target_proxy with validateForProxyless=False. This is necessary
# because patching target_grpc_proxy isn't supported.
delete_global_forwarding_rule(gcp)
delete_target_proxy(gcp)
create_target_proxy(gcp, gcp.target_proxy.name, validate_for_proxyless)
create_global_forwarding_rule(gcp, gcp.global_forwarding_rule.name,
[gcp.service_port])
def create_target_proxy(gcp, name, validate_for_proxyless=True):
if gcp.alpha_compute: if gcp.alpha_compute:
config = { config = {
'name': name, 'name': name,
'url_map': gcp.url_map.url, 'url_map': gcp.url_map.url,
'validate_for_proxyless': validate_for_proxyless, 'validate_for_proxyless': True,
} }
logger.debug('Sending GCP request with body=%s', config) logger.debug('Sending GCP request with body=%s', config)
result = gcp.alpha_compute.targetGrpcProxies().insert( result = gcp.alpha_compute.targetGrpcProxies().insert(

Loading…
Cancel
Save